概述
只要看过我之前的项目的同学一定会发现,哪些项目的配置相当复杂、繁琐!并且一个类对应一个请求,一个请求对应一个ActionForm,这对于真正的项目开发来说是一个巨大的BUG般的存在,不合理、非常不合理、完全不合理!这些不合理在Struts1当然不能存在。所以我们今天就讲讲怎么让一个类可以对应多个请求,多个请求怎么对应一个ActionForm。这样开发效率、配置量都会大大的减少.
首先,我们从配置文件里面开始讲怎么利用DispatchAction写Struts1项目,这个配置文件和我上文讲的没有多大的区别,只不过多加这个标签,启动这个parameter对应的值可以随便你取
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<!-- 配置所有的formbean,每个formbean都可以用一个<form-bean>类指定-->
<form-beans>
<form-bean name="UserBean" type="com.xingyao.model.UserBean"></form-bean>
</form-beans>
<!-- 配置具体接受action请求的信息,每一个action请求都可以用一个<action>来指定 -->
<action-mappings>
<!-- 配置action信息,其中
path表示用户form请求路径;
type表示服务器组件action的类;
name表示formBean组件;
scope表示将FormBean封装到那个域中
validate表示是否要验证该formBean
-->
<action
path="/user/test"
type="com.xingyao.action.LoginAction"
name="UserBean"
scope="request"
parameter="command1"
>
<!-- 具体请求的时候,得到返回结果,需要跳转(转发)的页面 -->
<forward name="success" path="/WEB-INF/JSP/success.jsp"></forward>
<forward name="error" path="/WEB-INF/JSP/error.jsp"></forward>
</action>
</action-mappings>
</struts-config>
然后我们来看看jsp页面的设计,这里我们需要注意的是:你请求的do?后面的command这个字符串需要与你配置文件里面 对应,然后就是需要注意jsp页面的command=”属性值”不能为execute或者为perform。为什么下面讲解源码会列出来
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
</head>
<body>
<a href="user/test.do?command=add">添加功能</a>
<a href="user/test.do?command=delete">删除功能</a>
</body>
</html>
我们在来看看DispatchAction吧,其实这里并没有什么需要讲的,用法和实现Action类是一样的,只不过可以用方法接受用户的请求。需要注意的是:方法名要和jsp页面配置的command的属性值一样
package com.xingyao.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
/**
* 登入功能的action
* @author xingyao
* @since 2016-8-24
*/
@SuppressWarnings("all")
public class LoginAction extends DispatchAction{
/**
* 添加用户功能
*/
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
request.setAttribute("message", "添加成功");
//返回结果,拥有返回页面的判断,参照配置文件(struts-config.xml)里面的<forward name="success" path="/WEB-INF/JSP/success.jsp"></forward>
return mapping.findForward("success");
}
/**
* 删除用户功能
*/
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
request.setAttribute("message", "删除成功");
//返回结果,拥有返回页面的判断,参照配置文件(struts-config.xml)里面的<forward name="success" path="/WEB-INF/JSP/success.jsp"></forward>
return mapping.findForward("success");
}
}
啦啦啦啦啦,讲到源码分析了,源码分析主要讲解两个问题:DispatchAction的执行原理;和为什么不能使用execute和perform属性,如果使用了会产生什么样的情况
1、DispatchAction的实现原理
/**
*
1、通过ActionMapping得到设置的parameter的属性值,假设为A
*
2、通过A得到表单参数对应的值。如果xxx.do?A="add",
*
3、通过反射调用add方法
*/
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
//这里是得到<action paramter="属性值">
String parameter = mapping.getParameter();
//判断属性值是否为null
if (parameter == null) {
String message =
messages.getMessage("dispatch.handler", mapping.getPath());
log.error(message);
throw new ServletException(message);
}
//通过上面得到是属性值再从request域里面得到表单参数的值,这个就是在DispatcherAction里面对应的方法名
String name = getMethodName(mapping, form, request, response, parameter);
//这里就是为什么方法名不能为execute和perform的原因
if ("execute".equals(name) || "perform".equals(name)){
String message =
messages.getMessage("dispatch.recursive", mapping.getPath());
log.error(message);
throw new ServletException(message);
}
// Invoke the named method, and return the result
return dispatchMethod(mapping, form, request, response, name);--------------------------见详细讲解1
}
—————————————————————详细讲解1—————————————————————–
/**
* Dispatch to the specified method.
* @since Struts 1.1
*/
protected ActionForward dispatchMethod(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response,
String name) throws Exception {
Method method = null;
try {
//通过方法名,得到方法对象------------------------------------------------具体的见详细讲解2
method = getMethod(name);
} catch(NoSuchMethodException e) {}
ActionForward forward = null;
try {
//封装方法调用需要的参数
Object args[] = {mapping, form, request, response};
//利用反射调用方法,得到方法返回的对象
forward = (ActionForward) method.invoke(this, args);
} catch(ClassCastException e) {
******省略其他的异常代码
}
return (forward);
}
————————————————————具体的见详细讲解2———————————————————–
我们先来了解下这个方法用到的全局变量
public abstract class DispatchAction extends Action {
//这里的this,是你继承了DisPatchAction的类的对象的引用
protected Class clazz = this.getClass();
//这个methods存放了你继承DispatchAction类里面的所有方法
protected HashMap methods = new HashMap();
//存放了方法里面参数的类型
protected Class[] types =
{
ActionMapping.class,
ActionForm.class,
HttpServletRequest.class,
HttpServletResponse.class
};
protected Method getMethod(String name)
throws NoSuchMethodException {
synchronized(methods) {
//这个方法先通过name到methods里面得到Method对象
Method method = (Method) methods.get(name);
if (method == null) {
//如果为空,这通过反射方法名,以及方法参数对象到this类里面对应name的方法对象
method = clazz.getMethod(name, types);
//然后在将该方法对象存入到methods里面
methods.put(name, method);
}
return (method);
}
}
将完了DispatchAction的执行原理了,我们也了解了为什么不能使用Execute和perform做方法名了,那么如果用了怎么办呢?当你用了execute方法做为方法名,那么就相当于你重写了Action的execute方法,这样就相当于你这个action只能执行一个方法,也就是execute方法,你配置的其他方法名是作为一个参数被request接受,而不能作为方法的反射对象的name被程序执行。
讲到这里,大家是不是爱上了
转载请标明出处
感谢苏波老师的指导
个人见解、错误请指出!请莫怪
最后
以上就是合适春天为你收集整理的Struts1框架七之DispatchAction的说明的全部内容,希望文章能够帮你解决Struts1框架七之DispatchAction的说明所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复