我们的统一功能处理肯定是通过Spring拦截器处理的撒
截器的实现分为以下两个步骤:
1. 创建⾃定义拦截器,实现 HandlerInterceptor 接⼝的 preHandle(执⾏具体⽅法之前的预处理)⽅ 法。
2. 将⾃定义拦截器加⼊ WebMvcConfigurer 的 addInterceptors ⽅法中。
统一登录处理
假如说我们在用一个网站的时候 无论你打开哪个分页 只要登录状态失效 就会让你重新登录 这种功能我们总不能在每个分页里面都放一个登录操作 麻烦死 所以我们就使用Spring拦截器来 统一登录处理
1.自定义拦截器
import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletRespon se response, Object handler) throws Exception { HttpSession session = request.getSession(false); if (session != null && session.getAttribute("userinfo") != null) { return true; } response.setStatus(401); return false; } }
preHandle的重写没啥好说的 就这么约定的
然后去获取请求中的session
这里提一嘴request.getsession的三种参数
1.无参数 从当前request中获取session 如果获取不到session 则会自动创建一个session,并返回新创建的session,如果获取到 就返回获取到的session
2.true 大体和无参时一致
3.false 在获取不到session时不会自动创建session 而是会返回null
这里登录的逻辑是 如果有session就不需要登录了没session再登录 这要是你再返回个新创建的session 那就坏了
关于返回 true就是表示可以通过(还会被其他的拦截器验证) false就是拦截(就死这儿了 其他拦截器也甭尝试了)
将⾃定义拦截器加⼊到系统配置
@Configuration public class AppConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/wuhu"); } }
@Configuration注解 标注这个是组件(别管 反正就是规定)
在registry.addInterceptor这里 添加我们之前自定义的拦截器 也可以不选择new的方式,进行属性注入也可
addPathPatterns 表示需要拦截的 URL,“**”表示拦截所有方法。
excludePathPatterns 表示需要排除的 URL。
也就是说实际的拦截范围是 所有URL减去 /wuhu 的部分
统一异常处理
我们在编写代码的时候 老会提示 哎呀 这个异常要处理 那个异常要处理 本来挺精简个代码的 trycatch一包围 一下子可读性就降低了 你说不处理吧 还不能运行 处理吧还不好看
所以我们就使用这个 统一异常处理
import java.util.HashMap; @ControllerAdvice public class ErrorAdive { @ExceptionHandler(Exception.class) @ResponseBody public Object handler(Exception e) { HashMap
map = new HashMap<>(); map.put("state", 0); map.put("data", null); map.put("msg", e.getMessage()); return map; } } 统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表 示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知 这个统一异常处理一步就可以 不需要再把它加入系统配置中了
@ExceptionHandler(Exception.class) 这个参数表示异常的类
public Object handler(Exception e) 这个参数表示要拦截的异常然后我们直接自定义一个hashmap把想返回的数据都放在一起 一起返回
我们在开发过程中 写了很多方法 前端一看 好家伙一坨数据 这啷个看的懂 就追着后端(很可能是你)
那基本没好了 八十个返回 跟你 沟流八十来次 所以为了防止这种情况的发生 直接统一数据返回格式 就讲一次就行(当然你要是暗恋前端那就另说了)
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyA
dvice;
import java.util.HashMap;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
/**
* 内容是否需要重写(通过此⽅法可以选择性部分控制器和⽅法进⾏重写)
* 返回 true 表示重写
*/
@Override
public boolean supports(MethodParameter returnType, Class converterTyp
e) {
return true;
}
/**
* ⽅法返回之前调⽤此⽅法
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType,
Class selectedConverterType, ServerHttpR
equest request,
ServerHttpResponse response) {
// 构造统⼀返回对象
HashMap result = new HashMap<>();
result.put("state", 1);
result.put("msg", "");
result.put("data", body);
return result;
}
}
真没啥说的
HashMap
result.put("state", 1);
result.put("msg", "");
result.put("data", body);
return result;
除了这块以外都是约定 就要求这么写
这块和上面一样 就是把数据统一收集在HashMap中 然后一起返回