目录
一.拦截器
拦截器是Spring框架提供的核功能之,主要来拦截的请求,在指定法前后,根据业务需要执预先设定的代码。
也就是说,允许开发员提前预定义些逻辑,在的请求响应前后执,也可以在请求前阻其执。
在拦截器当中,开发员可以在应程序中做些通性的操作,如通过拦截器来拦截前端发来的请求,判断Session中是否有登录的信息,如果有就可以放,如果没有就进拦截。
添加拦截器后,在原先逻辑之前会先判断是否拦截
使用拦截器需要分为俩步骤:
- 自定义拦截器
- 配置拦截器
定义拦截器:需实现HandlerInterceptor接,并重写其法
public interface HandlerInterceptor {
//?标?法执?前执?,返回值表示是否拦截
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
//?标?法执?后执?
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
//视图渲染完毕后执?
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
- preHandle()法:标法执前执,返回true:继续执后续操作;返回false:中断后续操作.
- postHandle()法:标法执后执
- afterCompletion()法:视图渲染完毕后执,最后执(但是现在基于前后端分离的设计模式,一般不需要后端返回视图,故而很少用)
添加拦截器后,执Controller的法之前,请求会先被拦截器拦截住执 preHandle() 法,这个法需要返回个布尔类型的值:如果返回true,就表放本次操作并且继续访问controller中的法;如果返回false,则不会放(controller中的法也不会执)。controller当中的法执完毕后,再回过来执 postHandle() 这个法以及afterCompletion() 法,执完毕之后,最终给浏览器响应数据。
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("LoginInterceptor ?标?法执?前执?..");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("LoginInterceptor ?标?法执?后执?");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("LoginInterceptor 视图渲染完毕后执?,最后执?");
}
}
自定义完成拦截器后,我们还需要将其使用起来,也就是进行相关配置
首先是要实现WebMvcConfigurer接口,为了将我们刚才自定义的拦截器进行注册,我们需要一个拦截器对象,通过依赖注入的方式注入其中。InterceptorRegistry表示拦截器注册类,我们通过该类的addInterceptor方法将注入的拦截器对象提交并且注册,通过addPathPatterns方法配置我们需要拦截的路径
@Configuration
public class WebConfig implements WebMvcConfigurer {
//?定义的拦截器对象
@Autowired
private LoginInterceptor loginInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
//注册?定义拦截器对象
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表?拦截所有请求)
}
}
我们在注册配置拦截器的时候,通过 addPathPatterns() 法指定要拦截哪些请求,也可以通过excludePathPatterns() 指定不拦截哪些请求。
@Configuration
public class WebConfig implements WebMvcConfigurer {
//?定义的拦截器对象
@Autowired
private LoginInterceptor loginInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器对象
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/user/login");
}
}
对于拦截路径,有以下需要注意
拦截路径
含义
举例
/*
一级路径
能匹配/user,/book,/login,不能匹配 /user/login
/**
任意级路径
能匹配/user,/book,/login,/user/login
对于一些比较复杂比较多的路径,可以将其封装到一个集合中再统一导入,即下面俩者的效果是一样的。
@Configuration
public class WebConfig implements WebMvcConfigurer {
//?定义的拦截器对象
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册?定义拦截器对象
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/user/login")
.excludePathPatterns("/**/*.js")
.excludePathPatterns("/**/*.css")
.excludePathPatterns("/**/*.png")
.excludePathPatterns("/**/*.html");
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
//?定义的拦截器对象
@Autowired
private LoginInterceptor loginInterceptor;
private List<String> excludePaths = Arrays.asList(
"/user/login",
"/**/*.js",
"/**/*.css",
"/**/*.png",
"/**/*.html"
);
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册?定义拦截器对象
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludePaths);
}
}
二.统一数据返回格式
统的数据返回格式使 @ControllerAdvice 和 ResponseBodyAdvice 的式实现,@ControllerAdvice 表控制器通知类
添加类 ResponseAdvice,实现 ResponseBodyAdvice 接,并在类上添加@ControllerAdvice 注解,示例如下:
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return false;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
return null;
}
}
supports法:判断是否要执beforeBodyWrite法,true为执,false不执。通过该法可以选择哪些类或哪些法的response要进处理,其他的不进处理。
beforeBodyWrite法:对response法进具体操作处理。
三.统一异常处理
统异常处理使的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表控制器通知类,@ExceptionHandler 是异常处理器,两个结合表当出现异常的时候执某个通知,也就是执某个法事件。
示例代码如下:
@ControllerAdvice
public class ErrorAdvice {
@ExceptionHandler
public Object handler(Exception e) {
return Result.fail(e.getMessage());
}
}
以上代码表,如果代码出现Exception异常(包括Exception的类),就返回个 Result的对象。
我们可以针对不同的异常,返回不同的结果。
@ControllerAdvice
public class ErrorAdvice {
@ExceptionHandler
public Object handler(Exception e) {
return Result.fail(e.getMessage());
}
@ExceptionHandler
public Object handler(NullPointerException e) {
return Result.fail("发?NullPointerException:"+e.getMessage());
}
@ExceptionHandler
public Object handler(ArithmeticException e) {
return Result.fail("发?ArithmeticException:"+e.getMessage());
}
}
当有多个异常通知时,匹配顺序为当前类及其类向上依次匹配。
本次的分享就到此为止了,希望我的分享能给您带来帮助,创作不易也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!
如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!
有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见