这里业务场景需要,所有的请求都需要登录验证。个别通用业务不需要登录拦截。注解方式替代原有的if判断。
使用:@RequireLogin默认(required = true)进行登录拦截。 声明属性required = false则放行。方法注解标记的优先级将大于类注解标记。
元注解说明:
@Retention:注解的保留位置 @Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含 @Retention(RetentionPolicy.CLASS) //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得, @Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到 @Target:注解的作用目标 @Target(ElementType.TYPE) //接口、类、枚举、注解 @Target(ElementType.FIELD) //字段、枚举的常量 @Target(ElementType.METHOD) //方法 @Target(ElementType.PARAMETER) //方法参数 @Target(ElementType.CONSTRUCTOR) //构造函数 @Target(ElementType.LOCAL_VARIABLE)//局部变量 @Target(ElementType.ANNOTATION_TYPE)//注解 @Target(ElementType.PACKAGE) ///包 @Document:说明该注解将被包含在javadoc中 @Inherited:说明子类可以继承父类中的该注解
1、自定义注解@RequireLogin:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 提供登陆拦截注解,默认全局登陆拦截,如果标记required = false则不拦截 * @author asus * @date 2019/8/6 */ @Target({ ElementType.METHOD, ElementType.TYPE }) //方法和类 @Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到 public @interface RequireLogin { boolean required() default true; }
2、定义登陆拦截器:
/** * Created by asus on 2019/8/6. */ @Component public class LoginInterceptor extends BaseInterceptor { private static Logger logger = LoggerFactory.getLogger(LoginInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { logger.info("进入登陆拦截器..."); if(isFilter(request, response, (HandlerMethod) handler)){ return super.preHandle(request, response, handler); } try { if(isLoginCheck){ //这里进行用户身份信息验证 ResponseUtils.renderText((HttpServletResponse) response, Response.fail("登陆信息失效,请重新登陆获取", ErrorCode.NEED_LOGIN).toString()); return false; } } catch (Exception e) { logger.error("处理异常" + e.getMessage(), e); ResponseUtils.renderText((HttpServletResponse) response,Response.fail("处理失败", ErrorCode.PROCESS_ERROR).toString()); } return super.preHandle(request, response, handler); } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
3、继承的BaseInterceptor:
import com.yllt.common.annotation.RequireLogin; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Created by asus on 2019/8/6. */ public class BaseInterceptor extends HandlerInterceptorAdapter { public boolean isFilter(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) { // 判断当前method上是否有标签; HandlerMethod hm = (HandlerMethod) handler; //类上有该标记 RequireLogin classAnnotation = hm.getBeanType().getAnnotation(RequireLogin.class); //方法上有该标记 RequireLogin methodAnnotation = hm.getMethod().getAnnotation(RequireLogin.class); //方法上的注解优先 RequireLogin requireLogin = methodAnnotation != null ? methodAnnotation : classAnnotation; if (requireLogin != null && !requireLogin.required()) { // 如果标记required = false 则放行 return true; } return false; } }
4、测试demo:
@Controller @RequestMapping("app") @RequireLogin(required = false) public class LoginAction extends BaseAction{ @ResponseBody @RequestMapping(value="login") public Response<?> login(String userName, String password){ return Response.success("111"); } @RequireLogin @RequestMapping("index") @ResponseBody public Response<?> index(){ return Response.success("222"); } }
这里类使用了注解@RequireLogin(required = false),则访问app/login.jhtml不拦截。
方法index由于使用了方法注解标记,优先级大于类注解标记,这里访问app/index.jhtml进行拦截。