文章目录
-
- [配置类 SpringMvcInit](#配置类 SpringMvcInit)
- [配置类 MvcConfig](#配置类 MvcConfig)
-
- 全局异常处理器
- User实体类 (参数校验)
- UserController
- [拦截器 MyInterceptor](#拦截器 MyInterceptor)
- [拦截器 MyInterceptor1](#拦截器 MyInterceptor1)

配置类 SpringMvcInit
java
package com.cool.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
"可以被 web项目加载,会初始化ioc容器,会设置 dispatcherServlet的地址"
public class SpringMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
"设置配置类"
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MvcConfig.class};
}
"配置springmvc内部自带servlet的访问地址"
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
配置类 MvcConfig
java
package com.cool.config;
import com.cool.interceptor.MyInterceptor;
import com.cool.interceptor.MyInterceptor1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
@Configuration
@ComponentScan({"com.cool.controller", "com.cool.error"})
public class MvcConfig implements WebMvcConfigurer {
/*
通过configurer.enable()启用默认Servlet处理。
当请求无法匹配到Spring的控制器时,会回退到Servlet容器的默认Servlet(如:Tomcat的DefaultServlet),
主要用于,处理静态资源(如HTML、JS、CSS)。
典型场景:
配置后,对 /static/** 的请求会先由Spring处理,未匹配则交给容器默认Servlet
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 配置方案-1:拦截全部请求
registry.addInterceptor(new MyInterceptor());
// 配置方案-2:拦截指定的请求
// *:任意一层字符串;**:任意多层字符串
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/user/**"); // 拦截 user/ 下的所有请求
// 配置方案-3:排除拦截
// 拦截 user/ 下除了 /user/data1 之外的请求地址
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/user/**")
.excludePathPatterns("/user/data1");
// 如果有多个拦截器,执行流程是怎样的呢?
/*
先声明的优先级高,优先级高的在外层,
MyInterceptor.preHandle
MyInterceptor1.preHandle
OrderController.data
MyInterceptor1.postHandle
MyInterceptor.postHandle
MyInterceptor1.afterCompletion
MyInterceptor.afterCompletion
*/
registry.addInterceptor(new MyInterceptor());
registry.addInterceptor(new MyInterceptor1());
}
}
全局异常处理器
全局异常处理器 GlobalException 使用了 @RestControllerAdvice,
处理 ArithmeticException 和 Exception。
当 Controller 中的方法抛出这些异常时,会被对应的 @ExceptionHandler 方法捕获并处理。
java
package com.cool.error;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*
* @ControllerAdvice
* 作用:全局异常发生,就会走此类的方法,可以返回 逻辑视图、转发、重定向
*
* @RestControllerAdvice
* 相当于 @ControllerAdvice 和 @ResponseBody 的组合,
* 可以直接返回 json 字符串
*
*/
@RestControllerAdvice
public class GlobalException {
/*
发生异常后 -> ControllerAdvice注解的类型 -> @ExceptionHandler(指定的异常) -> 执行handler
如果,没有找到指定的异常,就会找父类Exception
*/
"精准匹配算术异常"
@ExceptionHandler(ArithmeticException.class)
public Object ArithmeticExceptionHandler(ArithmeticException e){
// 自定义异常处理即可
String message = e.getMessage();
System.out.println("ArithmeticExceptionHandler=" + message);
return message;
}
"兜底所有异常"
@ExceptionHandler(Exception.class)
public Object ExceptionHandler(Exception e){
String message = e.getMessage();
System.out.println("ExceptionHandler=" + message);
return message;
}
}
User实体类 (参数校验)
java
package com.cool.pojo;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Past;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import java.util.Date;
/**
* name:不为null、不为空字符串
* 字符串不为空:@NotBlank
* 集合不为空:@NotEmpty
* 包装类型不为空:@NotNull
*
* password:长度大于6
*/
@Data
public class User {
@NotBlank
private String name;
@Length(min = 6, max = 20)
private String password;
@Min(1)
private int age;
@Email
private String email;
@Past
private Date birthday;
}
UserController
java
package com.cool.controller;
import com.cool.pojo.User;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("user")
public class UserController {
/**
* 步骤1:实体类属性添加校验注解
* 步骤2:handler(@Validated 实体类对象){}
* 细节:
* param、json 校验注解都有效果
* 只不过,json参数的话,需要用 @RequestBody 修饰形参哦!
*
* 这里有个天坑:如果不符合校验规则,会直接向前端抛出异常
* 解决办法:
* handler(@Validated 实体类对象, BindingResult request){}
* 多加一个 BindingResult request 参数,
* 此参数,必须紧挨着 @Validated 实体类对象,否则此参数不管用
*/
@PostMapping("register")
public Object register(@Validated @RequestBody User user, BindingResult result){
System.out.println("user= " + user);
if(result.hasErrors()){
// 有错误的话,就不直接返回给前端了,可以在这里自定义内容,返回给前端
Map data = new HashMap();
data.put("code", 400);
data.put("msg", "参数校验异常");
return data;
}
return user;
}
@GetMapping("data")
public String data(){
// 这个方法,做成,空指针异常
String name = null;
name.toString(); // NullPointerException,报错后,就不会执行下面的代码了,就会取异常处理那里
return "data - ok";
}
@GetMapping("data1")
public String data1(){
// 这个方法,做成,算数异常
int i = 1/0; // ArithmeticException: / by zero
return "data1 - ok";
}
}
拦截器 MyInterceptor
java
package com.cool.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* 声明好这个类之后,
* 需要在 MvcConfig 类中注册上
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* handler执行之前触发
* @param request 请求对象
* @param response 响应对象
* @param handler 就是我们要调用的方法对象
* @return true:放行,false:拦截
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("request= " + request + ",response= " + response + ",handler = " + handler);
System.out.println("MyInterceptor.preHandle");
return true;
}
/**
* 当 handler 执行完毕后,触发此方法,没有拦截机制了
* 此方法只有在 preHandle方法 return true 的时候才会被执行
* @param request
* @param response
* @param handler
* @param modelAndView 返回的视图和共享域的数据对象,如果没有的话,返回null
* @throws Exception
*
* 对 响应结果 的处理
*
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor.postHandle");
}
/**
* 整体处理完毕后,会触发这个方法
* @param request
* @param response
* @param handler
* @param ex 如果 handler方法报错了,这个参数就是异常对象
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor.afterCompletion");
}
}
拦截器 MyInterceptor1
java
package com.cool.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* 声明好这个类之后,
* 需要在 MvcConfig 类中注册上
*/
public class MyInterceptor1 implements HandlerInterceptor {
/**
* handler执行之前触发
* @param request 请求对象
* @param response 响应对象
* @param handler 就是我们要调用的方法对象
* @return true:放行,false:拦截
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1.preHandle");
return true;
}
/**
* 当 handler 执行完毕后,触发此方法,没有拦截机制了
* 此方法只有在 preHandle方法 return true 的时候才会被执行
* @param request
* @param response
* @param handler
* @param modelAndView 返回的视图和共享域的数据对象,如果没有的话,返回null
* @throws Exception
*
* 对 响应结果 的处理
*
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1.postHandle");
}
/**
* 整体处理完毕后,会触发这个方法
* @param request
* @param response
* @param handler
* @param ex 如果 handler方法报错了,这个参数就是异常对象
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1.afterCompletion");
}
}