在Struts 1.1后新增RequestProcessor类别,有关于使用者请求的处理分配等动作已经大部份交由RequestProcessor来处理,下图是ActionServlet接收到请求之后的一些主要动作,藉由这张图可以了解struts-config.xml的组件设定意义,以及Struts运作的方式。下面将分两点来介绍如何扩展Struts核心类。
1. 扩展RequestProcessor
RequestProcessor是Struts的核心类,而Struts的核心控制器是ActionServlet 。但ActionServlet并未完成真正的处理,只是调用RequestProcessor,它才是Struts的核心处理类。可以继承RequestProcessor,并改写其中的processXXXXX()方法来自定义请求的处理方式,扩展RequestProcessor的实例在Spring中有个示范,它提供的Delegating RequestProcessor是一个很好的示例。RequestProcessor包含了如下主要方法。
扩展RequestProcessor只需两步即可。
1>. 继承RequestProcessor,实现自定义的processXXXXX()处理方法。下面是一个权限处理实例:
/** * 用户认证方法 */ @Override protected boolean processRoles(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException, ServletException { // 得到映射的路径 String path = mapping.getPath(); // 得到用户所要调用的Action方法的名字 String method = request.getParameter(mapping.getParameter()); if (SqeStringUtils.isEmpty(method)) { method = StrutsConstants.DEFAULT_METHOD; } // 取得不需要校验权限的Action方法 String[] roles = mapping.getRoleNames(); if (roles != null && roles.length > 0) { // 进行方法的判断 for (String role : roles) { if (method.equals(role)) { request.setAttribute(StrutsConstants.REQUEST_CHECK_FLAG,true); return true; } } } // 得到Session对象和用户对象 HttpSession session = request.getSession(); User u = (User) session.getAttribute(StrutsConstants.SESSION_USER); // 如果用于对象不存在,那么说明用户没有登录 if (u == null) { // 用户没有执行的权限,跳转到错误页面 processLocale(request, response); RequestDispatcher rd = request.getRequestDispatcher("/vote/errors/noauthority.jsp"); rd.forward(request, response); return false; } // 判断用户是否为超级用户 String superusers = SqeConfigUtil.getSysConfigValue(ConfigConstants.SUPER_USER); String[] users = SqeStringUtils.splitString(superusers,ConfigConstants.USER_DELIM); if (SqeStringUtils.contains(users, u.getName())) {request.setAttribute(StrutsConstants.REQUEST_CHECK_FLAG, true); return true; } // 得到用户的角色信息 Cache cache = CacheFactory.getCache(); Role role = (Role) cache.get(u.getUserType()); if (role == null) { throw new SqeSystemException("Couldn't find the role!"); } // 进行用户执行功能的判断 Set<Function> functions = role.getFunctions(); for (Function function : functions) { Set<Action> actions = function.getActions(); for (Action action : actions) { if (path.equals(action.getPath())&& method.equals(action.getParameter())) { request.setAttribute(StrutsConstants.REQUEST_CHECK_FLAG,true); return true; } } } // 用户没有执行的权限,跳转到错误页面 processLocale(request, response); RequestDispatcher rd = request.getRequestDispatcher("/vote/errors/noauthority.jsp"); rd.forward(request, response); return false; } @Override protected void processLocale(HttpServletRequest request, HttpServletResponse response) { super.processLocale(request, response); try { request.setCharacterEncoding("utf-8"); } catch (Exception ex) {} }
2>. 在struts-config.xml文件中配置SqeRequestProcessor。用户重写了RequestProcessor ,但Struts 并不知道,必须配置才可以。下面是配置本示例:
<controller> <set-property property="processorClass" value="sqe.janier.struts.SqeRequestProcessor" /> <set-property property="contentType" value="text/html; charset=utf-8" /> <set-property property="nocache" value="true"/> </controller>在Struts 1.1后,新增了<controller>标签,它可以用于指定ActionServlet的一些参数,在Struts 1.1之前,这些参数是在<init-params>中加以指定,使用<controller>标签,应用程式中不同的模组也可以指定各自的参数给ActionServlet。
注意:重写RequestProcessor的方法时,别忘了使用super来调用父类的动作。
2. 扩展ActionServlet
通常是将ActionServlet当作黑盒子,只要使用它,然而也可以继承ActionServlet来定义自己的控制器,但由于在Struts 1.1后大部份的请求已经委托RequestProcessor来处理,继承ActionServlet来定义自己的控制器处理请求意义已经不大,通常的目的是重新定义ActionServlet的init()方法,增加自己的初始化动作。
如果需要在开始处理请求,或者处理结束之后加入自己的处理时,可对ActionServlet进行扩展。例如解决中文的编码问题。
ActionServlet接收处理请求参数时,并不是按UTF-8的解码方式处理请求,因此容易形成乱码。为了解决该问题,可以强制指定ActionServlet使用GBK的解码方式。实现该功能只需两步骤。
1>. 继承ActionServlet ,实现自定义处理方法:
public class MyActionServlet extends ActionServlet {
protected void process(HttpServletRequest request, HttpServletResponse response)
throws IOException,ServletException {
request.setCharacterEncoding("UTF-8");
super.process(request,response);
}
}
在本示例中,重写了process方法,该方法是ActionServlet处理用户请求的方法。当然,该方法会调用RequestProcossor 处理,首先在重写该方法的第一行设计解码方式,然后调用父类的方法。
2>. 在struts-config中配置扩展
在web.xml文件中配置MyActionServlet。由于系统改变了ActionServlet,因此必须使用MyActionServlet来拦截所有的用户请求。
下面是MyActionServlet的配置代码:
<servlet>
<!-- 配置核心处理器 -->
<servlet-name>action</servlet-name>
<!-- 使用自己的核心处理器 -->
<servlet-class>MyActionServlet</servlet-class>
<!-- 配置自动加载 -->
<load-on-startup>1<load-on-startup>
</servlet>