定义拦截器:
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("登录拦截器校验...");
//返回true表示放行, 返回false 表示拦截
HttpSession session = request.getSession();
UserInfo userInfo = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
if (userInfo!=null && userInfo.getId()>=0){
return true;
}
response.setStatus(401);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("目标方法执行后");
}
}
注册拦截器:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
private static List<String> excludePath = Arrays.asList("/user/login",
"/css/**",
"/js/**",
"/pic/**",
"/**/*.html",
"/test/**");
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**") // /** 表示所有方法添加拦截器
.excludePathPatterns(excludePath);
}
}
拦截路径 | 含义 | 举例 |
---|---|---|
/* | ⼀级路径 | 能匹配/user,/book,/login,不能匹配/user/login |
/** | 任意级路径 | 能匹配/user,/user/login,/user/reg |
/book/* | /book下的⼀级路径 | 能匹配/book/addBook,不能匹配/book/addBook/1,/book |
/book/** | /book下的任意级路径 | 能匹配/book,/book/addBook,/book/addBook/2,不能匹 配/user/login |
返回数据的格式:
@Data
public class Result {
/**
* 业务状态码
*/
private ResultCode code; //0-成功 -1 失败 -2 未登录
/**
* 错误信息
*/
private String errMsg;
/**
* 数据
*/
private T data;
public static Result success(T data){
Result result = new Result();
result.setCode(ResultCode.SUCCESS);
result.setErrMsg("");
result.setData(data);
return result;
}
public static Result fail(String errMsg){
Result result = new Result();
result.setCode(ResultCode.FAIL);
result.setErrMsg(errMsg);
result.setData(null);
return result;
}
public static Result fail(String errMsg,Object data){
Result result = new Result();
result.setCode(ResultCode.FAIL);
result.setErrMsg(errMsg);
result.setData(data);
return result;
}
public static Result unlogin(){
Result result = new Result();
result.setCode(ResultCode.UNLOGIN);
result.setErrMsg("用户未登录");
result.setData(null);
return result;
}
}
统一数据格式封装:
/**
* 实现统一数据返回的保底类
* 说明:在返回数据之前,检测数据的类型是否为统一的对象,如果不是,封装成统一的对象
*/
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
/**
* 开关,如果是true才会调用beforeBodyWrite
*/
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
/**
* 对数据格式进行效验和封装
*/
@Autowired
private ObjectMapper objectMapper;
@SneakyThrows//异常抛出,相当于方法上throw一个异常
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//进行了统一对象的封装,直接返回body
if (body instanceof Result){
return body;
}
//字符串类型特殊处理。手动对其进行ajax类型的转化
if (body instanceof String){
return objectMapper.writeValueAsString(Result.success(body));
}
//未进行封装的对其进行统一封装
return Result.success(body);
}
}
异常统一封装:
@ResponseBody,如果你在统一异常处理中没有使用@ResponseBody
注解,并且返回的结果是一个普通的Java对象而不是响应体,可能会导致控制台循环输出的问题。这通常是因为Spring Boot尝试使用默认的ExceptionResolver
去处理异常时,发现无法序列化返回的对象,而进入循环。
@ResponseBody
@Slf4j
@ControllerAdvice
public class ErrorHandler {
@ExceptionHandler
public Result excption(NullPointerException e){
log.error("发生异常,e:{}",e);
return Result.fail("NullPointerException异常,请联系管理员");
}
@ExceptionHandler
public Result excption(ArithmeticException e){
log.error("发生异常,e:{}",e);
return Result.fail("ArithmeticException异常,请联系管理员");
}
@ExceptionHandler
public Result excption(Exception e){
log.error("发生异常,e:{}",e);
return Result.fail("Exception异常,请联系管理员");
}
}
如果后端返回的结果是String类型,当我们使用统一结果返回时,返回的是JSON字符串
conten-type是text/html,我们需要把他转为JSON
如果后端进行转换:
@RequestMapping(value = "/addBook", produces = "application/json")
produces = "application/json"表示HTTP响应的数据类型是application/json