struts2 学习


仓库地址: https://github.com/biuaxia/struts

Struts

基础

hello struts

  1. 创建动态web项目,idea可选Struts2,Eclipse可选择dynamic web project的方式

  2. 导入jar包

    由于我使用的是idea,我先移动lib文件夹到了web-inf下,然后配置了FileSet即可

  3. 配置web.xml

    首先经过tomcat容器,所以先配置struts的过滤器,拦截全部请求

    <?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>
    
  4. 配置struts.xml文件

    该文件配置了具体的请求内容,例如简单的实现访问index服务器跳转index.jsp

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
            "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
        <!--其效果是当访问index路径的时候,服务端跳转到index.jsp-->
        <package name="basicStruts" extends="struts-default">
            <action name="index">
                <result>index.jsp</result>
            </action>
        </package>
    
    </struts>
    
  5. 设置index.jsp内容

    这里随便写点html内容即可

    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/2/10
      Time: 21:50
      在这里添加文件的描述
    --%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8" isELIgnored="false" %>
    <!DOCTYPE html>
    <html>
    <head>
        <title>/index</title>
    </head>
    <body>
    你好struts
    </body>
    </html>
    
  6. 启动tomcat并测试访问/index

  7. 基本思路
    访问/index -> 被web.xml配置的struts拦截器处理 -> 根据struts.xml的配置,访问/index将跳转到index.jsp文件 -> 显示index.jsp

练习 访问hello跳转hello.jsp

准备一个hello.jsp文件

通过配置struts.xml实现访问路径 /hello 跳转到 hello.jsp

显示数据到JSP

把Model的数据显示在视图JSP上

  1. 准备产品Product实体类

    package vip.javer.bean;
    
    import java.io.Serializable;
    
    /**
     * @author Administrator
     */
    public class Product implements Serializable {
        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;
        }
    }
    
  2. 准备产品ProductAction

    package vip.javer.action;
    
    import vip.javer.bean.Product;
    
    /**
     * @author Administrator
     */
    public class ProductAction {
        private Product product;
        
        public String show() {
            product = new Product();
            product.setName("OnePlus A5000");
            return "show";
        }
        
        public Product getProduct() {
            return product;
        }
        
        public void setProduct(Product product) {
            this.product = product;
        }
    }
    
  3. 修改struts.xml配置

    <action name="showProduct" class="vip.javer.action.ProductAction" method="show">
        <result name="show">show.jsp</result>
    </action>
    

    这里需要说明一下代码

    <action name="showProduct" class="vip.javer.action.ProductAction" method="show">中的name表示访问路径,class表示该路径被访问时会查询的类,method表示查询该类的show方法
    <result name="show">show.jsp</result>中的name表示方法show的返回值为show时调用视图show.jsp

练习 访问/showTime跳转showTime.jsp并且显示当前时间

提交数据到action

  1. show.jsp添加表单控件,方便提交
<form action="addProduct">
    <input type="text" name="product.name">
    <br/>
    <input type="submit" value="submit">
</form>
  1. 在ProductAction类添加add方法
public void add(){
    return "success";
}
  1. 修改struts.xml配置
<action name="addProduct" class="vip.javer.action.ProductAction" method="add">
    <result name="success">show.jsp</result>
</action>
  1. 测试
流程
  1. 携带输入框参数名为product.name的值访问addProduct
  2. web.xml的struts过滤器拦截
  3. 根据配置文件struts.xml, 会执行ProductAction的add方法
  4. 在add方法执行之前,Struts生成一个新的product对象,并把页面传递过来的name设置在该对象上,接着把该对象通过setProduct()方法,注入ProductAction
  5. 服务端跳转到show.jsp
  6. 在show.jsp中,访问ProductAction.getProduct() 获取注入的product,并显示其名称
练习

在页面上新增加age字段,提交到Action

为product新增加一个age属性,并提供setter和getter

最后在show.jsp上显示页面提交的age数据

解决struts中文问题

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

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

我这里由于idea的jsp模板已被我修改,所以不用配置<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>

  1. 修改前端表单方法为post
  2. 指定struts.xml的解码方式为utf-f
<struts>
    <!--指定解码方式为UTF-8-->
    <constant name="struts.i18n.encoding" value="UTF-8"/>
    ...
</struts>
  1. 测试

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>
关闭日志

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

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

request与response

想要在struts中使用request与response很简单

  1. ServletActionContext.getRequest()
  2. ServletActionContext.getResponse()

在Tomcat的控制台输出 可以看到Struts使用类StrutsRequestWrapper对HttpServletRequest进行了封装
Snipaste_2019-02-11_20-53-33.png

session

在struts中session有两个

  1. HttpSession,通过之前的request对象获取得到session对象
  2. Session,该对象为一个map集合,其中的值与httpsession同步
HttpSession session = ServletActionContext.getRequest().getSession();
Map<String, Object> sessionMap = ActionContext.getContext().getSession();

我们可以在add方法中把添加的把内容存入到session中看看效果

public String show() {
    /*测试request与response对象*/
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();
    System.out.println(request);
    System.out.println(response);
    
    /*测试session对象*/
    HttpSession session = ServletActionContext.getRequest().getSession();
    Map<String, Object> sessionMap = ActionContext.getContext().getSession();
    session.setAttribute("name1", "name1");
    sessionMap.put("name2", "name2");
    
    /*四大域存放测试: application,request,session,pageContext*/
    ActionContext requestMap = ActionContext.getContext();
    Map<String, Object> application = requestMap.getApplication();
    Map<String, Object> session1 = requestMap.getSession();
    
    requestMap.put("requestField", "request域内容");
    application.put("applicationField", "application域");
    session1.put("sessionField", "session域");
    
    /*正常代码逻辑*/
    product = new Product();
    product.setName("OnePlus A5000");
    String result;
    int i = (int) (Math.random() * 50);
    product.setId(i);
    if (i % 2 == 0) {
        result = "show";
    } else {
        result = "hide";
    }
    return result;
}
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2019/2/10
  Time: 22:28
  在这里添加文件的描述
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html>
<html>
<head>
    <title>show</title>
</head>
<body>
show.jsp
<br>
${product.id} - ${product.name} - ${product.age}
<br>
Session:&nbsp;${session_id} - ${session_name} - ${session_age}
<br>
四大域测试:&nbsp;${requestField} - ${applicationField} - ${sessionField}
<br>
<form action="addProduct" method="post">
    <label for="product.name">昵称:</label><input id="product.name" type="text" name="product.name" placeholder="请输入name">
    <br/>
    <label for="product.age">年龄:</label><input id="product.age" type="text" name="product.age" placeholder="请输入年龄">
    <br/>
    <input type="submit" value="submit">
</form>
<br>
<h3>测试session</h3>
session中的name1:&nbsp;${name1}
<br>
session中的name2:&nbsp;${name2}
</body>
</html>

上传文件

使用struts框架上传文件

  1. 准备upload.jsp

    <%@ taglib prefix="s" uri="/struts-tags" %>
    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/2/12
      Time: 8:18
      在这里添加文件的描述
    --%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8" isELIgnored="false" %>
    <!DOCTYPE html>
    <html>
    <head>
        <title>upload</title>
    </head>
    <body>
    <%--<s:file name="doc" label="upload"/>--%>
    <form action="upload" method="post" enctype="multipart/form-data">
        上传文件 : <input type="file" name="doc"/> <br>
        <input type="submit" value="上传">
    </form>
    </body>
    </html>
    
  2. 准备对应的上传处理action类

    package vip.javer.action;
    
    import java.io.File;
    
    /**
     * 在upload.jsp中file字段对应的name是"doc"
     * 所以在action中,必须准备3个属性,分别是
     * File doc;
     * String docFileName;
     * String docContentType;
     * 属性名字不能使用其他的,必须基于“doc"
     * 然后为这3个属性提供getter setter
     *
     * @author Administrator
     */
    public class UploadAction {
        
        File doc;
        String docFileName;
        String docContentType;
        
        /**
         * 实际上传方法
         * 这里并不是真正的上传,而是打印了一下上传的文件信息
         * <p>
         * 接着就为upload路径配置UploadAction,并返回success.jsp
         *
         * @return
         */
        public String upload() {
            System.out.println(doc);
            System.out.println(docFileName);
            System.out.println(docContentType);
            return "success";
        }
        
        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;
        }
    }
    
  3. 配置struts.xml

    <struts>
        <action name="upload" class="vip.javer.action.UploadAction" method="upload">
            <result name="success">uploadSuccess.jsp</result>
        </action>
    </struts>
    
  4. 准备uploadSuccess.jsp

    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/2/12
      Time: 8:23
      在这里添加文件的描述
    --%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8" isELIgnored="false" %>
    <!DOCTYPE html>
    <html>
    <head>
        <title>uploadSuccess</title>
    </head>
    <body>
    <h1>上传成功</h1>
    ${doc}
    <br>
    ${docFileName}
    <br>
    ${docContentType}
    </body>
    </html>
    
  5. 测试

    Snipaste_2019-02-12_08-34-44.png

上传文件最大值

struts上传文件的大小默认是比较小的只有2M,可以进行设置

<struts>
    <!--设置上传文件最大值100M-->
    <constant name="struts.multipart.maxSize" value="104857600"/>
</struts>

标签

form标签

与jstl标准标签库类似的,struts有专属标签库
form标签用于提交数据

  1. 修改hide.jsp \ show.jsp 的表单上传框为

    <%@ taglib prefix="s" uri="/struts-tags" %>
    
    <s:form action="addProduct">
      <s:textfield name="product.name" label="product name" />
      <s:submit value="Submit" />
    </s:form>
    

会发现自动转换为了html的表单代码

<form id="addProduct" name="addProduct" action="/struts_war_exploded/addProduct.action" method="post">
<table class="wwFormTable">
    <tr>
    <td class="tdLabel"><label for="addProduct_product_name" class="label">product name:</label></td>
    <td
><input type="text" name="product.name" value="OnePlus A5000" id="addProduct_product_name"/></td>
</tr>

    <tr>
    <td colspan="2"><div align="right"><input type="submit" id="addProduct_0" value="Submit"/>
</div></td>
</tr>

</table></form>

iterator标签

与JSTL标准标签库的c:forEach类似的,struts也提供了一个s:iterator用于遍历一个集合中的数据

为ProductAction增加list方法
  1. 为ProductAction增加一个products属性,类型是List,并提供getter setter

    private List<Product> products;
    
    public List<Product> getProducts() {
        return products;
    }
    
    public void setProducts(List<Product> products) {
        this.products = products;
    }
    
  2. 为ProductAction增加一个list()方法,为products添加3个product对象,并返回“list"

    public String list() {
        products = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Product p = new Product();
            p.setId(i);
            p.setName("商品第" + i + "号");
            p.setAge(i * 10);
            products.add(p);
        }
        return "list";
    }
    
  3. struts.xml配置

    <action name="listProduct" class="vip.javer.action.ProductAction" method="list">
        <result name="list">listProduct.jsp</result>
    </action>
    
  4. listProduct.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2019/2/12
  Time: 8:49

  --------------------------
    使用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" %>
<!DOCTYPE html>
<html>
<head>
    <title>listProduct</title>
    <style>
        table {
            border-collapse: collapse;
        }

        td {
            border: 1px solid gray;
        }
    </style>
</head>
<body>
<table align="center">
    <tr>
        <th>id</th>
        <th>name</th>
        <th>st.index</th>
        <th>st.count</th>
        <th>st.first</th>
        <th>st.last</th>
        <th>st.odd</th>
        <th>st.even</th>
    </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>
</body>
</html>
  1. 测试

Snipaste_2019-02-12_09-00-03.png

check标签

遍历3个product成为checkbox
并且第2个和第3个是默认选中的

private List<Integer> selectedProducts;

public String list() {
    selectedProducts = new ArrayList();
    
    for (int i = 0; i < 3; i++) {
        if ((i + 1) == 2 || (i + 1) == 3) {
            selectedProducts.add(i);
        }
        products.add(p);
    }
}

除了前例中准备的products
再新增一个属性ListselectedProducts,用于存放哪些产品被选中了
注意: ListselectedProducts 里放的是id,而不是对象

<s:checkboxlist value="selectedProducts" name="product.id" list="products" listValue="name" listKey="id"/>

radio标签

遍历products成为radio,并选中第二个

在前例checkbox标签的基础上增加s:radio标签
value表示:哪项被选中
name表示:提交到服务端用的名称
list:用于遍历的集合
listValue:显示的radio的名称
listKey:radio的value

<s:radio value="1" name="product.id" list="products" listValue="name" listKey="id"/>

select 标签

遍历products成为select标签
默认选中第2个和第3个

使用s:select标签
name表示:提交到服务端用的名称
list:用于遍历的集合
listKey:每个option的value
listValue:显示的名称
multiple:true表示可以选中多行
size="3"表示默认显示3行
value表示:哪些被选中

注: 可以增加一个属性 theme=“simple” 使得最后生成的最简单的风格的html,否则就会有一些奇奇怪怪的tr td
或者直接在struts.xml中加一句 Servlet下载文件

注: 如果要增加class,需要使用属性: cssClass

<s:select label="products"
       name="product.id"
       list="products"
       listKey="id"
       listValue="name"
       multiple="true"
       size="3"
       value="selectedProducts"
/>

多重迭代

有部分业务需求需要遍历list中的list
比如当前页面需要显示多个category,每个分类下又对应多个product

  1. Category除了有id和name属性外,还有List属性 表示category和product是一对多关系

    package vip.javer.bean;
    
    import java.util.List;
    
    /**
     * @author Administrator
     */
    public class Category {
        private int id;
        private String name;
        private List<Product> products;
        
        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;
        }
        
        public List<Product> getProducts() {
            return products;
        }
        
        public void setProducts(List<Product> products) {
            this.products = products;
        }
    }
    
  2. 在ProductAction -> list()中准备数据 两个category,并且每个category对应3个product

    private List<Category> categories;
    public List<Category> getCategories() {
        return categories;
    }
    
    public void setCategories(List<Category> categories) {
        this.categories = categories;
    }
    public String list() {
           products = new ArrayList<>();
           selectedProducts = new ArrayList();
           categories = new ArrayList<>();
           for (int i = 0; i < 2; i++) {
               Category category = new Category();
               category.setId(i);
               category.setName("分类" + i);
               List<Product> products = new ArrayList<>();
               for (int j = 0; j < 3; j++) {
                   Product p = new Product();
                   p.setId(i);
                   p.setName("商品第" + (i + 1) + "号");
                   p.setAge(i * 10);
                   products.add(p);
               }
               category.setProducts(products);
               categories.add(category);
           }
    }
    
  3. 展示

<table align="center" border="1" cellspacing="0">
    <tr>
        <th>id</th>
        <th>name</th>
        <th>products</th>
    </tr>
    <s:iterator value="categories" var="c">
        <tr>
            <td>${c.id}</td>
            <td>${c.name}</td>
            <td>
                <s:iterator value="#c.products" var="p">
                    ${p.id} - ${p.name} - ${p.age}<br/>
                </s:iterator>
            </td>
        </tr>
    </s:iterator>
</table>
<s:debug/>

调试

开启调试

导入jar包struts2-config-browser-plugin-2.2.3.1.jar

访问config-browser/actionNames即可

查看action到底有没有传递数据

有的时候jsp上不显示action传递过来的数据,有可能的原因是action并没有传递任何数据

这个时候我们就需要工具来查看action到底有没有传递数据

修改办法很简单,直接增加s:debug

<s:debug/>

通配符匹配链接

学习到目前为止,add,show, list分别需要进行配置
通过通配符匹配可以把这3个配置整合在一个配置中实现

<action name="*Product" class="vip.javer.action.ProductAction" method="{1}">
    <result name="show">show.jsp</result>
    <result name="hide">hide.jsp</result>
    <result name="success">show.jsp</result>
    <result name="list">listProduct.jsp</result>
</action>

这样就能满足多个需求

解释一下xml配置

name="*Product"表示匹配所有以Product结尾的请求
method="{1}"表示以*位置的内容作为方法,比如name = "showProduct"那么就是method = "show"

<result name="show">show.jsp</result>
<result name="hide">hide.jsp</result>
<result name="success">show.jsp</result>
<result name="list">listProduct.jsp</result>

表示对应的方法返回值跳转对应页面

拦截器

拦截器可以简单地看成是Struts中的"filter"
拦截器可以拦截指定的Action,并且对Action进行相应的操作
在本例里,拦截了ProductAction,并且注入了当前时间

  1. 在ProductAction添加date属性

  2. 在显示界面追加${date}

  3. 创建拦截器

    package vip.javer.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    import vip.javer.action.ProductAction;
    
    import java.util.Date;
    
    /**
     * 时间拦截器
     *
     * @author Administrator
     */
    public class DateInterceptor extends AbstractInterceptor {
        @Override
        public String intercept(ActionInvocation actionInvocation) throws Exception {
            ProductAction productAction = (ProductAction) actionInvocation.getAction();
            productAction.setDate(new Date());
            return actionInvocation.invoke();
        }
    }
    
  4. 配置struts.xml

    <package name="basicStruts" extends="struts-default">
        <!--声明时间拦截器-->
        <interceptors>
            <interceptor name="dateInterptor" class="vip.javer.interceptor.DateInterceptor"/>
        </interceptors>
        <action name="*Product" class="vip.javer.action.ProductAction" method="{1}">
            <!--对ProductAction使用拦截器dateInterceptor -->
            <interceptor-ref name="dateInterptor"/>
            <!--一旦使用了自定义的拦截器,本来配置在action上的默认的拦截器就失效了。 所以需要再加上defaultStack-->
            <interceptor-ref name="defaultStack"/>
        </action>
    </package>
    

5.测试

客户端跳转

struts默认是服务端跳转,想要实现客户端302跳转很简单

在struts.xml中的result标签加入`type="redirect"即可

客户端跳转带参数

这个也很简单,首先准备好action的属性,例如name,然后get\set,然后在方法内赋值,再在result标签的内容区域追加即可,例如<result name="success" type="redirect">index.jsp?name=${name}</result>

String name;
get/set
public void show(){
    name = "233";
}
<result name="show" type="redirect">show.jsp?name=${name}</result>

获取参数也很简单,上面的方法会直接展示url,还可以在页面获取

${param.name}

表单验证

  1. 在ProductAction中添加validate方法
public void validate() {
    if (product.getName().length() == 0) {
        addFieldError("product.name", "昵称不能为空");
    }
}
  1. 配置struts.xml
    比如我这里是表单的验证,那么就需要在addProduct的action下配置result
<result name="input">add.jsp</result>

这个input可以说是内置的方法吧,只管用就好了
大概意思就是如果在addProduct提交表单时出现错误返回到add.jsp

  1. 显示错误信息
<s:head/>

xml实现表单验证

  1. 去掉validate()方法

  2. 新建文件{ActionName}-validation.xml文件,一定要放在ActionName相同包下面

    <!DOCTYPE validators PUBLIC
            "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
            "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    <validators>
        <validator type="requiredstring">
            <param name="fieldname">product.name</param>
            <message>使用xml方式的提示,昵称不能为空</message>
        </validator>
    </validators>
    
  3. 重启测试

Action是多实例的

测试只需要多访问几次,然后在action的无参构造打印this就可以看到了

public ProductAction() {
    System.out.println(this);
}

Snipaste_2019-02-12_10-47-19.png

注解

以上的教程都是基于XML进行配置的,除此之外,Struts还能够基于注解进行配置

  1. 为了支持注解,需要导包

    1. 为了使struts支持注解,需要用到struts2-convention-plugin-x.x.x.jar 这个jar包,在前面的教程中是没有使用的,所以这里需要从右侧下载
    2. 下载好了之后,放在WEB-INF/lib 下
    3. 不仅如此,还要在项目导入jar,以使得eclipse能够编译通过
  2. 注释掉struts.xml的内容

  3. 在对应的Action类追加三个注解

    1. @Namespace("/")
    2. @ParentPackage(“struts-default”)
    @Results({
            @Result(name = "show", location = "/showTime.jsp")
    })
    
  4. 在对应的方法追加@Action(“showTime”)

其他常用注解
Namespace:指定命名空间。
ParentPackage:指定父包。

Result:提供了Action结果的映射。(一个结果的映射)
Results:“Result”注解列表
ResultPath:指定结果页面的基路径。

Action:指定Action的访问URL。
Actions:“Action”注解列表。

ExceptionMapping:指定异常映射。(映射一个声明异常)
ExceptionMappings:一级声明异常的数组。

InterceptorRef:拦截器引用。
InterceptorRefs:拦截器引用组。

一般说来,不是所有的注解都会用到,真正用到哪个的时候再来查一下就知道怎么回事了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值