需求:
自定義一個注解,使得controller層的類或者方法在寫上這個注解後,會有登陸驗證。
實作原理:
(1)先寫一個自定義注解,注解上可以通過注釋确定是類/方法可以加此注解。
(2)之後,寫一個攔截器,攔截器内可以通過handler得到被攔截器攔截的類或者方法,之後可以通過這個類/方法得知它是否有之前寫的注解,如果有,就需要登陸校驗。
(3)之後要把這個攔截器配置到spring-mvc的配置檔案中,需要讓spring知道有哪些請求需要被攔截器攔截,一般是“/**”,是所有請求。
(4)在controller的類或者方法上加上步驟一中的的自定義注解就可以輕易實作是否需要登陸校驗了。
例子:
1.自定義注解:
package com.qunar.fresh.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* LoginRequired
*
* @author chenliclchen
* @date 17-10-11 下午8:30
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
@Target({ElementType.METHOD, ElementType.TYPE}) 表示類和方法都可以加此注解
2.寫一個攔截器:
package com.qunar.fresh.interceptor;
import com.qunar.fresh.annotation.LoginRequired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* AuthInterceptor
*
* @author chenliclchen
* @date 17-10-11 下午8:38
*/
@Slf4j
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// return super.preHandle(request, response, handler);
if(handler instanceof HandlerMethod){
HandlerMethod myHandlerMethod = (HandlerMethod) handler;
Object bean = myHandlerMethod.getBean();
Method method = myHandlerMethod.getMethod();
LoginRequired classAnnotation = bean.getClass().getAnnotation(LoginRequired.class);
LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);
if(classAnnotation != null || methodAnnotation != null){
boolean loginState = isLogin(request, response);
if(loginState){
return true;
}
if(isAjax(request)){
//ajax 請求需要傳回json
log.info("ajax 請求,沒有登陸");
}else{
log.info("普通請求,沒有登陸");
}
return false;
}
}
return true;
}
private boolean isLogin(HttpServletRequest request, HttpServletResponse response){
return false;
}
private boolean isAjax(HttpServletRequest request){
String requestType = request.getHeader("X-Requested-With");
if(requestType != null && requestType.equals("XMLHttpRequest")){
return true;
}else{
return false;
}
}
}
在isLogin方法中寫上是否登陸的驗證。
原理是先通過myHandlerMethod.getBean();得到bean,再通過bean.getClass().getAnnotation(LoginRequired.class);的傳回值确定是否有LoginRequired(即步驟1)中的自定義注解。
通過myHandlerMethod.getMethod();也可以得到得到method。通過method.getAnnotation(LoginRequired.class);得到次方法是否有自定義注解。
也可以通過下面的方法得到是否有LoginRequired 自定義注解。
HandlerMethod handlerMethod = (HandlerMethod) handler;
if (!handlerMethod.getBeanType().isAnnotationPresent(LoginRequired.class)
&& !handlerMethod.getMethod().isAnnotationPresent(LoginRequired.class)) {
return false;
}
return true;
3.配置springmvc檔案:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<ref bean="authInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
4.使用例子:
package com.qunar.fresh.controller;
import com.qunar.fresh.annotation.LoginRequired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* TestController
*
* @author chenliclchen
* @date 17-10-11 下午9:05
*/
@LoginRequired
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/one")
public String test(){
return "test";
}
}
這樣,通路以/test開頭的所有url都會有是否登陸的驗證。