HelloWorld环境搭建

  1. 在eclipse中创建Web动态项目struts
  2. 导入jar包

  3. WEB-INF目录下新建web.xml
    <web-app>
        <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>
            <dispatcher>FORWARD</dispatcher>
            <dispatcher>REQUEST</dispatcher>       
            <url-pattern>/*</url-pattern>
        </filter-mapping>
     
    </web-app>
  4. src目录下创建一个struts.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
     
    <struts>
      <package name="basicstruts" extends="struts-default">
     
      <action name="index">
        <result>index.jsp</result>
      </action>   
     
    </package>
     
    </struts>
  5. web目录下创建index.jsp

总结流程原理:




显示数据到jsp

  1. Product.java 用于存放数据
    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;
        }
    }

  1. ProductAction用于控制

  1. public class ProductAction {
        private Product product;
     
        public String show() {
            product = new Product();
            product.setName("iphone7");
            return "show";
        }
     
        public Product getProduct() {
            return product;
        }
     
        public void setProduct(Product product) {
            this.product = product;
        }
    }
  2. 在struts.xml中配置跳转
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
      
    <struts>
      <package name="basicstruts" extends="struts-default">
      
      <action name="showProduct" class="com.how2java.action.ProductAction" method="show">
        <result name="show">show.jsp</result>
      </action>   
      
    </package>
      
    </struts>
  3. web目录下创建show.jsp文件。通过EL表达式,取出product的name${product}会访问对应的Action的 getProduct()方法
    <%@page isELIgnored="false"%>
    ${product.name}
    

  1. 原理流程如下:



中文乱码问题:

Struts的中文问题,由3部分组成 
1. jsp提交数据的时候,必须是UTF-8编码的 (提交数据指定编码方式UTF-8,POST方式提交)
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%>

<html>
<form action="addProduct" method="post">
 <input type="text" name="product.name">
	<br/>
 <input type="submit" value="submit">
</form>
</html>
2. struts拿到数据后进行UTF-8解码 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
 
<struts>
  <constant name="struts.i18n.encoding" value="UTF-8"></constant>
   
  <package name="basicstruts" extends="struts-default">
   
  <action name="showProduct" class="com.how2java.action.ProductAction" method="show">
    <result name="show">show.jsp</result>
  </action>   
  <action name="addProduct" class="com.how2java.action.ProductAction" method="add">
    <result name="show">show.jsp</result>
  </action>   
 
</package>
 
</struts>
3. 服务端跳转到jsp进行显示的时候,要指定浏览器使用UTF-8进行显示 
UTF-8可以换成GBK或者GB2312,但是必须统一,不能混用 
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%>

<%@page isELIgnored="false"%>

${product.name}

为了便于调试,在src下增加log4j配置文件

<?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中也可以获取servlet包中的request和response对象

public class ProductAction extends ActionSupport {
    private Product product;
 
    public String show() {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
 
        System.out.println("request:\t" + request);
        System.out.println("response:\t" + response);
 
        product = new Product();
        product.setName("iphone7");
        return "show";
    }
 
    public String add() {
 
        Map m = ActionContext.getContext().getSession();
        m.put("name", product.getName());
        return "show";
    }
 
    // public void validate(){
    // if ( product.getName().length() == 0 ){
    // addFieldError( "product.name", "name can't be empty" );
    // }
    // }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
}
struts中的Session有两个 
一个是传统的servlet包下的HttpSession 
另一个是Struts中自己定义的Session 

传统的servlet包下的session的获取办法是: 
ServletActionContext.getRequest().getSession(); 
使用该方法,需要在eclipse的项目中导入servlet-api.jar,可以在右边下载 

新的Session的获取办法是 
Map m = ActionContext.getContext().getSession(); 
这个session以Map类的形式出现,其中的值和HttpSession中的值是同步的 
在Action类中放入值
public class ProductAction extends ActionSupport {
    private Product product;
 
    public String show() {
        product = new Product();
        product.setName("iphone7");
        return "show";
    }
 
    public String add() {
        Map m = ActionContext.getContext().getSession();
        m.put("name", product.getName());
        return "show";
    }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
}
通过jsp的EL表达式获取值
<%@page isELIgnored="false"%>
 
${product.name}
 
${name}

使用struts进行文件的上传

form表单加上enctype="multipart/form-data"表示表示提交的数据是二进制的
method方法为method="post"
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%>
  
<%@page isELIgnored="false" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
  
<html>
<body>
 
<form action="upload" method="post" enctype="multipart/form-data">
 
  上传文件 : <input type="file" name="doc" /> <br>
  <input type="submit" value="上传">
</form>
 
</body>
</html>
UploadAction的类:
File doc;    属性名字必须与表单的name一致。
String docFileName;
String docContentType;
public class UploadAction {
 
    File doc;
    String docFileName;
    String docContentType;
 
    public File getDoc() {
        return doc;
    }
 
    public void setDoc(File doc) {
        this.doc = doc;
    }
 
    public String getDocFileName() {
        return docFileName;
    }
 
    public void setDocFileName(String docFileName) {
        this.docFileName = docFileName;
    }
 
    public String getDocContentType() {
        return docContentType;
    }
 
    public void setDocContentType(String docContentType) {
        this.docContentType = docContentType;
    }
 
    public String upload() {
        System.out.println(doc);
        System.out.println(docFileName);
        System.out.println(docContentType);
        return "success";
    }
}
struts.xml
为upload路径配置UploadAction,并返回success.jsp
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
 
<struts>
  <package name="basicstruts" extends="struts-default">
 
  <action name="showProduct" class="com.how2java.action.ProductAction" method="show">
    <result name="show">show.jsp</result>
  </action>   
  <action name="addProduct" class="com.how2java.action.ProductAction" method="add">
    <result name="input">addProduct.jsp</result>
    <result name="show">show.jsp</result>
  </action>   
  <action name="upload" class="com.how2java.action.UploadAction" method="upload">
    <result name="success">success.jsp</result>
  </action>   
 
</package>
 
</struts>
success.jsp
分别显示doc,docFileName,docContentType
<%@page isELIgnored="false"%>
uploaded success
 
${doc}
<br/>
${docFileName}
<br/>
${docContentType}
<br/>
struts上传文件的大小默认是比较小的只有2M,可以进行设置
在struts.xml中<constant name="struts.multipart.maxSize" value="10240000"/>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
 
<struts>
  <constant name="struts.multipart.maxSize" value="10240000"/>
   
  <package name="basicstruts" extends="struts-default">
 
  <action name="showProduct" class="com.how2java.action.ProductAction" method="show">
    <result name="show">show.jsp</result>
  </action>   
  <action name="addProduct" class="com.how2java.action.ProductAction" method="add">
    <result name="input">addProduct.jsp</result>
    <result name="show">show.jsp</result>
  </action>   
  <action name="upload" class="com.how2java.action.UploadAction" method="upload">
    <result name="success">success.jsp</result>
  </action>   
 
</package>
 
</struts>

struts有专属标签库 
jsp中表单标签:通过浏览器查看源码可以发现,struts把表单里的内容自动转换成了table
<%@ taglib prefix="s" uri="/struts-tags" %>
 
<html>
 
<body>
 
<s:form action="addProduct">
 
  <s:textfield name="product.name" label="product name" />
  <s:submit value="Submit" />
 
</s:form>
 
</body>
</html>

jsp结果遍历标签

使用s:iterator标签进行遍历
value 表示集合
var 表示遍历出来的元素
st 表示遍历出来的元素状态
st.index 当前行号 基0
st.count 当前行号 基1
st.first 是否是第一个元素
st.last 是否是最后一个元素
st.odd 是否是奇数
st.even 是否是偶数
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
 
<%@ taglib prefix="s" uri="/struts-tags"%>
 
<style>
table {
    border-collapse: collapse;
}
 
td {
    border: 1px solid gray;
}
</style>
 
<table align="center">
    <tr>
        <td>id</td>
        <td>name</td>
        <td>st.index</td>
        <td>st.count</td>
        <td>st.first</td>
        <td>st.last</td>
        <td>st.odd</td>
        <td>st.even</td>
 
    </tr>
 
    <s:iterator value="products" var="p" status="st">
        <tr>
            <td>${p.id}</td>
            <td>${p.name}</td>
            <td>${st.index}</td>
            <td>${st.count}</td>
            <td>${st.first}</td>
            <td>${st.last}</td>
            <td>${st.odd}</td>
            <td>${st.even}</td>
        </tr>
    </s:iterator>
 
</table>

基于注解方式的struts

1. 为了使struts支持注解,需要用到struts2-convention-plugin-x.x.x.jar 这个jar包

2. 下载好了之后,放在WEB-INF/lib 下

3. 不仅如此,还要在项目导入jar,以使得eclipse能够编译通过

4.注释掉xml配置文件中的<action><result>

5.添加注解到action类中
@Namespace("/")表示访问路径,如果是@Namespace("/test"),那么访问的时候,就需要写成http://127.0.0.1:8080/struts/test/showProduct
@ParentPackage("struts-default")与配置文件中的struts-default相同,表示使用默认的一套***
@Results({@Result(name="show", location="/show.jsp") 预先定义多个results, "show" 返回"/show.jsp" , "home" 返回 "/index.jsp". 
@Result(name="home", location="/index.jsp")})   注: 这里并没有用到"home",写出来的目的是为了演示这种定义多个result 的代码风格。
@Action("showProduct")  表示当访问路径是showProduct的时候,就会调用show方法
@Namespace("/")
@ParentPackage("struts-default")
@Results({@Result(name="show", location="/show.jsp"),
        @Result(name="home", location="/index.jsp")})
 
public class ProductAction {
    private Product product;
    @Action("showProduct")
    public String show() {
        product = new Product();
        product.setName("iphone7");
        return "show";
    }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
}

总结可以看出来,注解方式,就是把本来做在struts.xml里的事情,搬到了Action类里面来做。
那么到底应该用注解还是配置呢?从个人经验来讲,小项目适合用注解,大项目因为其复杂性,采用注解会导致配置信息难以维护和查询,更适合采用xml配置方式。