springMvc使用註解攔截用戶登錄狀態及自定義解析器

一、使用註解攔截用戶登錄狀態

1.定義Login註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Login {

}

2.定義攔截器

public class UserInterceptor extends HandlerInterceptorAdapter {
	

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		if(handler instanceof HandlerMethod) {
			
			UserVO user = getUser(request);
			UserContext.setUser(user);
			
			HandlerMethod hm = (HandlerMethod) handler;
			//攔截有@Login註解的方法,驗證是否有用戶登錄
			Login login = hm.getMethodAnnotation(Login.class);
			String callback = request.getParameter("callback");
			if(null != login) {
				if(user == null) {
					WebUtil.render(response,CodeMsg.SESSION_EXPIRE,callback);
					return false;
				}
			}
			
		}
		return true;
	}
	
	private UserVO getUser(HttpServletRequest request) {
		HttpSession session = request.getSession();
		Object object = session.getAttribute("userId");
	
		if(null != object) {
			UserVO user = new UserVO();
			user.setUserId(Long.parseLong(object.toString()));
			return user;
		}
		return null;
	}

我這裏用了一個UserContext,目的是上下文臨時存放用戶數據,便於後面使用,ThreadLocal爲線程安全。

public class UserContext {

	private static ThreadLocal<UserVO> userHolder = new ThreadLocal<UserVO>();

	public static void  setUser(UserVO user) {
		userHolder.set(user);
	}
	
	public static UserVO  getUser() {
		return userHolder.get();
	}
}

還有一點需要注意,我們項目用了jsonp,所以在out.write的時候不要忘了callback。

public class WebUtil {

	public static void render(HttpServletResponse response,CodeMsg cm,String callback) throws IOException {
		response.setContentType("application/json;charset=utf-8");
		OutputStream out = response.getOutputStream();
		String str = JSON.toJSONString(Result.result(cm));
		if(StringUtil.isNotEmpty(callback)) {
			str = callback+"("+str+")";
		}
		out.write(str.getBytes("utf-8"));
		out.flush();
		out.close();
		// TODO Auto-generated method stub
		
	}
}

3.xml文件配置攔截器

<mvc:interceptors>  
 	<mvc:interceptor>
	<mvc:mapping path="/**" />
		<bean class="com.cmedicine.core.interceptor.UserInterceptor" />
	</mvc:interceptor> 
</mvc:interceptors>

因爲我們用了<mvc:annotation-driven> ,所以攔截器不可以用bean的方式配置,會導致失效的情況。

4.使用

在需要用戶登錄的方法加上@Login註解,即可對用戶登錄狀態校驗

@Login
@RequestMapping(params = "method=test",produces={"application/json; charset=UTF-8"})
@ResponseBody
public Result test(String e) {


	return Result.success();
		
}	

二、自定義解析器

上面我們配置了用戶狀態攔截,並且把用戶信息放到了ThreadLocal,下面我們就把它拿出來。

1.定義@LoginUser註解

/**
 * 登錄用戶信息
 * @author hanyuelei
 *
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {

}

2.自定義解析器,實現HandlerMethodArgumentResolver 接口

/**
 * 給controller帶@LoginUser註解的參數userVo注入當前登錄用戶信息
 * @author hanyuelei
 *
 */
@Component
public class UserArgumentResolver implements  HandlerMethodArgumentResolver {

	/**
	 * 只有這裏返回true ,纔會執行resolveArgument
	 */
	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		// TODO Auto-generated method stub
		Class<?> clazz = parameter.getParameterType();
//		return clazz == UserVO.class;
		return parameter.getParameterType().isAssignableFrom(UserVO.class) && parameter.hasParameterAnnotation(LoginUser.class);
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		// TODO Auto-generated method stub
//		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
//		HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
//		String userId = request.getAttribute("userId").toString();
		System.out.println("獲取用戶:"+UserContext.getUser());
        //從UserContext獲取用戶
		return UserContext.getUser();
	}

}

3.配置xml,指定我們自定義的解析器,我們前面配置過  <mvc:annotation-driven> 

 <mvc:annotation-driven> 
    <mvc:argument-resolvers>
         <bean class="com.cmedicine.core.interceptor.resolver.UserArgumentResolver"/>
     </mvc:argument-resolvers>     
 </mvc:annotation-driven> 

4.使用,參數增加@LoginUser

	@Login
	@RequestMapping(params = "method=test",produces={"application/json; charset=UTF-8"})
	@ResponseBody
	public Result test(@LoginUser UserVO uservo) {

		System.out.println("userId:"+uservo.getUserId());
	
		return Result.success(uservo.getUserId());
		
	}	

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章