Struts1的基础知识

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);

}

}

}

上一篇:CentOS环境下tomcat启动超级慢的解决方案


下一篇:〖Linux〗noip免费域名申请,及更新域名的API