一 Struts框架(上)

时间:2023-03-09 08:38:43
一    Struts框架(上)

Struts2 是基于MVC的WEB框架

经过六年多的发展,Struts1已经成为了一个高度成熟的框架,不管是稳定性还是可靠性都得到了广泛的证明。市场占有率超过20%,拥有丰富的开发人群,几乎已经成为了事实上的工业标准。但是随着时间的流逝,技术的进步,Struts1的局限性也越来越多地暴露出来,并且制约了Struts1的继续发展。
对于Struts1框架而言,由于与JSP/Servlet耦合非常紧密,因而导致了一些严重的问题。首先,Struts1支持的表现层技术单一。由于Struts1出现的年代比较早,那个时候没有FreeMarker、Velocity等技术,因此它不可能与这些视图层的模版技术进行整合。其次,Struts1与Servlet API的严重耦合,使应用难于测试。最后,Struts1代码严重依赖于Struts1 API,属于侵入性框架。
从目前的技术层面上看,出现了许多与Struts1竞争的视图层框架,比如JSF、Tapestry和spring MVC等。这些框架由于出现的年代比较近,应用了最新的设计理念,同时也从Struts1中吸取了经验,克服了很多不足。这些框架的出现也促进了Struts的发展。
Struts已经分化成了两个框架:第一个是在传统的Struts1的基础上,融合了另外的一个优秀的Web框架WebWork的Struts2。Struts 2虽然是在Struts1的基础上发展起来的,但是实质上是以WebWork为核心的。Struts2为传统的Struts1注入了WebWork的先进的设计理念,统一了Struts1和WebWork两个框架。

官网下的jar包
一    Struts框架(上)
打开看见这是apache和opensymphony的WebWork结合的一个产品
一    Struts框架(上)
一    Struts框架(上)

找到struts-2.3.16.3\apps路径下的struts2-blank.war这个包参考写代码
一    Struts框架(上)

1参考上面的war包创建Web动态工程导入相关jar包

一    Struts框架(上)
参考xml。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
        </filter>

        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </web-app>

然后在src下放一个struts.xml,参考得来下面的
这是最简单的struts.xml配置
其效果是当访问index路径的时候,服务端跳转到index.jsp

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
        <package name="default" namespace="/" extends="struts-default">
            <action name="index">
                <result>index.jsp</result>
            </action>
        </package>
    </struts>

2开始写HelloWorld

修改一下inde.jsp页面
一    Struts框架(上)
运行产生效果
一    Struts框架(上)
通过这个过程体会到
相当于实现了servlet的服务端跳转到index.jsp的功能

3整个流程

一    Struts框架(上)

4 继续 struts 显示数据到JSP

Model层使用一个简单的Product用于存放数据

    public class Product {

        int id;
        String name;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }

ProductAction用于控制

    import com.tzy.struts.Product;

    public class ProductAction {
        private Product product;

        public String show() {
            product = new Product();
            product.setName("xiaomi8");
            return "show";
        }

        public Product getProduct() {
            return product;
        }

        public void setProduct(Product product) {
            this.product = product;
        }
    }

在struts.xml中配置跳转
该配置表示 访问路径/showProduct会调用 ProductAction 类的 show 方法
服务端跳转到show.jsp
一    Struts框架(上)

    <action name="showProduct" class="com.tzy.struts.action.ProductAction" method="show">
        <result name="show">show.jsp</result>
    </action>

show.jsp
在web目录下创建show.jsp文件
通过EL表达式,取出product的name
注: ${product}会访问对应的Action的 getProduct()方法

注: 严格地说,是Struts通过getProudct()方法返回product对象,然后再把product对象通过request.setAttribute("product", product) 放在"product" 这个key上,这样就方便EL表达式去取出来了

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
        ${product.name}
</body>
</html>

一    Struts框架(上)

5整个流程

  1. 访问路径 /showProduct
  2. 所有访问都被struts的filter所拦截,并进入struts的工作流程
  3. 根据配置文件struts.xml, 会执行ProductAction的show方法
  4. 在show方法中,将实例属性product指向一个新的对象,并设置名称为xiaomi8
  5. 服务端跳转到show.jsp
  6. 在show.jsp中,访问ProductAction.getProduct() 获取实例属性product,并显示其名称xiaomi8

一    Struts框架(上)

6 struts 提交数据到ACTION

准备提交数据的jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>submit</title>
    </head>
    <body>
    <form action="addProduct">
        <input type="text" name="product.name">
        <br/>
        <input type="submit" value="submit">
    </form>
    </body>
    </html>

为addProduct路径配置对应的action和方法以及返回

    <action name="addProduct" class="com.tzy.struts.action.ProductAction" method="add">
        <result name="show">show.jsp</result>
    </action>

在ProductAction添加add方法

  public String add(){
    System.out.println("product.name:"+product.getName());
    return "show";
   }

一    Struts框架(上)
一    Struts框架(上)

7 原理图

  1. 访问路径 /addProduct
  2. 所有访问都被struts的filter所拦截,并进入struts的工作流程
  3. 根据配置文件struts.xml, 会执行ProductAction的add方法
  4. 在add方法执行之前,Struts生成一个新的product对象,并把页面传递过来的name设置在该对象上,接着把该对象通过setProduct()方法,注入ProductAction
  5. 服务端跳转到show.jsp
  6. 在show.jsp中,访问ProductAction.getProduct() 获取注入的product,并显示其名称

一    Struts框架(上)

8 struts 中文问题

Struts的中文问题,由3部分组成

  1. jsp提交数据的时候,必须是UTF-8编码的
  2. struts拿到数据后进行UTF-8解码
  3. 服务端跳转到jsp进行显示的时候,要指定浏览器使用UTF-8进行显示
    UTF-8可以换成GBK或者GB2312,但是必须统一,不能混用

使用上一步的操作传入啦啦啦
一    Struts框架(上)

修改提交页面

一    Struts框架(上)

修改展示页面

一    Struts框架(上)

修改struts.xml文件
一    Struts框架(上)

<constant name="struts.i18n.encoding" value="UTF-8"></constant>

再次测试
一    Struts框架(上)

8 struts 启动失败,出现错误ERROR FILTERSTART 应该如何调试

在tomcat启动struts web应用的时候,如果出现了struts配置上的错误,你可能只能看到一个 Error FilterStart的提示,而看不到详细的错误原因。

这样就加大了定位和解决问题的难度

这是因为默认配置下,struts把日志输出关闭了
为了把日志输出开启便于调试,需要增加log4j.xml这个配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">

    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

        <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
           <layout class="org.apache.log4j.PatternLayout">
              <param name="ConversionPattern" value="%d %-5p %c.%M:%L - %m%n"/>
           </layout>
        </appender>

        <!-- specify the logging level for loggers from other libraries -->
        <logger name="com.opensymphony">
            <level value="DEBUG" />
        </logger>

        <logger name="org.apache.struts2">
             <level value="DEBUG" />
        </logger>

       <!-- for all other loggers log only debug and above log messages -->
         <root>
            <priority value="INFO"/>
            <appender-ref ref="STDOUT" />
         </root> 

    </log4j:configuration> 

一    Struts框架(上)

这样struts就会启动失败,虽然启动失败了,但是tomcat给出的错误信息非常有限,很不利于调试。 无法知道到底哪里写错了。

一    Struts框架(上)

一    Struts框架(上)
然后重新启动tomcat即可看到具体struts启动失败错误原因

如图所示,可以看到很明确的错误原因,ProductAction类的ClassNotFoundException

一    Struts框架(上)

关闭log4j.xml日志输出
有了log4j.xml日志输出可以帮助调试,但是也会导致struts的启动变慢。

关闭log4j.xml日志输出很简单,直接把log4j.xml命名成其他文件即可,以后要用再把名字改回来,很方便

9 在struts中也可以获取servlet包中的request和response对象

修改ProductAction的show方法,获取request和response对象

public String show(){
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();

    System.out.println("request:\t" + request);
    System.out.println("response:\t" + response);

    Product product = new Product();
    product.setName("xiaomi8");
    return "show";
}

在Tomcat的控制台输出 可以看到Struts使用类StrutsRequestWrapper对HttpServletRequest进行了封装
一    Struts框架(上)

10 struts 获取SESSION对象

  • struts中的Session有两个
    • 一个是传统的servlet包下的HttpSession
    • 另一个是Struts中自己定义的Session
  • 传统的servlet包下的session的获取办法是:
    • ServletActionContext.getRequest().getSession();
    • 使用该方法,需要在eclipse的项目中导入servlet-api.jar,可以在右边下载
  • 新的Session的获取办法是
    • Map m = ActionContext.getContext().getSession();
    • 这个session以Map类的形式出现,其中的值和HttpSession中的值是同步的

修改ProductAction的add方法中访问Session

public String add(){
    Map m = ActionContext.getContext().getSession();
    m.put("name", product.getName());
    return "show";
}

在show.jsp中把通过EL表达式把session中的数据取出来
一    Struts框架(上)

通过
http://127.0.0.1:8080/addProduct.jsp
增加数据

在show.jsp中就可以看到session中的name
一    Struts框架(上)

11 省略上传下载