spring mvc 方法註解攔截器

應用場景,在方法級別對本次調用進行鑑權,如api接口中有個用戶惟一標示accessToken,對於有accessToken的每次請求能夠在方法加一個攔截器,得到本次請求的用戶,存放到request或者session域。java

python中,以前在python flask中能夠使用裝飾器來對方法進行預處理,進行權限處理python

先看一個實例,使用@access_required攔截:web

@api.route('/post_apply')
@access_required
def apply():
    """
     活動報名
    """
    print '報名者是:'+g.user
    return jsonify(response_data)

實現很簡單:spring

# 驗證access_token並保存當前用戶到g中
def access_required(f):
    @wraps(f)
    def decorated_func(*args, **kwargs):
        access_token = request.values.get('access_token')
        if access_token == None:
            return error_msg('500', 'access_token required')
        if access_token == "":
            return error_msg('500', 'access_token can not empty')
        if is_access_token(access_token) == False:
            return error_msg('500', 'invalid_access_token')
        return f(*args, **kwargs)
    return decorated_func


java中,自定義註解攔截器來實現,在須要的攔截的方法上面加上一個註解@AccessRequiredjson

spring mvc Controller中的使用實例flask

/**
	 * 註解攔截器方法
	 * @return
	 */
	@RequestMapping(value="/urlinter",method=RequestMethod.GET)
	@AccessRequired
	public @ResponseBody String urlInterceptorTest() {
		return "經過攔截器:user"+request.getAttribute("currUser");
	}

如何實現以上實例呢?api

定義一個註解:session

import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessRequired {
	
}

搞一個攔截器:mvc

/**
 * 攔截url中的access_token
 * @author Nob
 * 
 */
public class UserAccessApiInterceptor extends HandlerInterceptorAdapter {

	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {

		HandlerMethod handlerMethod = (HandlerMethod) handler;
		Method method = handlerMethod.getMethod();
		AccessRequired annotation = method.getAnnotation(AccessRequired.class);
		if (annotation != null) {
		   System.out.println("你遇到了:@AccessRequired");
		   String accessToken = request.getParameter("access_token");
			/**
			 * Do something
			 */
		    response.getWriter().write("沒有經過攔截,accessToken的值爲:" + accessToken);
		}
		// 沒有註解經過攔截
		return true;
	}
}

在spring mvc配置文件中:app

<!-- 攔截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- 對全部的請求攔截使用/** ,對某個模塊下的請求攔截使用:/myPath/* -->
			<mvc:mapping path="/api/**" />
			<ref bean="userAccessInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

	<bean id="userAccessInterceptor"
		class="com.banmacoffee.web.interceptor.UserAccessApiInterceptor">
	</bean>

注意問題:

    若是你使用了<mvc:resources mapping="/resources/**" location="/resources/" />來配置靜態資源,那麼配置如上攔截器的時候就要使用使用了全局攔截/**,不然會攔截靜態資源拋出ResourceHttpRequestHandler cannot be cast to HandlerMethod異常

辦法一:加上攔截路徑前綴

<mvc:mapping path="/path/**" />

<!-- 這裏使用一個path前置,如api,不然會攔截靜態資源 -->

辦法二:在自定義攔截器中使用instanceof 過濾ResourceHttpRequestHandler 類型

大功告成,你能夠在攔截器裏隨心所欲,而且把它加載任何你想的Controller 請求的方法上

相關文章
相關標籤/搜索