1.掌握基于SpringMVC获取请求参数与响应json数据操作 2.熟练应用基于REST风格的请求路径设置与参数传递 3.能够根据实际业务建立前后端开发通信协议并进行实现 4.基于SSM整合技术开发任意业务模块功能 5.能够理解并实现统一结果封装与统一异常处理 6.能够完成前后台功能整合开发 7.掌握拦截器的编写
Web工作流程:通过浏览器访问页面,通过异步提交的方式访问后端,后端通过三层架构的形式进行开发,最后返回json格式给前端,前端解析数据并交给浏览器
SpringMVC是一种基于Java实现MVC模型的轻量级Web框架,用于表现层功能开发
优点:灵活性强、较Servlet来说使用简单、开发便捷
原始版
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
}优化版
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
//加载Spring配置类
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
//加载SpringMVC配置类
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
//设置SpringMVC请求地址拦截规则
protected String[] getServletMappings() {
return new String[]{"/"};
}
//设置post请求中文乱码过滤器
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
return new Filter[]{filter};
}
}
SpringMvcConfig来初始化SpringMVC的容器(此时创建了WebApplicationContext对象)SpringMvcConfig配置类@ComponentScan对应的bean,扫描了指定包及以下类中的注解@RequestMapping的对应方法http://localhost/save由于SpringMVC负责加载Controller层,为了防止Spring扫描控制层,我们可以有以下方法解决
1.设置扫描范围
将扫描范围定位精准范围即可
@Configuration
@ComponentScan({"com.Coolipa.service","com.Coolipa.dao"})
public class SpringConfig {
}2.排除bean
通过excludeFilters进行过滤
@Configuration
@ComponentScan(value="com.itheima",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}只需要知道第一种ANNOTATION即可,其他作为了解
这里着重强调REST风格的请求与响应,其他作为了解
通过规范开发,避免每人设置不同的请求路径从而冲突
通过设置模块名作为请求路径前缀,从而避免冲突。
示例:
@Controller
public class UserController {
//设置访问路径
@RequestMapping("/user/save")
//设置返回值类型
@ResponseBody
public String save(){
System.out.println("user save");
return "{'module':'springmvc'}";
}
//设置访问路径
@RequestMapping("/user/insert")
//设置返回值类型
@ResponseBody
public String insert(){
System.out.println("user insert");
return "{'module':'springmvc'}";
}
}注意:
@RequestMapping注解,前端发送请求的时候,要和两个注解的value值相加匹配才能访问到。/都可以Get请求传参
普通参数:url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数(使用Params)

Post请求参数
普通参数:form表单post请求传参,表单参数名与形参变量名相同,定义传参即可接收参数(使用Body的x-www-form-urlencoded)

这里分为普通参数、POJO参数、数组类型参数、集合类型参数四种。
普通参数
若请求参数名与形参变量名不同,使用@RequestParam绑定参数关系
@RequestMapping("/commonParam")
@ResponseBody
public String commonParamDifferentName(@RequestParam("name") String userName , int age){
// ......
return .....;
}
POJO参数
请求参数名与形参对象属性名相同,定义POJO类型形参就能接收参数,若为嵌套类型(POJO嵌入其他POJO),使用.即可
public class User {
private String name;
private int age;
private Address address;
//get和set方法...
}//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
//......
return .....;
}
数组类型参数
请求参数名与形参对象属性名相同且为多个,定义数组类型形参即可接收参数
//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
//.....
return ...;
}
集合类型参数
由于SpringMVC会默认把List看错POJO对象,从而导致把前端数据封装到对象中,因此会导致报错,所以使用
@RequestParam注解
请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
//...
return ...;
}使用条件:引入 Jackson(例如 jackson-databind),并确保注册了 MappingJackson2HttpMessageConverter。非 Spring Boot 环境可通过 @EnableWebMvc 或 XML 启用 MVC 以激活消息转换;在 Spring Boot 中无需 @EnableWebMvc。
对于JSON数据类型,我们常见的有三种:
JSON普通数组
使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("list common(json)参数传递 list ==> "+likes);
return "{'module':'list common for json param'}";
}
JSON对象数据
json数据与形参对象数据名相同,定义POJO类型形参即可接收参数,若是由嵌套POJO类型,在JSON也嵌套即可
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
System.out.println("pojo(json)参数传递 user ==> "+user);
return "{'module':'pojo for json param'}";
}
JSON对象数组
json数组数据与集合泛型属性名相同,定义List类型形参即可接收参数
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("list pojo(json)参数传递 list ==> "+list);
return "{'module':'list pojo for json param'}";
}
在SpringMVC默认支持的字符串转日期的格式为yyyy/MM/dd,如果格式不同,需要使用@DateTimeFormat。
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2) {
System.out.println("参数传递 date ==> "+date);
System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);
System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
return "{'module':'data param'}";
}拓展:内部实现原理
SpringMVC提供了许多类型转换接口和实现类,例如Converter
public interface Converter<S, T> {
@Nullable
//该方法就是将从页面上接收的数据(S)转换成我们想要的数据类型(T)返回
T convert(S source);
}
REST(Representational State Transfer) 表现形式状态转换,是一种软件架构风格
传统风格与REST风格对比
http://localhost/user/getById?id=1 查询id为1的用户信息http://localhost/user/saveUser 保存用户信息http://localhost/user/1http://localhost/user优点:隐藏资源访问行为,书写简化
拓充:按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
具体实例:
http://localhost/users 查询全部用户信息 GET(查询)http://localhost/users/1 查询指定用户信息 GET(查询)http://localhost/users 添加用户信息 POST(新增/保存)http://localhost/users 修改用户信息 PUT(修改/更新)http://localhost/users/1 删除用户信息 DELETE(删除)原始使用
以http://localhost/users/1为例
@Controller
@RequestMapping("/users")
public class UserController {
//设置当前请求方法为DELETE,表示REST风格中的删除操作
@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
}简便使用
@RestController
@RequestMapping("/books")
public class BookController{
@Autowired
private BookService bookService;
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("book getById"+id);
return "{'module':'book getById'}";
}
}拦截器( Interceptor ) 是一种控制方法前后执行代码的工作机制,底层是AOP。
作用:
需要写拦截器接口
@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {
@Override
//原始方法调用前执行的内容
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return true;
}
@Override
//原始方法调用后执行的内容
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
@Override
//原始方法调用完成后执行的内容
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}此处需要被SpringMVC扫到,且需要在单独写SpringMvcSupport类。注意:继承 WebMvcConfigurationSupport 会禁用默认MVC配置,通常更推荐仅实现 WebMvcConfigurer。
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//配置拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books/**");
}
}@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//配置多拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books/**");
}
}前置处理
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}参数:
返回值:
后置处理
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...")
}参数:
不需要使用,了解即可
完成后处理
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion")
}可以通过SpringMVC的异常处理机制替换
实现接口,并重写接口中的方法
@Component
public class ProjectInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...222");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...222");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...222");
}
}@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Autowired
private ProjectInterceptor2 projectInterceptor2;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//配置多拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books/**");
registry.addInterceptor(projectInterceptor2).addPathPatterns("/books/**");
}
}与栈相同,先进后出,后进先出
如果这篇文章对你有帮助,希望可以给一个推荐,收藏和评论