下面以用戶登錄爲例:部分需要參考的配置文件如下:
<form-beans >
<form-bean name="loginForm" type="com.hundsun.struts.form.LoginForm" />
</form-beans>
<action-mappings >
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="com.hundsun.struts.action.LoginAction" />
</action-mappings>
struts有一箇中央控制器ActionServlet,負責處理用戶的url請求,ActionServlet在web.xml文件中配置,它繼承了HttpServlet,其實就是一個普通的servlet。ActionServlet中有兩個方法,如下:
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
process(request, response);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
process(request, response);
}
ActionServlet會自動調用doGet()或doPost()方法。從中可以看出doGet(),doPost()直接調用了process(request, response)方法:
protected void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
ModuleUtils.getInstance().selectModule(request, getServletContext());
ModuleConfig config = getModuleConfig(request);
RequestProcessor processor = getProcessorForModule(config);
if (processor == null) {
processor = getRequestProcessor(config);
}
processor.process(request, response);
}
process方法繼續調用RequestProcessor 的process(request, response)方法,process的部分源代碼如下:
public void process(HttpServletRequest request,
HttpServletResponse response){
request = processMultipart(request);
String path = processPath(request, response);
if (path == null) {
return;
}
ActionMapping mapping = processMapping(request, response, path);
if (mapping == null) {
return;
}
ActionForm form = processActionForm(request, response, mapping);
processPopulate(request, response, form, mapping);
if (!processForward(request, response, mapping)) {
return;
}
Action action = processActionCreate(request, response, mapping);
if (action == null) {
return;
}
ActionForward forward =
processActionPerform(request, response,
action, form, mapping);
processForwardConfig(request, response, forward);
}
processMultipart(request);主要是用來處理file域,其實就是重寫request得到屬性的方法。
String path = processPath(request, response);截取用戶提交的url地址,該方法主要的兩句代碼如下:
int slash = path.lastIndexOf("/");
int period = path.lastIndexOf(".");
此時的path="/login";接着我們來看
ActionMapping mapping = processMapping(request, response, path);主要源代碼如下:
protected ActionMapping processMapping(HttpServletRequest request,
HttpServletResponse response,
String path)
throws IOException {
ActionMapping mapping = (ActionMapping)
moduleConfig.findActionConfig(path);
ActionConfig configs[] = moduleConfig.findActionConfigs();
for (int i = 0; i < configs.length; i++) {
if (configs[i].getUnknown()) {
mapping = (ActionMapping) configs[i];
request.setAttribute(Globals.MAPPING_KEY, mapping);
return (mapping);
}
}
}
我們先看ActionMapping mapping = (ActionMapping)moduleConfig.findActionConfig(path)方法。
moduleConfig類是個接口,他的實現類是moduleConfigImpl
public ActionConfig findActionConfig(String path) {
ActionConfig config = (ActionConfig) actionConfigs.get(path);
return config;
}
actionConfigs是個hashmap通過key=path="/login"獲取,actionConfigs的這個值是在struts初始化的時候放進去的。
ok,現在ActionMapping已經得到,一個ActionMapping就是對應一個<action/>標籤,它的key爲 <action/>標籤中的path的值,這裏爲"/login",其餘的<action/>標籤中的屬性值就是value。
下面看:ActionForm form = processActionForm(request, response, mapping);
protected ActionForm processActionForm(HttpServletRequest request,
HttpServletResponse response,
ActionMapping mapping) {
ActionForm instance = RequestUtils.createActionForm
(request, mapping, moduleConfig, servlet);
if (instance == null) {
return (null);
}
if ("request".equals(mapping.getScope())) {
request.setAttribute(mapping.getAttribute(), instance);
} else {
HttpSession session = request.getSession();
session.setAttribute(mapping.getAttribute(), instance);
}
return (instance);
}
先看ActionForm instance = RequestUtils.createActionForm(request, mapping, moduleConfig, servlet);
public static ActionForm createActionForm(
HttpServletRequest request,
ActionMapping mapping,
ModuleConfig moduleConfig,
ActionServlet servlet) {
// Is there a form bean associated with this mapping?
String attribute = mapping.getAttribute();
if (attribute == null) {
return (null);
}
String name = mapping.getName();
FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());
return createActionForm(config, servlet);
}
String attribute = mapping.getAttribute();是來找attribute="loginForm"如果沒有就直接返回,因爲formbean我們不一定要創建。
這句String name = mapping.getName();是得到form的名字 name="loginForm"
接着是FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
public FormBeanConfig findFormBeanConfig(String name) {
return ((FormBeanConfig) formBeans.get(name));
}
formBeans也是個hashmap,裏面存放的就是一個個<form-bean/>標籤這裏例子中的key="loginForm"
現在我們得到了一個FormBeanConfig。接着:
ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());
private static ActionForm lookupActionForm(HttpServletRequest request, String attribute, String scope)
{
ActionForm instance = null;
HttpSession session = null;
if ("request".equals(scope)) {
instance = (ActionForm) request.getAttribute(attribute);
} else {
session = request.getSession();
instance = (ActionForm) session.getAttribute(attribute);
}
return (instance);
}
先在request和session找下是否存在這個FormBean,如果有就直接返回。如果instance爲空,就繼續創建createActionForm(config, servlet);
public static ActionForm createActionForm(FormBeanConfig config, ActionServlet servlet)
{
ActionForm instance = null;
instance = config.createActionForm(servlet);
return (instance);
}
public ActionForm createActionForm(ActionServlet servlet)
throws IllegalAccessException, InstantiationException {
Object obj = null;
// Create a new form bean instance
if (getDynamic()) {
obj = getDynaActionFormClass().newInstance();
} else {
obj = formBeanClass().newInstance();
}
ActionForm form = null;
if (obj instanceof ActionForm) {
form = (ActionForm)obj;
} else {
form = new BeanValidatorForm(obj);
}
return form;
}
通過動態代理得到一個formBean。
好了,現在我們看 Action action = processActionCreate(request, response, mapping);
protected Action processActionCreate(HttpServletRequest request,
HttpServletResponse response,
ActionMapping mapping)
throws IOException {
String className = mapping.getType();
Action instance = null;
synchronized (actions) {
instance = (Action) actions.get(className);
if (instance != null) {
return (instance);
}
instance = (Action) RequestUtils.applicationInstance(className);
instance.setServlet(this.servlet);
actions.put(className, instance);
}
return (instance);
}
String className = mapping.getType();得到的就是action的完整路徑名,這裏爲com.hundsun.struts.action.LoginAction
synchronized (actions) actions是個hashmap,loginAction存在就返回,這裏進行了同步,也就是說只會創建一個loginAction實例。接下看下面的代碼,如果不存在就調用instance = (Action) RequestUtils.applicationInstance(className)
public static Object applicationInstance(String className)
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
return (applicationClass(className).newInstance());
}
返回一個loginAction實例。
ActionForward forward =processActionPerform(request, response,action, form, mapping);
protected ActionForward
processActionPerform(HttpServletRequest request,
HttpServletResponse response,
Action action,
ActionForm form,
ActionMapping mapping)
throws IOException, ServletException {
return (action.execute(mapping, form, request, response));
}
這裏直接調用了action類的execute方法,返回一個ActionForward,ActionForward類裏存放着對應<action/>標籤下的所有的forward信息。最後執行processForwardConfig(request, response, forward);
protected void processForwardConfig(HttpServletRequest request,
HttpServletResponse response,
ForwardConfig forward)
throws IOException, ServletException {
if (forward == null) {
return;
}
String forwardPath = forward.getPath();
String uri = null;
if (forwardPath.startsWith("/")) {
uri = RequestUtils.forwardURL(request, forward, null);
} else {
uri = forwardPath;
}
if (forward.getRedirect()) {
if (uri.startsWith("/")) {
uri = request.getContextPath() + uri;
}
response.sendRedirect(response.encodeRedirectURL(uri));
} else {
doForward(uri, request, response);
}
}
。。。。。
分兩種情況進行轉發,一種是: response.sendRedirect(response.encodeRedirectURL(uri));
另二種是:doForward(uri, request, response);該方法裏主要的兩句代碼是:
RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);
rd.forward(request, response);
OVER!
轉自http://lovedance.blogbus.com/logs/36997014.html