疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Struts1配置及调用过程实例详解


 

        MVC架构是目前web开发中的经典架构,它的核心思想就是将业务代码和视图代码分离,能够有效的理清系统结构,降低系统复杂度和维护难度。在传统的java web开发中采用servlet作为控制器将视图和模型分离,实现MVC架构模式。有过开发经验的人都明白即便严格按照MVC规范进行开发,在实际的项目管理尤其是后期维护阶段所带来的巨大工作量简直令人望而生畏,更何况在实际开发中真正能够严格按照MVC进行发说起来容易做起来其实是很困难的。正是在这样的背景下struts应运而生了。在实例介绍struts的使用之前我们首先要弄清楚以下三点:
 
  1.      struts到底是什么?
 
  其实说的简单一点struts是一个实现了MVC架构的框架。它无余地的规范了MVC开发的整个过程,换句话说只要使用struts框架进行开发那么一定是遵循MVC架构的,不给你“出轨”的机会。
 
  2.      struts是怎样规范MVC架构开发模式的,它的内部执行机制是怎样的?
 
  (1)      客户端的请求以Http的方式传递到服务器上的,首先会执行规范检测,只要是符合struts规范的请求都会提交到ActionServlet上。
 
  (2)      ActionServlet所充当的角色可以看成是一个中央控制器,它对客户端的请求进行拦截,然后截取URL,根据URL取得struts-config.xml文件中的配置信息,将配置信息封装到ActionMapping对象中,并将该对象传递给所请求的对象RealAction。
 
  (3)      根据配置信息实例化相应的ActionForm对象,并将传过来的表单参数进行打包然后赋给ActionForm对象的各个属性。
 
  (4)      根据配置信息实例化用户所请求的对象RealAction,并将上面接受了表单数据的ActionForm对象传递给请求对象RealAction。该RealAction是继承了struts框架中Action类的对象。它持有一个execute()方法,这个方法是所有继承了Action类的核心方法,所有的业务逻辑控制都是在这个方法中完成的。也就是说在这个方法中我们可以与Model层打交道,实现业务逻辑控制和数据的持久化等操作。
 
  (5)      Execute()方法执行完毕之前会将执行的结果以ActionForward对象的形式返回给ActionServlet,这个返回结果是根据传递过来的ActionMapping中的forward标签决定页面跳转的。ActionServlet接收到新的跳转请求的时候再次重复这个过程直到将目的界面返回给用户。
 
  3.      使用struts和不是用struts的区别是什么?
 
  (1)      采用struts框架实现servlet的统一控制。传统的servlet开发中每写一个servlet都要在配置文件中,这就导致了当servlet很多的时候我们所看到的配置文件凌乱不堪。难于管理。采用struts框架,所有符合规范的请求将会统一交给ActionServlet进行处理,在struts-config.xml文件中根据配置决定由那个RealAction进行处理。
 
  (2)      在传统的servlet开发中,当处理完业务逻辑后具体的页面跳转是由每个servlet自己决定的,也就是说几乎每个servlet都有一条页面跳转代码,这样的话如果有N个servlet需要跳转到同一个页面,那相同的跳转语句需要重复写N次,更为重要的是如果后期需求变更,需要跳转到新的页面那么需要改动的代码也就有N次。采用struts框架能够解决这个问题,我们所需要做的仅仅是把跳转页置到<forward>标签中,需求变更的话只需改变配置文件即可。
 
  (3)      数据采集。Servlet开发中数据的采集是servlet接收到request,采用getParameter()方法取得表单数据,并且不能实现格式的自动转换。如果采用struts框架,定义好ActionForm后,ActionServlet会自动将表单数据加载到相应的ActionForm中并且实现数据类型的自动转换。
 
  说了这么多,那struts到底该怎样用呢?下面我们来介绍struts框架的搭建并通过一个简单的登录实例讲解struts的应用。
 
  1.      引入struts相关jar包。Struts相关jar包拷贝到WEB-INF/lib文件夹下。
 
  2.      配置Servlet。既然ActionServlet是Servlet,那么要使用这个Servlet同样需要将该Servlet配置到web.xml文件中(具体配置信息见下面实例)。
 
  3.      配置struts-config.xml文件。当Tomcat(本例中以Tomcat服务器为例),启动的时候实例化ActionServlet对象,在这个过程中便将struts-config.xml文件中的内容加载到内存中。
 
  Web.xml文件中的配置信息如下:
 
  [html]
 
  <?xml version="1.0" encoding="UTF-8"?>
 
  <web-app version="2.5"
 
  xmlns="java.sun.com/xml/ns/javaee"
 
  xmlns:xsi="www.w3.org/2001/XMLSchema-instance"
 
  xsi:schemaLocation="java.sun.com/xml/ns/javaee
 
  java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 
  <display-name></display-name>
 
  <welcome-file-list>
 
  <welcome-file>index.jsp</welcome-file>
 
  </welcome-file-list>
 
  <servlet>
 
  <servlet-name>action</servlet-name>
 
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 
  <init-param>
 
  <param-name>config</param-name>
 
  <param-value>/WEB-INF/struts-config.xml</param-value>
 
  </init-param>
 
  <load-on-startup>2</load-on-startup>
 
  </servlet>
 
  <!-- Standard Action Servlet Mapping -->
 
  <servlet-mapping>
 
  <servlet-name>action</servlet-name>
 
  <url-pattern>*.do</url-pattern>
 
  </servlet-mapping>
 
  </web-app>
 
  <?xml version="1.0" encoding="UTF-8"?>
 
  <web-app version="2.5"
 
  xmlns="java.sun.com/xml/ns/javaee"
 
  xmlns:xsi="www.w3.org/2001/XMLSchema-instance"
 
  xsi:schemaLocation="java.sun.com/xml/ns/javaee
 
  java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 
  <display-name></display-name>
 
  <welcome-file-list>
 
  <welcome-file>index.jsp</welcome-file>
 
  </welcome-file-list>
 
  <servlet>
 
  <servlet-name>action</servlet-name>
 
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 
  <init-param>
 
  <param-name>config</param-name>
 
  <param-value>/WEB-INF/struts-config.xml</param-value>
 
  </init-param>
 
  <load-on-startup>2</load-on-startup>
 
  </servlet>
 
  <!-- Standard Action Servlet Mapping -->
 
  <servlet-mapping>
 
  <servlet-name>action</servlet-name>
 
  <url-pattern>*.do</url-pattern>
 
  </servlet-mapping>
 
  </web-app>
 
该配置信息中<servlet-name>和<servlet-class>与之前使用的servlet开发中web.xml文件的含义是一样的都是配置servlet的路径。在<init-param>标签中所配置的内容为当该Servlet实例化的时候所加载的配置文件的路径。<servlet-mapping>所配置的内容可以解释为凡是以.do结尾的请求都会被提交给ActionServlet进行处理。
 
  Struts-config.xml中的配置信息:
 
  [html]
 
  <?xml version="1.0" encoding="ISO-8859-1" ?>
 
  <!DOCTYPE struts-config PUBLIC
 
  "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
 
  "jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
 
  <struts-config>
 
  <form-beans>
 
  <form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"/>
 
  </form-beans>
 
  <action-mappings>
 
  <action path="/login"
 
  type="com.bjpowernode.struts.LoginAction"
 
  name="loginForm"
 
  scope="request"
 
  >
 
  <forward name="success" path="/login_success.jsp"/>
 
  <forward name="error" path="/login_error.jsp"/>
 
  </action>
 
  </action-mappings>
 
  </struts-config>
 
  <?xml version="1.0" encoding="ISO-8859-1" ?>
 
  <!DOCTYPE struts-config PUBLIC
 
  "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
 
  "jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
 
  <struts-config>
 
  <form-beans>
 
  <form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"/>
 
  </form-beans>
 
  <action-mappings>
 
  <action path="/login"
 
  type="com.bjpowernode.struts.LoginAction"
 
  name="loginForm"
 
  scope="request"
 
  >
 
  <forward name="success" path="/login_success.jsp"/>
 
  <forward name="error" path="/login_error.jsp"/>
 
  </action>
 
  </action-mappings>
 
  </struts-config>
 
  <form-beans>配置的是装载表单数据的java类的路径。<action-mapping>标签中所path属性值为请求路径 ,type表示真正的请求对象,也就是上文中提到的RealAction。name 为装载表单数据的AcitonForm类,对应于相应的<form-beans>。<forward>标签对应便是各种条件下的跳转页面了。
 
  转载页面表单信息的LoginActionForm(即上文中提到的ActionForm):
 
  [java]
 
  package com.bjpowernode.struts;
 
  import org.apache.struts.action.ActionForm;
 
  @SuppressWarnings("serial")
 
  public class LoginActionForm extends ActionForm {
 
  private String username;
 
  private String password;
 
  public String getUsername() {
 
  return username;
 
  }
 
  public void setUsername(String username) {
 
  this.username = username;
 
  }
 
  public String getPassword() {
 
  return password;
 
  }
 
  public void setPassword(String password) {
 
  this.password = password;
 
  }
 
  }
 
  package com.bjpowernode.struts;
 
  import org.apache.struts.action.ActionForm;
 
  @SuppressWarnings("serial")
 
  public class LoginActionForm extends ActionForm {
 
  private String username;
 
  private String password;
 
  public String getUsername() {
 
  return username;
 
  }
 
  public void setUsername(String username) {
 
  this.username = username;
 
  }
 
  public String getPassword() {
 
  return password;
 
  }
 
  public void setPassword(String password) {
 
  this.password = password;
 
  }
 
  }
 
  接下来是最能体现Struts统一控制的LoginAction(即上文中提到的RealAction)中的代码,该java类具有一个execute函数,所有的业务逻辑操作以及操作的返回结果及决定跳转界面的操作均在该函数中进行:
 
  [java]
 
  package com.bjpowernode.struts;
 
  import javax.servlet.http.HttpServletRequest;
 
  import javax.servlet.http.HttpServletResponse;
 
  import org.apache.struts.action.Action;
 
  import org.apache.struts.action.ActionForm;
 
  import org.apache.struts.action.ActionForward;
 
  import org.apache.struts.action.ActionMapping;
 
  public class LoginAction extends Action {
 
  @Override
 
  public ActionForward execute(ActionMapping mapping, ActionForm form,
 
  HttpServletRequest request, HttpServletResponse response)
 
  throws Exception {
 
  LoginActionForm laf = (LoginActionForm)form;
 
  String username = laf.getUsername();
 
  String password = laf.getPassword();
 
  if("admin".equals(username) && "admin".equals(password)){
 
  //登录成功
 
  return mapping.findForward("success");
 
  }else{
 
  //登录失败
 
  return mapping.findForward("error");
 
  }
 
  }
 
  }
 
package com.bjpowernode.struts;
 
  import javax.servlet.http.HttpServletRequest;
 
  import javax.servlet.http.HttpServletResponse;
 
  import org.apache.struts.action.Action;
 
  import org.apache.struts.action.ActionForm;
 
  import org.apache.struts.action.ActionForward;
 
  import org.apache.struts.action.ActionMapping;
 
  public class LoginAction extends Action {
 
  @Override
 
  public ActionForward execute(ActionMapping mapping, ActionForm form,
 
  HttpServletRequest request, HttpServletResponse response)
 
  throws Exception {
 
  LoginActionForm laf = (LoginActionForm)form;
 
  String username = laf.getUsername();
 
  String password = laf.getPassword();
 
  if("admin".equals(username) && "admin".equals(password)){
 
  //登录成功
 
  return mapping.findForward("success");
 
  }else{
 
  //登录失败
 
  return mapping.findForward("error");
 
  }
 
  }
 
  }
 
  最后是客户端代码:
 
  [html]
 
  <%@ page language="java" contentType="text/html; charset=GB18030"
 
  pageEncoding="GB18030"%>
 
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "www.w3.org/TR/html4/loose.dtd">
 
  <html>
 
  <head>
 
  <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
 
  <title>Insert title here</title>
 
  </head>
 
  <body>
 
  <form action="login.do" method="post">
 
  用户:<input type="text" name="username"><br>
 
  密码:<input tyep="password" name="password"><br>
 
  <input type="submit" value="登录">
 
  </form>
 
  </body>
 
  </html>
 
  <%@ page language="java" contentType="text/html; charset=GB18030"
 
  pageEncoding="GB18030"%>
 
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "www.w3.org/TR/html4/loose.dtd">
 
  <html>
 
  <head>
 
  <meta http-equiv="Content-Type" content="text/html; charset=GB18030">
 
  <title>Insert title here</title>
 
  </head>
 
  <body>
 
  <form action="login.do" method="post">
 
  用户:<input type="text" name="username"><br>
 
  密码:<input tyep="password" name="password"><br>
 
  <input type="submit" value="登录">
 
  </form>
 
  </body>
 
  </html>
 
  在客户端中我们指定的action是“login.do”,以“.do”结尾的页面就是我们在web.xml文件中规定的哪些请求会被提交到ActionServlet上。在上文中空谈了很多Struts的执行机制大家可能还不能很好的理解,下面以这个登录例子为例我们来具体解释下Struts到底是怎样一个执行流程。
 
  1. 当Tomcat启动的时候根据配置文件中的<loadon-on-startup>标签中的值,ActionServlet伴随着Tomcat的启动而被实例化。
 
  2. ActionServlet被实例化后会加载struts-config.xml文件,将该文件中的配置信息以键值对的形式读到内存中。
 
  3. 当login页面被提交的时候由于该页面的action结尾是以.do结束的(也就说它符合在web.xml文件中规定的受struts规范的条件,该条件简单的来说就是只要请求是以.do结尾的就都受struts约束),该请求会被提交到ActionServlet。
 
  4. 请求被提交到ActionServlet后,ActionServlet会首先对该URL进行截取(将.do去掉),然后根据截取后的path在已经加载到内存中的struts-config.xml找到对应的path,同时实例化配置文件中配置好的具体的ActionForm对象和RealAction对象,同时将表单信息赋给ActionForm对象。
 
  5.根据配置文件中的type属性找到真正的请求类LoginAction后,由该类完成业务逻辑的各种操作,最后返回ActionForward对象给ActionServlet,最后ActionServlet根据返回情况从struts-config.xml文件中找到对应的跳转页面实现页面导航的统一控制。