Struts笔记一

Struts

概念:

    是一个MVC框架;

Servlet的缺点

1.在web.xml中文件中需要配置很多行代码,维护起来很不方便呢,不利于团队合作。

2.一个servlet的入口只有一个doPost或者doGet方法,如果在一个servlet在写好几个方法 ,怎么办?

这样会导致代码结构很乱

3.servlet类与servlet容器高度耦合,每个方法中都有两个参数,request、response、如果服务器不启动,这两个参数没有办法初始化(单元测试)。

4.如果在servlet中的一个方法中,有很多功能,这个时候会导致该方法比较复杂、以至于不利于维护。

用户注册完成四件事情、所以整个方法比较杂乱。

5.如果一个servlet类中有很多方法、浏览器对这些方法进行请求、URL写起来麻烦

6.在servlet中如果要获取页面表单中的数据,那么在方法中会写很多行代码。

Servlet的重构

 目的:

  1.在web.xml文件中只写一个过滤器

  2.用action处理业务逻辑

  3.在过滤器中动态的调用action中的方法处理业务逻辑。

类的设计:

  

1.监听器:

  1.准备一个map

  2.把所有的action的key,value放到map中

  3.把map放到application域中;

2过滤器:

  1.获取application域中的map

  2.解析URL

  3.根据解析的URL从map中把value提取出来

  4.根据java的反射机制动态调用action

  5.根据action返回的方法跳转到相应的页面

3.执行action的execute方法,该方法返回一个字符串

实现:

1.写监听器:

 1 import java.util.HashMap;
 2 import java.util.Map;
 3 
 4 import javax.servlet.ServletContextEvent;
 5 import javax.servlet.ServletContextListener;
 6 
 7 public class ServletListener implements ServletContextListener{
 8     /**
 9      * 在tomcat销毁的时候执行
10      */
11     @Override
12     public void contextDestroyed(ServletContextEvent arg0) {
13         arg0.getServletContext().setAttribute("mappings", null);
14     }
15     /**
16      *    在tomcat启动的时候执行 
17      */
18     @Override
19     public void contextInitialized(ServletContextEvent arg0) {
20         Map<String, String> map = new HashMap<String, String>();
21         map.put("userAction", "com.itheima09.action.UserAction");
22         arg0.getServletContext().setAttribute("mappings", map);
23     }
24 }
ServletListener

2.写过滤器:

 1 import java.io.IOException;
 2 import java.lang.reflect.Method;
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 import javax.servlet.Filter;
 7 import javax.servlet.FilterChain;
 8 import javax.servlet.FilterConfig;
 9 import javax.servlet.ServletContext;
10 import javax.servlet.ServletException;
11 import javax.servlet.ServletRequest;
12 import javax.servlet.ServletResponse;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15 
16 import com.itheima09.servlet.utils.ServletUtils;
17 
18 public class DispatcherFilter implements Filter{
19     
20     private ServletContext servletContext;
21 
22     @Override
23     public void destroy() {
24         // TODO Auto-generated method stub
25         
26     }
27 
28     @Override
29     public void doFilter(ServletRequest arg0, ServletResponse arg1,
30             FilterChain arg2) throws IOException, ServletException {
31         /**
32          * 1、从 application域中获取map
33          */
34         HttpServletRequest request = (HttpServletRequest)arg0;
35         HttpServletResponse response = (HttpServletResponse)arg1;
36         Map<String, String> map = (HashMap<String, String>)this.servletContext.getAttribute("mappings");
37         /**
38          * 2、获取浏览器中的url,把url解析出来
39          *     http://localhost:8080/itheima09_servlet_super/userAction.action
40          *     ---->userAction
41          */
42         //mapping = userAction
43         String mapping = ServletUtils.parse(request.getRequestURI());
44         String value = map.get(mapping); //value就是action的类的全名
45         try {
46             Class class1 = Class.forName(value);
47             Method method = class1.getMethod("execute", HttpServletRequest.class,HttpServletResponse.class);
48             //调用了action中的方法
49             String jspName = (String)method.invoke(class1.newInstance(), request,response);
50             request.getRequestDispatcher(jspName).forward(request, response);
51         } catch (Exception e) {
52             // TODO Auto-generated catch block
53             e.printStackTrace();
54         }
55     }
56 
57     @Override
58     public void init(FilterConfig arg0) throws ServletException {
59         // TODO Auto-generated method stub
60         this.servletContext = arg0.getServletContext();
61     }
62     
63 }
DispatcherFilter

 3.工具类:

 1 import org.junit.Test;
 2 
 3 public class ServletUtils {
 4     /**
 5      * http://localhost:8080/itheima09_servlet_super/userAction.action
 6      * @param url
 7      * @return
 8      */
 9     public static String parse(String url){
10         String[] array = url.split("/");
11         String mapping = array[array.length-1].substring(0,array[array.length-1].indexOf("."));
12         return mapping;
13     }
14     
15     @Test
16     public void test(){
17         System.out.println(ServletUtils.parse("http://localhost:8080/itheima09_servlet_super/userAction.action"));
18     }
19 }
ServletUtils

4.action类:

1 import javax.servlet.http.HttpServletRequest;
2 import javax.servlet.http.HttpServletResponse;
3 
4 public class UserAction {
5     public String execute(HttpServletRequest request,HttpServletResponse response){
6         return "index.jsp";
7     }
8 }
UserAction

5.配置文件:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 5     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 6     <listener>
 7         <listener-class>com.itheima09.servlet.listener.ServletListener</listener-class>
 8     </listener>
 9     
10     <filter>
11         <filter-name>actionFilter</filter-name>
12         <filter-class>com.itheima09.servlet.filter.DispatcherFilter</filter-class>
13     </filter>
14     <filter-mapping>
15         <filter-name>actionFilter</filter-name>
16         <url-pattern>*.action</url-pattern>
17     </filter-mapping>
18     <welcome-file-list>
19         <welcome-file>login.jsp</welcome-file>
20     </welcome-file-list>
21 </web-app>
Web.xml

Struts2的历史

 1.servlet

 2.struts1

    1,写action

    2,写了一个中控的servlet

    3,actionForm和页面表单中的内容一致

3.webwork(框架MVC):

    1.使得action和servlet容器完全松耦合

    2.属性驱动和模型驱动获取页面上表单中的数据

    3.利用拦截器的概念把servlet容器的第四个缺点克服掉了

4.struts1+webwork=struts2

Struct2的第一个例子:

1.创建一个web project

2.导入jar包

3.编写web.xml文件

4.写一个action

5.编写struts.xml文件;(放在classpath根目录下)

6.运行访问:格式:http://localhost:8080/ProjectName/[namespace]/ActionName.action

解析:

1.structs.xml文件内容:

上图为加载流程

注意:

1、  struts.xml文件必须放在classpath的根目录下

2、  名字必须为struts.xml文件

3、  因为整个加载过程写在了过滤器中的init方法中,所以tomcat启动的时候就把该文件加载了

2.Package:

1.目的:用来管理action的;

从上图可以看出system模块下有三个action

2.name属性:

  为包名称,是惟一的;

3.namespace:命名空间,针对URL的

上述的命名空间针对的是:itheima09_struts2_helloworld/hello

当浏览器提交一个url:

 

上述的url直接从项目的根目录查找,所以找不到

 

该路径和上述的url是对应的

 

先找hello/a下的action,如果找不到,则查找上一层,再找不到再找上一层,直到找到,如果最上层找不到,则报错

如果我们的namespace设的是/a 那么:工程名/a/xx/xx/xx.action可以由右向左找到此目录,但是如果在工程名后面写不存在的目录则会报错:工程名xx/xx/a/xx/xx/xx.action这个样就报错了,可以理解为在url中工程名与namespace地址是紧密关联的,

 

上述的命名空间针对的是:itheima09_struts2_helloworld

只要命名空间加一层,最后跳转到相应的jsp以后,也会加上相应的路径

 

 

这样的体系不好。

4.extends:

  1.在Tomcat启动的时候,不仅仅加载了struts.xml文件,还加载了struts-default.xml文件,而这个文件在classpath下,针对该文件的路径在:

在一个配置文件中:

说明helloworld拥有package的名称为struts-default包的所有功能;

案例:

Action:

    action元素代表一个类

    class为action的类的全名,可以写,也可以不写

                         如果不写class属性,则默认执行ActionSupport中的execute方法

                            该方法什么都没有做,仅仅返回了一个success字符串

如图:

Result

       代表一种结果集

  Type 为结果集的类型

  Name 属性的值和action中某一个方法的返回值一致

  type属性不写,则默认和struts-default中的结果集中的default="true"的结果集保持一致

                        为dispatcher,转发

                         result标签中的内容就是要转发到的页面

在struts-default.xml文件中

Name属性也可以不写,如果不写,则默认值为”success”

Struts2基本用法的其他方法

Include

       在struts.xml文件中

  

  就可以把struts-helloworld.xml文件包括进来了

Action的写法

1.简单的javabean

2.实现action接口

3.继承ActionSupport

.Action和.do

structs2默认的是以.action为后缀,springmvc是以.do为后缀。structs1也是.do。两者并没什么区别,名字不同而已。

structs2修改为.do后缀的方法如下:

可以在struts.xml中costant标签中,设置“struts.action.extension”的值为do即可。。

    <constant name="struts.action.extension" value="do"/>

并且value可以设置成任意值。比如.hello,.haha。你开心就好

springmvc我现在还不知道怎么改。但是controller可以接收.html和.do。在web.xml里配置servlet-mapping映射吧

Action的模式

       在action的构造器中输出一句话,在浏览器中多次请求,可以看到构造器执行了好几次,所以action是多例的。

结果集:

转发

重定向

重定向到action

通配符映射

第一种:

将执行UrlPatternAction中的execute方法

第二种:

 

 

缺点:action中有几个方法就得在配置文件中写几个action元素

第三种

      

第四种

      

 

第五种

      

 标识符:*写什么  {1}就代表什么    <action name=类名_*     method={1}    class=类所在路径

该模型的好处:如果在action中增加了一个方法,配置文件是不需要改变的,在写url时

urlPatternAction_后面的内容变成要请求的方法的名称就可以了

第六种

     

   针对不同action中的同名方法;

  格式:<action name=类名_*     method=方法名    class=类所在路径{1}

第七种(不推荐)

 

这么写不好,覆盖范围太大,很有可能出现和其他的action 的配置冲突的情况

第八种

      

 格式:<action name=类名_*     method={1}    class=类所在路径

    <result>{1}.jsp<result>

强制让url中的_后面的内容和方法保持一致,跳转到的jsp页面的名称和方法的名称也保持一致。这么写带有一定的规范性

Struts2与servlet容器的交互

 

这种方法可以交互,但是这种方法把ServletAction与servlet容器耦合性变高了,不利于测试。

 

可以通过ServletActionContext把servlet容器相关的类调出来

 

该写法使得action与servlet容器的耦合性不是很强。

总结

1、  sturts2的配置文件中用了package的机制,这样可以分模块

name是唯一的名称,extends采用了继承的机制

2、  写的action与servlet容器完全松耦合了

3、  通配符映射解决:很容器就把一个url映射到一个action的方法中了

4、  Include保证了可以写多个配置文件

5、  结果集的封装

     struts内核流程图:

合群是堕落的开始 优秀的开始是孤行
原文地址:https://www.cnblogs.com/biaogejiushibiao/p/9372087.html