springMvc使用注解拦截用户登录状态及自定义解析器

本文介绍了如何在SpringMvc中使用注解拦截用户登录状态,详细讲解了定义Login注解、拦截器配置以及利用ThreadLocal管理用户数据。同时,文章还阐述了自定义解析器的实现过程,包括@LoginUser注解定义、实现HandlerMethodArgumentResolver接口以及在XML中的配置,以方便获取和使用用户信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、使用注解拦截用户登录状态

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());
		
	}	

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值