用户进行访问官网或者游戏需要对用户的操作进行相应的拦截,可是有时候需要对用户各个行为进行分开拦截,有的操作不必对其进行拦截。这时候容易想到的是使用MethodFilterInterceptor类来进行对各个方法进行是否拦截的操作。可是当一个应用非常复杂,这时就会在struts的配置文件配置多个excludeMethods,这样看起来就会很臃肿,一时也想不起使用什么更好的方法来进行对方法的拦截,后来发现使用注解是一个不错的选择:在某个action类的某个具体方法上写上对应的注解,根据注解的值来确定是否进行拦截。这时遇到的问题是如何检测当前请求的action方法是否有此注解,并且注解也有在类上也有在方法上的,这时又是如何区分呢,参考了一些资料,写成了这样:
//RestMethod这个注解是注解在方法上private boolean isRestMethod(Method actionMethod) { boolean annotationPresent = actionMethod.isAnnotationPresent(RestMethod.class);//检查某个方法是否是注解方法,RestMethod是自己定义的注解类 if (annotationPresent) { RestMethod restMethod = actionMethod.getAnnotation(RestMethod.class);//如果是注解的方法,则得到注解类的实例 return restMethod.intercept();//调用注解实例的intercept方法 } return false; } //AnonymousRedirect这个注解是注解在方法和类上的 private boolean isAnonymousRedirect(Class<?> actionClass, Method actionMethod) { Class<Redirection> rclass = Redirection.class;//Redirection是自己定义的注解类 boolean annotationPresent = actionMethod.isAnnotationPresent(rclass); Redirection redirection = null; if (annotationPresent) { redirection = actionMethod.getAnnotation(rclass);//获得方法上的注解类实例 return redirection.value(); } else { annotationPresent = actionClass.isAnnotationPresent(rclass); if (annotationPresent) { redirection = actionClass.getAnnotation(rclass);//获得类上的注解类实例 return redirection.value(); } else { return false; } } }这样的话我们就可以写一个继承了MethodFilterInterceptor这个类的拦截类。在这个类的doIntercept方法里实现具体的拦截过程并转发视图,具体代码如下:
protected String doIntercept(ActionInvocation invocation) throws Exception {
final Object action = invocation.getAction();//得到拦截起拦截的action类
ActionContext context = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
// HttpServletResponse response = (HttpServletResponse)
// context.get(HTTP_RESPONSE);
String clientIp = ServletUtils.getClientIp(request);
Class<?> actionClass = action.getClass();
Method currentMethod = null;
try {
currentMethod = getActionMethod(actionClass, invocation.getProxy().getMethod());
} catch (NoSuchMethodException ex) {
return GLOBAL_VIEW_404;
}
String format = ServletUtils.getParameter(request, PARAM_FORMAT, AjaxResult.FORMAT_JSON);
SessionBean session = SessionManager.getConcurrentSession();
Authentication authToken = session == null ? Authentication.ANONYMOUS : session.getAuthToken();
if (authToken.isAnonymous()) {//如果是匿名用户则使用action类注解来进行相应的拦截
if (isAnonymousRedirect(actionClass, currentMethod)) {
if (action instanceof IndexAction) {
return ConstantConfig.GLOBAL_VIEW_LOGIN;
}
return ConstantConfig.GLOBAL_VIEW_LOGIN;
}
if (isRestMethod(currentMethod)) {
String referer = request.getHeader("Referer");
if (isIllegalReferer(referer)) {
StringBuffer buf = new StringBuffer("Illegal request referer: ");
buf.append(referer).append(" @").append(actionClass.getName()).append("#");
buf.append(currentMethod.getName()).append(" request client IP:").append(clientIp);
LOGGER.error(buf.toString());
if (AjaxResult.FORMAT_JSON.equalsIgnoreCase(format)) {
String jsonResult = AjaxResult.getErrorJson("Illegal Request Referer.");
request.setAttribute(AjaxResult.RESULT_KEY, jsonResult);
return GLOBAL_VIEW_JSON;
} else {
return GLOBAL_VIEW_ERROR;
}
}
}
}
if (action instanceof AuthenticationAware) {
AuthenticationAware authAware = (AuthenticationAware) action;
authAware.setAuthentication(session == null ? Authentication.ANONYMOUS : session.getAuthToken());
}
return invocation.invoke();
}
//获得action中定义的方法
private Method getActionMethod(Class<?> actionClass, String methodName) throws NoSuchMethodException {
Method method = null;
try {
method = actionClass.getMethod(methodName, new Class[0]);
} catch (NoSuchMethodException ex) {
// 未打到指定的方法,试试 找父类方法。
Class<?> superClass = actionClass.getSuperclass();
try {
method = superClass.getMethod(methodName, new Class[0]);
} catch (NoSuchMethodException nsme) {
throw nsme;
}
}
return method;
}
/** 访问方是否为非法来源。 */
private boolean isIllegalReferer(String referer) {
return false;
}然后将该类配置在struts配置文件当中,这样就可以实现对具体方法进行具体拦截的功能了。