版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun5769675/article/details/77477967
今天介绍的是一个关于登录校验的自定义注解,之前有过一篇写如果自定义注解的博文:Java中的自定义注解
那么这次讲一个经常会出现的场景下,会使用到的注解,一般我们无论是开发后端系统还是前端系统,都会有用户的概念,那么很多业务场景下我们都需要去校验当前访问者是否已经登录了,举个例子,如果是一个商城系统访问者要访问用户个人中心,那么请求发出到服务器后程序一定会先去校验是否登录了,如果没有登录让他跳到去登录的页面或者去自定义的页面展示什么特定的东西,那么这个校验登录和跳转的代码就会重复出现在各个这种类型的方法中,写起来让人很烦。
OK,那么现在我们来写一个自定义注解,只要你在需要验证登录的方法上打上注解,那么请求过来的时候先去判断是否登录了,没有登录的话根据你的配置看他是跳转到登录页还是你配置的页面去,废话不多说直接贴代码来看:
先来创建一个NeedLogin注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description 标识当前方法需要登录后才能进入
* @author chenbin.sun
* @date 2017年8月17日下午4:53:58
*
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin {
/**
* 用来确定没有登录后跳到哪里
* 如果有值,则使用returnUrl做为跳转,否则根据业务跳到指定url
* @return
*/
String returnUrl() default "";
}
再来写一个跟注解配合使用的拦截器:
/**
* @Description 校验是否需要登录后访问,注意如果有自动登录的功能,那么该拦截器一定要配置在自动登录拦截器的后面
* <p>
* 如果NeedLogin标签配置了returnUrl那么没登录的时候会直接跳returnUrl指定的地方,如果没有配置,
* 那么会默认跳登录页面,并把当前的请求作为回调参数,传递给登录页面,以供登录完后跳转回来
* @author chenbin.sun
* @date 2017年8月16日下午5:49:58
*
*/
public class CheckLoginInterceptor extends HandlerInterceptorAdapter {
private final static Logger LOGGER = LoggerFactory.getLogger(CheckLoginInterceptor.class);
/** 配置登录页面url,如果没登录且没有配置自定义的跳转,那么跳到这里 */
public static final String LOGIN_PAGE_URL = "/login.htm";
/** 回调url参数的key */
public static final String CALL_BACK_URL = "callBackUrl";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
// 获取方法上有没有打注解
NeedLogin needLogin = method.getMethodAnnotation(NeedLogin.class);
// 不为null表示该方法打了注解需要校验是否登录了
if (needLogin != null) {
// 先获取当前请求的请求参数
String query = StringUtils.isNotEmpty(request.getQueryString()) ? ("?" + request.getQueryString()) : "";
// 先获取当前请求的请求完整url
String callBackUrl = request.getRequestURL().toString() + query;
LOGGER.info(LogUtils.format(LogType.NEEDLOGIN_INTERCEPTOR, "当前请求的url:%s", callBackUrl));
LOGGER.info(LogUtils.format(LogType.NEEDLOGIN_INTERCEPTOR, "当前请求需要登录后才能请求,开始检验是否登录!"));
// 判断是否登录了
MemberCommand memberCommand = (MemberCommand) request.getSession()
.getAttribute(SessionAttr.MEMBER_DETAIL);
if (Validator.isNotNullOrEmpty(memberCommand)) {
LOGGER.info(LogUtils.format(LogType.NEEDLOGIN_INTERCEPTOR, "校验完毕,已经登录了请求通过"));
return true;
}
LOGGER.info(LogUtils.format(LogType.NEEDLOGIN_INTERCEPTOR, "校验完毕,当前没有登录,开始进行重定向"));
// 如果没有登录
// 校验是否配置了自定义的跳转地址
if (StringUtils.isNotEmpty(needLogin.returnUrl())) {
LOGGER.info(LogUtils.format(LogType.NEEDLOGIN_INTERCEPTOR, "重定向的url:%s", needLogin.returnUrl()));
// 自定义的跳转地址不为null那么去做重定向跳转
response.sendRedirect(needLogin.returnUrl());
} else {
// 没有配置自定义的跳转,根据我们的业务应该会跳到登录页面
// 最终重定向的url,这里加了参数是为了登录成功后回跳会这个原来请求的地址,这个要登录功能配合才行
String finallyUrl = LOGIN_PAGE_URL + "?" + CALL_BACK_URL + "=" + callBackUrl;
LOGGER.info(LogUtils.format(LogType.NEEDLOGIN_INTERCEPTOR, "重定向的url:%s", finallyUrl));
// 开始做重定向操作
response.sendRedirect(finallyUrl);
}
return false;
}
}
return true;
}
}
拦截器写完了别忘了配置到xml里:
<!-- 拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.chenbin.sun.interceptor.CheckLoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
好了到这里基本就写完了,那么看下如何使用:
@NeedLogin
@RequestMapping(value = "/memberInfo")
public String memberInfo(Model model,HttpServletRequest request){
return "member.info";
}
上面这种用法,根据我们的拦截器的写法,如果没登录的用户请求过来会重定向到登录页面,同时会得到当前请求的这个/memberInfo的url参数,那么当那边登录成功后可以回跳到/memberInfo。
另一种用法:
@NeedLogin(returnUrl="/xxx/xxx")
@RequestMapping(value = "/memberInfo")
public String memberInfo(Model model,HttpServletRequest request){
return "member.info";
}
这种写法按照我们的拦截器的规则,如果没有登录的用户请求过来会直接给他重定向到/xxx/xxx,这个可能是个注册页面或者某个活动页面什么的,这就取决于业务了,反正我觉得这两种基本需求都可以满足的。
OK,大家如果有自己的业务需求可以根据需求修改拦截器的逻辑,或者在NeedLogin中加需要的参数都是可以的。
最后,有什么问题欢迎留言~~