大多数的web端项目都会用到"权限"这个东西,首先要明白权限是捆绑在角色上的,也就是对应关系,权限:角色=n:1.
既然需要有权限的地方,那么拦截器自然不可以缺少了。
1.拦截器的配置文件(struts.xml):
<package name="manage" namespace="/" extends="default">
<!--管理员 -->
<interceptors>
<interceptor name="admininter" class="cn.yitongworld.util.AdminInteceptor"></interceptor> <interceptor-stack name="admininterstack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="admininter"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 配置默认拦截器栈-->
<default-interceptor-ref name="admininterstack"/>
<global-results>
<result name="login" type="chain">preLogin</result>
<result name="optresult_success">/WEB-INF/manage/operationresult_success.jsp</result>
<result name="optresult_error">/WEB-INF/manage/operationresult_error.jsp</result>
</global-results>
<!-- 上传图片 -->
<action name="fileUpload" class="cn.yitongworld.action.FileUploadAction"></action>
</package>
2.java代码(类):
@ParentPackage("manage")
@Namespace("/")
@Controller
public class ManBillAction extends BaseAction<Bill> {
代码省略.........
}
3.java代码(拦截器)
@SuppressWarnings("serial")
public class AdminInteceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation){
//获取当前用户信息
Map<String, Object> session = ActionContext.getContext().getSession();
//获得当前请求的对象(好像就是一个地址)
HttpServletRequest request = ServletActionContext.getRequest();
//判断用户是否存在
if(session.get(Const.SESS_USER)!=null){
try { //转换称用户对象
User user=(User) session.get(Const.SESS_USER);
//判断用户是不是管理员
if(user.getId()==null||!user.getType().equals(UserType.ADMINUSER)){
return Action.LOGIN;
}
//判断用户是不是超级管理员
if(user.getId().toString().equals(Cache.getSetting(Const.SUPERADINID).getValue())){ //如果是超级管理员,继续调用下面的action或者是result
return invocation.invoke();
}
//判断用户的权限和角色是否为空
if(MyString.isEmpty(user.getAuthority())&&MyString.isEmpty(user.getRole())){
request.setAttribute("tipMessage","抱歉,权限不够!");
return Action.ERROR;
}
//从当前请求的对象中得到url
String url=request.getRequestURI();
//从url中截取出action
String action =url.substring(url.lastIndexOf("/")+1);
//判断是否含有权限
if(hasAuth(invocation, user.getAuthority(), action))
//如果有权限继续走原先的action
return invocation.invoke();
//判断所在角色是否含有权限
if(!MyString.isEmpty(user.getRole()))
//角色有多个权限
for(String role:user.getRole().split(",")){
//role其实就是角色中的任意一个权限
if(hasAuth(invocation, StaticDataCache.getStaticdata(role).getValue(), action)) //如果有权限继续走原先的action
return invocation.invoke();
}
request.setAttribute("tipMessage","抱歉,权限不够!");
return Action.ERROR;
} catch (Exception e) {
e.printStackTrace();
return "500";
}
}else{
request.setAttribute("tipMessage","未登陆,请先登陆!");
//跳转至拦截页面
if(!request.getRequestURI().contains("login"))
session.put("returnUrl", getReturnUrl(request));
return Action.LOGIN;
}
}
private boolean hasAuth(ActionInvocation invocation, String authority, String action){
if(!MyString.isEmpty(authority)){
for(String auth:authority.split(","))
{
if(MyString.isEmpty(auth)){
continue;
}
try{
Staticdata sd = StaticDataCache.getStaticdata(auth.trim());
if(sd.getValue()==null)
continue;
if(sd.getValue().equals(action))
return true;
}catch(Exception e){
e.printStackTrace();
continue;
}
}
}
return false;
}
private String getReturnUrl(HttpServletRequest request){
Map<String, String[]> map=request.getParameterMap();
StringBuffer temp=new StringBuffer(request.getRequestURI()+"?");
Iterator<Entry<String, String[]>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) iter.next();
for(String val:entry.getValue()){
temp.append(entry.getKey()+"="+val+"&");
}
}
String value=temp.toString();
if(value.endsWith("&")){
value=value.substring(0, value.length()-1);
}
return temp.toString();
}
}
程序应该是这样走的,当用户点击相应的url的时候,会直接进入action中,但是在action中出现了以下2个注解
@ParentPackage("manage")
@Namespace("/")
你是不是想问这个是什么呢?看完拦截器的配置你就懂了,是对应的(此拦截器配置在了进入action之前)
<package name="manage" namespace="/" extends="default">
所以说还没有加载页面数据的时候,程序看到类的注释会先去配置文件中找到相应的Interceptor
<interceptor name="admininter" class="cn.yitongworld.util.AdminInteceptor"></interceptor>
根据Interceptor的引用找到相应的类进行拦截,直到遇见
return invocation.invoke();
说明拦截成功,此时程序会怎么样执行呢?也是最难的一点对于我这个菜鸟来说。一般来说都是调用一个方法得到一个结果,那拦截器是不是这个道理呢?当然啦!说明拦截成功了!只有拦截成功才可以运行下面的"程序",这个"程序"指的就是加拦截器注释的类。大概程序运行过程是这样的:2->1->3->2
总结:struts2的Interceptor其实有n种方式去拦截,我这里是在程序执行之前进行的拦截(用户没有权限直接不去执行下面的action),你也可以在加载页面数据之后进行CRUD的拦截。根据具体情况而定了。