SpringMvc快速入门
概述
SpringMVC是一种基于]ava实现MVC模型的轻量级Web框架
优点
-
使用简单,开发便捷(相比于Servlet)
-
灵活性强

入门案例
-
使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标
<!--SpringMVC--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> -
创建SpringMVC控制器类(等同于Servlet功能)
@Controller public class UserController { @RequestMapping("/save") @ResponseBody public String save(){ System.out.println("user save ...") ; return "{'info':springmvc'}"; } } -
初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
@Configuration @ComponentScan("com.itheima") public class SpringMvcConfig { } -
初始化Servlet:容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer { // 将Spring注册到Tomcat服务器 protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx new = AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; } // 拦截所有请求到Spring protected String[] getServletMappings() { return new String[]{"/"}; } protected WebApplicationContext createRootApplicationContext() { return null; } }进阶版:
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { // 加载spring容器配置 @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } // 加载springMVC容器配置 @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; } // 设置哪些请求归属springMVC处理 @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
请求
GET 和 POST
- SpringMVC中
GET和POST请求在同一个方法中,不像servlet一样分为两个方法 - 接受参数直接写在方法的参数里面
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(String name) {
System.out.println("user save..." + name);
return "{'module':"+name+"}";
}
}
POST乱码处理
在ServletContainersInitConfig里面写了如下的:
// POST乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
URL请求 @RequestParam
请求的参数与实际的形参名字不相同,可以用@RequestParam注解
@RequestMapping("/save")
@ResponseBody
public String save(@RequestParam("name") String userName) {
System.out.println("user save..." + userName);
return "{'module':"+userName+"}";
}
JSON请求 @RequestBody

-
导入Json坐标
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> -
在
SpringMvcConfig添加功能 @EnableWebMvc@Configuration @ComponentScan("com.itheima.controller") @EnableWebMvc public class SpringMvcConfig { } -
在ApiFox发送Body带Json数据的请求
{ "name":"baozi", "age":18, "address":{ "province":"Guangdong", "city":"Shantou" } } -
请求参数加上
@RequestBody@RequestMapping("/Json") @ResponseBody public String ParamForJson(@RequestBody User user) { System.out.println("user save..." + user); return "{'module':'JsonOK'}"; }
还可以接收数组哦!
@RequestMapping("/JsonList")
@ResponseBody
public String ParamForJsonList(@RequestBody List<User> users) {
System.out.println("users save..." + users);
return "{'module':'JsonOK'}";
}
{
{"name":"baozi","age":18},{"name":"runrun","age":18}
}
@RequestParam 和 @RequestBody 区别
-
区别
-
@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】 -
@RequestBody用于接收json数据【application/json】
-
-
应用
-
后期开发中,发送json格式数据为主,
@RequestBody应用较广 -
如果发送非json格式数据,选用
@RequestParam接收请求参数
-
日期类型参数处理

-
日期类型数据基于系统不同格式也不尽相同
- 2088-08-18
- 2088/08/18
- 08/18/2088
-
接收形参时,根据不同的日期格式设置不同的接收方式
@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.printIn("参数传递date(yyyy-MM-dd)=>"+date1); System.out.println("参数传递date(yyyy/MM/ddHH:mm:ss)=>"+date2); return "{'module':'data param'}"; }此时的URL:
http://1oca1host/dataParam?date=2088/88/08&date1=2088-08-18&date2=2088/08/28 8:08:08
响应

返回pojo对象数据

返回List数据

REST风格
简介


实现区分行为动作的功能需要用到@RequestMapping

入门案例
主要就两个点:
- 设定http请求动作
method - 设定请求参数(路径变量:
@PathVariable)


形参注解 @PathVariable

快速开发
- 俩注解合二为一

- Mapping快速写

三种接受参数的区别

前端显示目录放行
因为我们用SpringMvc拦截了所有路径的请求,会导致放在webApp的前端页面无法被请求到
所以需要定义一个放行类来放行对应的目录(白学!后续可以一起定义在SpringMvcConfig里面)
-
定义该放行类,在
Confing包下@Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { // 映射路径/pages/**到/pages目录下 registry.addResourceHandler("/pages/**"). addResourceLocations("/pages/"); // 以下同理 registry.addResourceHandler("/css/**"). addResourceLocations("/css/"); registry.addResourceHandler("/js/**"). addResourceLocations("/js/"); registry.addResourceHandler("/plugins/**"). addResourceLocations("/plugins/"); } } -
别忘了在
SpringMvc扫描上面的配置类@Configuration @ComponentScan({"com.itheima.controller", "com.itheima.config"}) @EnableWebMvc public class SpringMvcConfig { }
表现层与前端协议
就是与前端约定一种返回数据的格式,懂的都懂,我就不细说了
异常处理
程序运行时有时候不可避免会出现异常,出现异常现象的常见位置与常见诱因如下:
-
框架内部抛出的异常:因使用不合规导致
-
数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
-
业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
-
表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
-
工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
异常处理器
Spring给我们定义了异常处理器,方便我们集中的、统一的处理项目中出现的异常
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
return new Result(666,null);
}
}
-
@RestControllerAdvice作用:用于声明该类是异常处理器类,前面加的
Rest说明是用REST风格位置:专用于异常处理类上方
-
@ExceptionHandler作用:设置指定异常的处理方案,功能等同于控制器(
Controller)方法,出现异常后终止原始控制器执行,并转入当前方法执行位置:专用于异常处理的控制器方法上方
说明:此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常
异常处理方案
- 业务异常(BusinessException)
- 发送对应消息传递给用户,提醒规范操作
- 系统异常(SystemException)
- 发送固定消息传递给用户安抚用户
- 发送特定消息给运维人员,提醒维护
- 记录日志
- 其他异常(Exception)
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给编程人员,提醒维护(纳入预期范围内)
- 记录日志
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException ex) {
System.out.println("处理系统异常!");
//1. 记录日志
//2. 发送消息给运维
//3. 发送消息(ex对象)给开发人员
return new Result(ex.getCode(), ex.getMessage(), null); //4. 返回给前端
}
@ExceptionHandler(BusinessException.class)
public Result doBusinessException(BusinessException ex) {
System.out.println("处理业务异常!");
//可以不记录日志
//这类异常不需要发送消息提醒
return new Result(ex.getCode(), ex.getMessage(), null); // 返回给前端
}
// 不能省略,用于处理其他异常
@ExceptionHandler(Exception.class)
public Result doException(Exception ex) {
System.out.println("处理其他异常!");
//1. 记录日志
//2. 发送消息给运维
//3. 发送消息(ex对象)给开发人员
return new Result(Code.SYSTEM_UNKNOW_ERR, "系统繁忙", null); //4. 返回给前端
}
}
异常处理编写步骤
-
自定义(系统级|业务级|...)异常

-
自定义异常编码(持续补充)

-
将可能出现异常的地方进行包装(可以使用AOP快速开发)

-
拦截并处理异常

拦截器
概念
官方:拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
人话:拦截器是在进入Spring框架主体的 前面 与 出去之后 做的行为

作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
拦截器与过滤器区别
归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
入门案例
-
声明拦截器的bean,并实现HandlerInterceptor接口(注意:扫描加载bean)
路径:
/controller/interceptor@Component public class ProjectInterceptor implements HandlerInterceptor { @Override public boolean preHandle(...) throws Exception { System.out.println("preHandle..."); // 这里返回false后面直接不执行,结束 return true; } @Override public void postHandle(...) throws Exception { System.out.println("postHandle..."); } @Override public void afterCompletion(...) throws Exception { System.out.println("afterCompletion..."); } } -
定义配置类,继承WebMvcConfigurationSupport,实现addInterceptor方法(注意:扫描加载配置)
路径:
/Config@Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Autowired private ProjectInterceptor projectInterceptor; // 过滤访问路径的静态资源 @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { ... } // 配置类 @Override protected void addInterceptors(InterceptorRegistry registry) { // 添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个 registry.addInterceptor(projectInterceptor) .addPathPatterns("/books", "/books/*"); } }
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
}
}
执行顺序
preHandle
-
return true
- controller
- postHandle
- afterCompletion
-
return false
- 结束
拦截器链
由多个拦截器组成的叫做拦截器链
