有時候我們要在controller層每個方法中判斷用戶是否已經登錄了,假如一個一個去判斷的話會很繁瑣。可以采用HandlerMethodArgumentResolver來進行參數自動注入
1 自定義參數解析類UserArgumentResolver ,並將其注入到了argumentResolvers中,注入失敗會拋出自定義異常
@Configuration public class WebConfig extends WebMvcConfigurerAdapter{ @Autowired UserArgumentResolver userArgumentResolver; @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { //注入自定義參數解析器 argumentResolvers.add(userArgumentResolver); } }
@Service public class UserArgumentResolver implements HandlerMethodArgumentResolver { @Autowired MiaoshaUserService userService; //只解析方法中參數類型是MiaoshaUser的參數 public boolean supportsParameter(MethodParameter parameter) { Class<?> clazz = parameter.getParameterType(); return clazz== MiaoshaUser.class; } //從cookie或者請求參數中獲取token,然后通過token獲取MiaoshaUser對象, // 如果獲取不到MiaoshaUser對象,拋出異常,然后被GlobalExceptionHandler捕獲異常,返回給前端 //如果可以獲取到MiaoshaUser對象,controller方法中的MiaoshaUser類型的參數就被注入值了 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); String paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN); String cookieToken = getCookieValue(request, MiaoshaUserService.COOKI_NAME_TOKEN); if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) { throw new GlobalException(CodeMsg.SESSION_ERROR); } String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken; return userService.getByToken(response, token); } private String getCookieValue(HttpServletRequest request, String cookiName) { Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length > 0 ){ for(Cookie cookie : cookies) { if(cookie.getName().equals(cookiName)) { return cookie.getValue(); } } } return null; } }
2 全局異常捕獲
public class GlobalException extends RuntimeException{ private static final long serialVersionUID = 1L; private CodeMsg cm; public GlobalException(CodeMsg cm) { super(cm.toString()); this.cm = cm; } public CodeMsg getCm() { return cm; } }
@ControllerAdvice @ResponseBody public class GlobalExceptionHandler { @ExceptionHandler(value=Exception.class) public Result<String> exceptionHandler(HttpServletRequest request, HttpServletResponse response ,Exception e){ e.printStackTrace(); if(e instanceof GlobalException) { GlobalException ex = (GlobalException)e; response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter out = null; try { out = response.getWriter(); out.append(JSON.toJSONString(Result.error(ex.getCm()))); } catch (Exception exx) { exx.printStackTrace(); } finally { if (out != null) { out.close(); } } return null; }else if(e instanceof BindException) { BindException ex = (BindException)e; List<ObjectError> errors = ex.getAllErrors(); ObjectError error = errors.get(0); String msg = error.getDefaultMessage(); return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg)); }else { return Result.error(CodeMsg.SERVER_ERROR); } } }
3 controller層中的方法 MiaoshaUser是被自動注入的。如果注入失敗會拋出異常,把異常返回給前端
@Controller @RequestMapping("/goods") public class GoodsController { @RequestMapping(value="/to_list") @ResponseBody public String list(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user) { System.out.println(user); model.addAttribute("user", user); return "goods_list"; } }