一、目的:通过在方法上加注解控制哪些方法需要登陆后才能访问
二、方式:利用拦截器判断用户是否登陆
三、实现步骤
- 定义配置文件
struts.xml添加节点
1234567891011121314151617181920<
package
name
=
"custom-default"
extends
=
"struts-default"
>
<
interceptors
>
<!-- 声明自定义的权限控制拦截器 -->
<
interceptor
name
=
"loginInterceptor"
class
=
"interceptors.LoginInterceptor"
/>
<!-- 把自定义的权限控制拦截器和默认的拦截器栈加到新的自定义的拦截器栈 -->
<
interceptor-stack
name
=
"myInterceptors"
>
<
interceptor-ref
name
=
"loginInterceptor"
/>
<
interceptor-ref
name
=
"defaultStack"
/>
</
interceptor-stack
>
</
interceptors
>
<!-- 指定新的自定义的拦截器栈为默认的拦截器栈,这样自定义的权限控制拦截器就可以发挥作用了 -->
<!-- 这里name属性值对应的是上述interceptor-stack name属性值 -->
<
default-interceptor-ref
name
=
"myInterceptors"
></
default-interceptor-ref
>
<!-- 这里对应拦截器中return Action.LOGIN对应的页面-->
<
global-results
>
<
result
name
=
"login"
>/WEB-INF/content/LoginInfo/login.jsp</
result
>
</
global-results
>
</
package
>
-
定义注解
注解主要是作用在方法上,拦截器根据方法是否定义注解来处理登陆判断
123456789101112131415package
annotations;
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Target
({ElementType.METHOD})
@Retention
(value = RetentionPolicy.RUNTIME)
public
@interface
Authority {
/**
* @return The namespace value.
*/
String value();
}
-
定义拦截器
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748package
interceptors;
import
java.lang.reflect.Method;
import
java.util.Map;
import
org.apache.struts2.convention.annotation.InterceptorRef;
import
com.opensymphony.xwork2.Action;
import
com.opensymphony.xwork2.ActionContext;
import
com.opensymphony.xwork2.ActionInvocation;
import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import
annotations.Authority;
import
common.Constants;
@SuppressWarnings
(
"serial"
)
public
class
LoginInterceptor
extends
AbstractInterceptor {
@Override
public
String intercept(ActionInvocation invocation)
throws
Exception {
String methodName = invocation.getProxy().getMethod();
Class clazz = invocation.getAction().getClass();
// 获取类对象
Method currentMethod = clazz.getMethod(methodName);
//获取拦截的方法
//方法上添加了注解
if
(currentMethod.isAnnotationPresent(Authority.
class
)) {
// 取得当前请求的注解的action
ActionContext context = invocation.getInvocationContext();
Map session = context.getSession();
//Constants.UserName=="UserName"
String user = (String) session.get(Constants.UserName);
System.err.println(
"拦截器起作用"
);
if
(user ==
null
)
// 未登陆,跳转到登录页
{
System.err.println(
"进入拦截器:未登陆"
);
context.put(
"tip"
,
"你还没有登录"
);
return
Action.LOGIN;
}
else
{
//已登录,继续后续流程
System.err.println(
"进入拦截器:已登录"
);
return
invocation.invoke();
}
}
else
{
System.err.println(
"进入拦截器:没有使用注解"
);
return
invocation.invoke();
}
}
}
- 定义Action类及方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package action; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.InterceptorRef; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import org.apache.struts2.interceptor.validation.SkipValidation; import annotations.Authority; import common.Constants; import org.apache.struts2.convention.annotation.InterceptorRefs; @SuppressWarnings ( "serial" ) @ParentPackage ( "custom-default" ) //这里对应的配置文件中包的名称 public class LoginAction extends SuperActionSupport { @Action (value = "loginValidate" , results = { @Result (name = "success" , location = "/WEB-INF/content/LoginInfo/success.jsp" ), @Result (name = "input" , location = "/WEB-INF/content/LoginInfo/login.jsp" ) }) @Authority ( "" ) //定义注解后未登录回到登陆页,否则执行后续步骤 public String loginValidate() throws Exception { return SUCCESS; } } |
四、实现过程中遇到的坑
-
内置的注解@InterceptorRefs/@InterceptorRef只能作用在类文件上,不能作用到方法上(从其@Target属性即可看出)
-
类上的注解@ParentPackage("custom-default")必须对应structs.xml中package的name属性,否则注解不起效
-
structs.xml中default-interceptor-ref的name值对应的是interceptor-stack的name值,否则注解不起效
五、参考资料