Controller层方法参数自动注入用户信息
有时候我们要在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"; } }