首选说下要求背景,用户通过网站登录后会将用户的基本信息记录在session,而当有请求需要用到用户信息的时候,每个方法都需要自己从session中拉取用户信息,而获取不到时还需要去处理跳转登录的操作,十分麻烦。因此考虑到开发的方便性,希望可以用到注解的方式直接将用户信息封装好,作为参数传递给各个请求。
首先有个用户的Vo类
public class UserVO { private int id=0; private String ticket=""; //唯一证书 private String username=""; //用户名 private String nickname="";//昵称 private String avatar="";//头像 private int gender=0;// 性别 private String phone="";//电话 private String email="";//邮箱 private int role=0;//用户权限 //认证信息 private String access_token=""; private String refresh_token=""; private Integer expires_in=0; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getAvatar() { return avatar; } public void setAvatar(String avatar) { this.avatar = avatar; } public int getGender() { return gender; } public void setGender(int gender) { this.gender = gender; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTicket() { return ticket; } public void setTicket(String ticket) { this.ticket = ticket; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAccess_token() { return access_token; } public void setAccess_token(String access_token) { this.access_token = access_token; } public String getRefresh_token() { return refresh_token; } public void setRefresh_token(String refresh_token) { this.refresh_token = refresh_token; } public Integer getExpires_in() { return expires_in; } public void setExpires_in(Integer expires_in) { this.expires_in = expires_in; } public int getRole() { return role; } public void setRole(int role) { this.role = role; } } 建立个参数级的注解,用于注入用户信息 @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface UserVo { /** * The URI template variable to bind to. */ String value() default ""; } 建立解释器从session中获得用户 public class UserArgumentResolver implements HandlerMethodArgumentResolver{ /** * 定义解释器支持解析的参数 */ @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterAnnotation(UserVo.class) != null; } @Override public UserVO resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest request= (HttpServletRequest) webRequest.getNativeRequest(); //从session中获取用户信息 UserVO userInfo=(UserVO)request.getSession().getAttribute("userInfo"); return userInfo; } } 最后在xml中加入解释器 <mvc:annotation-driven> <mvc:argument-resolvers> <!-- 自定义标签获得UserVO--> <bean class="com.xiaoma.universe.common.interceptor.UserArgumentResolver" /> </mvc:argument-resolvers> </mvc:annotation-driven> 配合拦截器一起使用,当请求发生的时候先进入拦截器判断session中的用户信息是否为null,不为空进入解释器获取,为空直接进入登录页面定义拦截器:
public class UserInterceptor implements HandlerInterceptor{ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object obj, Exception err) throws Exception { } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView mav) throws Exception { } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception { HttpSession session = request.getSession(); UserVO userInfo = (UserVO) session.getAttribute("userInfo"); String url = request.getRequestURI(); if((userInfo==null) { //不符合条件的,跳转到登录界面 response.sendRedirect("/login"); return false; } request.setAttribute("userInfo", userInfo); return true; } } xml中配置拦截规则 <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/*"/> <bean class="xx.xx.xx.UserInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>