在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包含了如下主要方法。
- ActionForm processActionForm(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping): 填充ActionForm時執行該方法。
- Action processActionCreate(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException: 調用Action時調用該方法。
- boolean processPreprocess(HttpServletRequest request,HttpServletResponse response): 預處理用戶請求時執行該方法。
- boolean processValidate(HttpServletRequest request,HttpServletResponse response, ActionForm form, ActionMapping mapping)throws IOException, ServletException, InvalidCancelException: 處理輸入校驗時調用該方法。
擴展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>