struts1.0的配置
在web.xml文件中的配置
<servlet>
<!--配置ActionServlet类,一启动就创建该类对象-->
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<!--配置struts-config.xml文件的位置,默认从WEN-INF/下找文件名为struts-config.xml文件 如果是按照默认路径和默认文件名存放的配置文件,就可以不用配置,但是建议配置-->
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml<param-value>
</init-param>
<!-- 错误日志配置,一旦出错会自动生成错误日志 -->
<init-param>
<param-name>debug</param-name>
<param-value>2<param-value>
</init-param>
<!-- 对xml文件的解析日志 -->
<init-param>
<param-name>detail</param-name>
<param-value>2<param-value>
</init-param>
<!--配置为:tomcat一启动就创建ActionServlet类的对象 这个一定要记得配置-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!--处理所有的.do请求-->
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
在struts-config.xml文件中的配置
<action-mappings>
<!--
action标签 每个请求对应一个action配置,
path:请求路径 与发送请求的表单的action=””对应,只是多了个斜杠
name:对应的表单bean name,与 form-bean标签中的name属性相同
scope:存储的域 默认为session 建议存储在request域中
type:指明Action子类的全路径名 (包名+类名)
-->
<action path="" name="" scope="" type="">
<!--
forward标签是指定跳转信息
name:跳转的名字,通过名字找到path
path:指定要跳转到的jsp页面
redirect:指定跳转方式,默认为false 为true的时候表示客户端跳转,为false的时候表示服务端跳转
-->
<forward name="" path="" redirect=""></forward>
</action>
</action-mappings>
<!--
form-bean标签对应form对象 继承ActionForm的子类
name:指定收集表单数据的对象名
type:指定ActionForm子类的全路径名(包名+类名)
-->
<form-beans>
<form-bean name="" type=""></form-bean>
</form-beans>
自己对于struts1.0执行流程的理解:
tomcat服务器一启动,就创建ActionServlet对象 ModuleConfig对象 ModuleConfig对象中封装了三个Map集合
1、 : Map actionConfigs = new HashMap();//用来存储ActionMapping对象的集合, action标签中的path属性的属性值作为该集合的key,ActionMapping对象作为集合的value
actionConfigs.put(path,new ActionMapping());//往集合中添加数据
ActionMapping mapping=actionConfigs.get(path);//通过path取出ActionMapping对象 path作为actionConfigs集合的key,ActionMapping对象作为actionConfigs集合的value
mapping.getName();//通过ActionMapping对象得到<action>标签中的name属性对应的属性值 (与form-bean标签的name值相同,formBeans正好使用这个值取得FormBeanConfig对象)
mapping.getScope();//通过ActionMapping对象得到<action>标签中的scope属性对应的属性值 (确定ActionForm对象的存储域,一般是session 或 request)
mapping.getType();//通过ActionMapping对象得到<action>标签中的type属性对应的属性值 --(类的全路径名,通过这个值来创建Action对象)
mapping.getValidate();//通过ActionMapping对象得到<action>标签中的validate属性对应的属性值, (确定是否对收集的表单数据做验证,默认为true ,设值为false的时候不验证)
2、 : Map formBeans = new HashMap();//用来存储FormBeanConfig对象的集合,form-bean标签中的name属性作为该集合的key,FormBeanConfig对象作为集合的value
formBeans.put(name,new FormBeanConfig());//往集合中添加数据
FormBeanConfig form=formBeans.get(name);//通过《action》标签中的name属性值取出FormBeanConfig对象,name是map集合formBeans中的key,FormBeanConfig对象为formBeans集合的value
form.getType();//通过FormBeanConfig对象得到<form-bean>标签中的type属性对应的属性值 (类的全路径名,用来创建ActionFrom对象)
3、 : Map forwards = new HashMap();//用来存储ActionForward对象的集合,forward标签中的name属性作为该集合的key,ActionForward对象作为该集合的value。
forwards.put(name,new ActionForward());//往集合中添加数据
ActionForward forward = forwards.get(name);//通过name属性得到ActionForward对象,name为forwards集合中的key,ActionFoward对象为forwards集合中的value
forwards.getRedirect();//通过ActionForward对象得到<froward>标签中的redirect属性对应的属性值, (确定跳转方式,默认为false 服务端跳转,设值为true的时候为客户端跳转)
forwards.getPath();//通过ActionForward对象得到<forward>标签中的path属性对应的属性值(得到跳转路径,确定跳转的目的jsp页面)
执行流程
ActionServlet对象一创建,就将struts-config.xml文件读到内存中,ModuleConfig对象存在整个配置文件中的信息
用户发*.do请求时,tomcat会自动把请求交给ActionServlet对象处理(也可以说是交给struts处理),
ActionServlet会调用根据发送请求的方式调用本身的doGet()或者doPost()方法。
//ActionServlet类中的doGet()方法
public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{
process(request,response);//调用ActionServlet类中的process方法处理请求
}
//ActionServelt类中的doPost()方法
public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{
process(request,response);//调用ActionServlet类中的process方法处理请求
}
//ActionServlet类中的process方法(在这个process方法中完成对请求的处理全部流程,从请求字符串的截取(processPath)—>ActionMapping对象的创建(processMapping)—>ActionForm对象的创建(processActionForm)—>表单数据的收集(processPopulate)—>Action对象的创建(processActionCreate)—>Action对象的execute的方法的执行(processActionPerform)—>完成跳转(processForwardConfig))
protected void process(HttpServletRequest request,HttpServlet
Response response)throws IOException, ServletException {
ModuleConfig config = getModuleConfig(request);//config为ModuleConfig对象
RequestProcessor processor = getProcessorForModule(config);//通过ModuleConfig对象创建RequestProcessor对象
processor.process(request, response);//调用RequestProcessor类的process()方法
}
//RequestProcessor类中的process()方法
public void process(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException {
String path=processPath(request,response); //调用RequestProcessor类的processPath ()方法
//RequestProcessor类中的processPath()方法,返回path
protected String processPath(HttpServletRequest request,HttpServletResponse response) throws IOException {
String url=request.getContextPath();//获取除项目名以外的项目全路径名
(例如:请求路径 http://localhost:8080/struts1.0/login.do? username="dfx"& password="123" url=" /login.do?username="dfx" &password="123" 这里就算是post请求,表单中的参数名和参数值都会发送过来,只是被封装在协议体中,不显示而已 ")
int index=url.lastIndexOf(".");//找到从请求字符串从最后一个位置开始反向搜索,第一次出现(.)的位置 ,这里index=6;
int start=ur.lastIndexOf("/");//找到请求字符串中从最后一个位置开始反向搜索,第一次出现(/)的位置,这里start=0;
//截取请求 作为path
String path=url.substring(start,index);//这里的 path= “/login” ;
}
//调用RequestProcessor类中的processMapping()方法得到ActionMapping对象
ActionMapping mapping = processMapping(request, response, path);
//RequestProcessor类中processMapping()
protected ActionMapping processMapping(HttpServletRequest request, HttpServletResponse response, String path)throws IOException {
//调用ModuleConfig接口中的findActionConfig()方法取得ActionMapping对象
ActionMapping mapping = (ActionMapping)moduleConfig.findActionConfig(path);
}
//ModuleConfig实现类中的findActionConfig()方法 (该方法中的actionConfigs是Map集合,该map集合的key为path,value为ActionMapping对象)
public ActionConfig findActionConfig(String path) {
ActionConfig config = (ActionConfig) actionConfigs.get(path);//通过key (path)取出map集合中的value值(ActionMapping对象)
return config;//返回ActionConfig对象(ActionMapping是ActionConfig的子类)
}
//取出ActionMapping对象后,调用RequestProcessor类中的processActionForm()方法得到ActionForm对象
ActionForm form = processActionForm(request, response, mapping);
//RequestProcessor类中的processActionForm()方法
protected ActionForm processActionForm(HttpServletRequest request,HttpServletResponse response, ActionMapping mapping) {
//调用RequestUtils类中的静态方法 createActionForm()创建ActionForm对象
ActionForm instance = RequestUtils.createActionForm(request, mapping, moduleConfig, servlet);
return instance;//返回ActionForm对象
}
//RequestUtils类中的静态方法 createActionForm()
public static ActionForm createActionForm(HttpServletRequest request,ActionMapping mapping, ModuleConfig moduleConfig, ActionServlet servlet) {
String name = mapping.getName();//通过ActionMapping对象得到<action>标签中name属性对应的属性值(这个name属性和《form-bean》标签中的name属性是一样的)
//通过name属性值,调用ModuleConfig接口中的moduleConfig.findFormBeanConfig()方法得到FormBeanConfig对象
FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
《
//ModuleConfig接口实现类中的方法findFormBeanConfig()
public FormBeanConfig findFormBeanConfig(String name) {
//formbeans为map集合,该集合中的key为<form-bean>标签中的name属性值,value为FormBeanConfig对象
return ((FormBeanConfig) formBeans.get(name));//所以这里可以通过formBeans.get(name)取得value FormBeanConfig对象
}
》
//调用RequestUtils类中的lookupActionForm()方法,得到ActionForm对象
ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());
《
// RequestUtils类中的lookupActionForm()方法
private static ActionForm lookupActionForm(HttpServletRequest request, String attribute, String scope)
{
//ActionForm类型变量用来接收ActionForm对象
ActionForm instance = null;
HttpSession session = null;
if ("request".equals(scope)) {//判断ActionForm对象是否被指定存储在request域中
/*判断是request域的时候,就从request域中取出ActionForm对象
注:这里的getAttribute()方法是指从request中取出属性值,
attribute作为默认属性名,如果attribute属性不存在就从name属性中取值 name属性中存放的是ActionForm对象存储在内置对象中的属性名,内置对象的属性值为 ActionForm对象
例如: request.setAttribute("loginForm",new LoginForm()); //这里 name="loginform" ,getAttribute(name),取出来的便是ActionForm对象
*/
instance = (ActionForm) request.getAttribute(attribute);
} else {
session = request.getSession();//如果ActionForm对象是否被指定存储在session域中,
instance = (ActionForm) session.getAttribute(attribute);//这里的解释和request域雷同
}
return (instance);
}
》
//调用RequestUtils类中的createActionForm()方法创建ActionForm对象
return createActionForm(config, servlet);
《
//RequestUtils类中的createActionForm()方法
public static ActionForm createActionForm(FormBeanConfig config, ActionServlet servlet){
ActionForm instance = null;
try {
//通过FormBeanConfig对象,调用FormBeanConfig类的createActionForm()方法创建ActionForm对象
instance = config.createActionForm(servlet);
《
//FormBeanConfig类的createActionForm()方法
public ActionForm createActionForm(ActionServlet servlet) throws IllegalAccessException, InstantiationException {
Object obj = null;
//调用FormBeanConfig类中的formBeanClass()方法创建 Object类型的对象
obj = formBeanClass().newInstance();
《
//FormBeanConfig类中的formBeanClass()方法
protected Class formBeanClass() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();//加载该对象
try {
return (classLoader.loadClass(getType()));//<form-bean>标签中的type属性(类全路径名)对应的类对象,暂时定义为Object类型
} catch (Exception e) {
return (null);
}
}
》
ActionForm form = null;
if (obj instanceof ActionForm) {
form = (ActionForm)obj;//将FormBeanConfig类中的formBeanClass()方法得到的type指定的类对象造型为ActionForm类型
}
form.setServlet(servlet);
return form; //返回ActionForm对象
}
》
} catch(Throwable t) {
log.error(servlet.getInternal().getMessage("formBean", config.getType()), t);
}
return (instance);
}
》
}
//调用RequestProcessor类中的processPopulate()方法,将表单中的数据封装到表单bean中 (ActionForm对象中)
processPopulate(request, response, form, mapping);
// RequestProcessor类中的processPopulate()方法
protected void processPopulate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping) throws ServletException {
if (form == null) {
return;
}
form.setServlet(this.servlet);
form.reset(mapping, request);//在收集表单中的数据到表单bean中之前,调用reset()方法,初始化数据
//调用RequestUtils类中的populate()方法,收集表单数据
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(), request);
《
//RequestUtils类中的populate()方法
public static void populate(Object bean,String prefix,String suffix, HttpServletRequest request) throws ServletException {
HashMap properties = new HashMap();//创建map集合,表单中的参数名和参数值分别作为key和value存储在该集合中
Enumeration names = null;//创建Enumeration集合,迭代出request内置对象(域)中的所有参数名和参数值
names = request.getParameterNames();//迭代出封装在request内置对象中的所有参数名
while (names.hasMoreElements()) {
String name = (String) names.nextElement();//迭代取得request内置对象中参数名 (假若是个登录表单:第一个取出 username ,第二次取出password)
String stripped = name;//将参数名保存在临时变量中,作为map集合的key
Object parameterValue = null;
//得到request内置对象的参数名对应的参数值(假若是个登录表单:参数名为 username对应的参数值为“admin” ,参数名password对应的参数值为“123”)
parameterValue = request.getParameterValues(name);
properties.put(stripped, parameterValue);//将参数名和参数值分别作为key和value存储到map集合中
}
try {
//调用BeanUtils中的populate()方法
BeanUtils.populate(bean, properties);
《
//BeanUtils中的populate()方法
public static void populate(Object bean, Map properties)throws IllegalAccessException, InvocationTargetException {
if ((bean == null) || (properties == null)) {
return;
}
//先将map集合转换成Set集合,然后调用iterator()方法进行迭代输出(map集合中存放的是request内置对象中的参数名和参数值)
Iterator names = properties.keySet().iterator();
while (names.hasNext()) {
String name = (String) names.next();//得到request内置对象中的参数名 username
Object value = properties.get(name);//参数名name作为key,map.get(name)得到value值,request内置对象中的参数值 "admin"
/*bean:为ActionForm对象,name为参数名 (username),value为参数值(admin)//这句代码的意思就是将request内置对象中的参数名和参数值设置到ActionForm对象(bean)中。
*/
setProperty(bean, name, value);
注:表单bean ActionForm对象 bean会从表单中找到和它属性名相同的参数名进行收集,并且只收集属性名相同的表单参数,和属性名不同参数名的不会被收集。找到对应的属性名的参数,调用set方法,设值(这里会找到与name对应的表单bean的属性进行设值。比如:当name为username时,bean.setUsername(value); 当name为password时,bean.setPasswrod(value); value的值和name值一 一对应)
}
}
》
} catch(Exception e) {
throw new ServletException("BeanUtils.populate", e);
} finally { }
}
》
//在RequestProcessor类中的process()方法中调用processActionCreate()方法创建Action对象(使用map单例+同步方法创建保证安全性)
Action action = processActionCreate(request, response, mapping);
《
//RequestProcessor类中的processActionCreate()方法
protected Action processActionCreate(HttpServletRequest request,HttpServletResponse response, ActionMapping mapping) throws IOException {
String className = mapping.getType();//得到type属性值,也就是继承Action类的类全路径名(cn.action.LoginAction)
Action instance = null;
synchronized (actions) {
//actions是一个map集合 ,HashMap actions=new HashMap();//该map集合的key为type属性值(cn.action.LoginAction),value为type类名对应的类对象
instance = (Action) actions.get(className);//先从map中type对应的类对象,取到了就直接返回(保证单例)
if (instance != null) {
return (instance);
}
try {
//从map集合中没有取到Action对象时,就通过反射创建该对象
instance = (Action) RequestUtils.applicationInstance(className);
} catch (Exception e) {
}
instance.setServlet(this.servlet);
actions.put(className, instance);//将继承Action类的类名和类对象分别作为key和value存入map集合中
}
return (instance);
}
》
//在RequestProcessor类中的process()方法中调用processActionPerform()方法创建ActionFoward对象
ActionForward forward = processActionPerform(request, response, action, form, mapping);
《
//RequestProcessor类中的processActionPerform()方法
protected ActionForward processActionPerform(HttpServletRequest request, HttpServletResponse response, Action action, ActionForm form,
ActionMapping mapping) throws IOException, ServletException {
try {
return (action.execute(mapping, form, request, response));//执行Action对象的execute()方法,返回值为ActionForward对象
} catch (Exception e) {
return (processException(request, response, e, form, mapping));
}
}
》
//在RequestProcessor类中的process()方法中调用processForwardConfig()转向信息方法
processForwardConfig(request, response, forward);
《
//RequestProcessor类中的processForwardConfig()方法,完成跳转
protected void processForwardConfig(HttpServletRequest request, HttpServletResponse response,ForwardConfig forward)
throws IOException, ServletException {
if (forward == null) {//先判断转向对象是否为null,为null的时候表示不是要struts提供的转向方法,使用自己写的跳转信息
return;
}
String forwardPath = forward.getPath();//通过ForwardConfig对象获得<forward>标签中的path 转向路径 例如 “/success.jsp”
String uri = null;
if (forward.getRedirect()) {//判断跳转方式,为true的时候表示客户端跳转
response.sendRedirect(response.encodeRedirectURL(uri));
} else {
//这里调用RequestProcessor类中的doForward()方法完成服务端跳转
doForward(uri, request, response);//为false的时候表示服务端跳转(默认为false 服务端跳转)
《
//RequestProcessor类中的doForward()方法
protected void doForward( String uri, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);
rd.forward(request, response);
》
}
}
》
}