Spring 中提供了具体的实现拦截器:HandlerInterceptor,拦截器的实现分为以下两个步骤:
接下来使⽤代码来实现⼀个⽤户登录的权限效验,⾃定义拦截器是⼀个普通类,分为两步:
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("userinfo") != null) {
return true; // 返回为真就通过, 反之就拦截
}
response.sendRedirect("/login.html");
return false;
}
}
然后就是将自定义的拦截器配置到系统当中:
总共分为三步:
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")// 拦截所有请求
.excludePathPatterns("/**/*.html")// 放开不需要拦截的部分
.excludePathPatterns("/user/login")
.excludePathPatterns("/user/reg");
}
}
统⼀访问前缀添加
所有请求地址添加 api 前缀, 有两种方式:
@Configuration
public class AppConfig implements WebMvcConfigurer {
// 所有的接⼝添加 api 前缀
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/api", c -> true);
}
}
server.servlet.context-path=/api
统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件,具体实现代码如下:
@ControllerAdvice
@ResponseBody
public class ErrorAdive {
@ExceptionHandler(Exception.class)
public Object error(Exception e) {
Map<String, Object> map = new HashMap<>();
map.put("code", -1);
map.put("data", null);
map.put("msg", e.getMessage());
return map;
}
}
以上⽅法表示,如果出现了异常就返回给前端⼀个 HashMap 的对象,其中包含的字段如代码中定义的那样. 我们可以针对不同的异常,返回不同的结果, 例如:
@ExceptionHandler(NullPointerException.class)
public Object nullPointerexceptionAdvice(NullPointerException e) {
HashMap<String, Object> result = new HashMap<>();
result.put("success", -1);
result.put("message", "空指针异常:" + e.getMessage());
result.put("data", null);
return result;
}
当有多个异常通知时,匹配顺序为当前类及其⼦类向上依次匹配
统⼀数据返回格式的优点有很多,⽐如以下⼏个:
统⼀的数据返回格式可以使⽤ @ControllerAdvice + 实现 ResponseBodyAdvice 的⽅式实现,具体实现代码如下:
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
/**
* 内容是否需要重写(通过此⽅法可以选择性部分控制器和⽅法进⾏重写)
* 返回 true 表示重写
* @param returnType
* @param converterType
* @return
*/
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
ObjectMapper objectMapper = new ObjectMapper();
HashMap<String, Object> result = new HashMap<>();
result.put("success", -1);
result.put("message", "");
result.put("data", body);
// 当 body 值是 String 类型的值时直接返回会报错
if (body instanceof String) {
try {
return objectMapper.writeValueAsString(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return result;
}
}