大多数的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的拦截。根据具体情况而定了。