李兴华struts2学习笔记

跳转类型

struts2有常用的三种跳转类型:

1.服务器跳转,url地址不变。默认情况下就是此跳转:

<result name="success" type="dispatcher">/test1.jsp</result>

2.客户端跳转,url地址改变:

<result name="success" type="redirect">/test1.jsp</result>

3. 由一个Action跳转到另一个Action:

 

取得jsp内置对象

由于struts2的Action中并没有像servlet或者filter那样有参数为request和response的方法,所以需要借助ServletActionContext类的方法取得request等对象。

 HttpServletRequest request= ServletActionContext.getRequest();
 HttpServletResponse response=ServletActionContext.getResponse();
 ServletContext context=ServletActionContext.getServletContext();

多人开发

可以建立多个struts的xml配置文件,然后在struts.xml中include多个配置文件,include顺序越前面优先级越高。

解决中文乱码

如果项目统一使用utf-8,就不会有乱码问题,如果使用的是gbk,那么需要解决乱码问题。

在src目录下建立struts.properties文件:

struts.i18n.encoding=utf-8
struts.locale=zh_Ch

配置资源文件

三种级别的资源文件:

1.全局资源文件:在src目录下,可以有一个struts.properties,多个其他名称的poperties(其他的全局资源文件命名规则与Java类名称命名规则相同),并且在struts.properties中注册其他的全局资源文件。(推荐使用)

struts.custom.i18n.resources=Hello,Message

2.包级别资源文件:在某一包下,只能够给该包使用,名称为"package.properties"。

3.指定Acton的资源文件:在该Action所在包下,只能够给该Action使用,名称为"(Action的名称).properties"。

上面三种级别的优先级为3>2>1 

在Action中读取资源文件:super.getText()方法。

示例:

EchoAction.properties:

msg=EchoAction.properties{0} {1} 嘻嘻{2} {3}

EchoAction:

System.out.println(super.getText("msg",new String[]{"one","two","three"}));

 运行结果:

EchoAction.propertiesone two 嘻嘻three {3}

资源文件中有4个占位符,但在Action中只传了3个字符串,这样虽然不会报错,但是最好我们编写代码的时候,有几个占位符就传几个字符串。 

结合VO输入

java类:

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;

public class EchoAction extends ActionSupport {
    private City city=new City();

    public City getCity() {
        System.out.println("EchoAction的getCity()");
        return city;
    }

    public void setCity(City city) {
        System.out.println("EchoAction的setCity()");
        this.city = city;
    }

    public EchoAction(){
        System.out.println("EchoAction()构造方法");
    }

    @Override
    public String execute() throws Exception {

        System.out.println("EchoAction执行execute()");
        System.out.println("city:"+city);

        return Action.SUCCESS;
    }
}


import java.util.Date;
public class City {
    private int id;
    private double price;
    private String cityName;
    private Date date;
    private Province province;

    public City(){
        System.out.println("City()构造方法");
    }
    public String getCityName() {
        System.out.println("getCityName()");
        return cityName;
    }

    public void setCityName(String cityName) {
        System.out.println("setCityName()");
        this.cityName = cityName;
    }

    public Province getProvince() {
        System.out.println("getProvince()");
        return province;
    }

    public void setProvince(Province province) {
        System.out.println("setProvince()");
        this.province = province;
    }

    public int getId() {
        System.out.println("getId()");
        return id;
    }

    public void setId(int id) {
        System.out.println("setId()");
        this.id = id;
    }

    public Date getDate() {
        System.out.println("getDate()");
        return date;
    }

    public void setDate(Date date) {
        System.out.println("setDate()");
        this.date = date;
    }

    @Override
    public String toString() {
        return "City{" +
                "id=" + id +
                ", cityName='" + cityName + '\'' +
                ", province=" + province +
                ", date=" + date +
                '}';
    }
}


public class Province {
    private String provinceName;

    public Province(){
        System.out.println("Province()构造方法");
    }

    public String getProvinceName() {
        System.out.println("getProvinceName()");
        return provinceName;
    }

    public void setProvinceName(String provinceName) {
        System.out.println("setProvinceName()");
        this.provinceName = provinceName;
    }

    @Override
    public String toString() {
        return "Province{" +
                "provinceName='" + provinceName + '\'' +
                '}';
    }
}

jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>echo</title>
  </head>
  <body>
 <form action="echo">
     cityName:<input name="city.cityName"><br/>
     id:<input name="city.id"/><br/>
     price:<input name="city.price"><br/>
     date: <input name="city.date"><br/>
     province:<input name="city.province.provinceName"><br/>
   <input type="submit">
 </form>
  </body>
</html>

 struts.xml:

<?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>

    <!--根命名空间-->
    <package name="test"  namespace="/" extends="struts-default">
        <action name="echo" class="struts2.EchoAction">
            <result name="success">echo.jsp</result>
        </action>

    </package>

</struts>

访问echo并填写表单提交后控制台输出:

City()构造方法
EchoAction()构造方法
EchoAction执行execute()
city:City{id=0, cityName='null', province=null, date=null}
City()构造方法
EchoAction()构造方法
EchoAction的getCity()
setCityName()
EchoAction的getCity()
setDate()
EchoAction的getCity()
setId()
EchoAction的getCity()
EchoAction的getCity()
getProvince()
Province()构造方法
setProvince()
setProvinceName
EchoAction执行execute()
city:City{id=1, cityName='宁波', province=Province{provinceName='浙江'}, date=Fri Dec 12 00:00:00 CST 2014}

(我已被自己绕晕)

标签与属性范围 

在action中request.setAttribute("msg","msg"),转发的页面可以用#request.msg取出。

非UI标签

1.日期格式化标签

<s:date name="date" format="yyyy-MM-dd HH:mm:ss"/>

2.资源文件输出标签

  <%--name=资源文件的名称--%>
  <s:i18n name="Hello">
      <%--name=资源文件中的key--%>
      <s:text name="msg">
          <%--给资源文件中key=msg的值传递参数给占位符--%>
          <s:param>小鱼仙倌</s:param>
          <s:param>锦觅</s:param>
      </s:text>
  </s:i18n>

3.判断与迭代标签

  <s:if test="cities!=null">
      <s:iterator value="cities" var="c">
          <%--id的获取利用了JSTL,这里是想说明可以用JSTL,也可以用struts标签--%>
          <li>城市名称:<s:property value="cityName"/>城市编号:${c.id} </li>
      </s:iterator>
  </s:if>

完整示例代码:

echo.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>echo</title>
  </head>
  <body>
  <h><s:property value="date"/> </h><br/>
  <s:date name="date" format="yyyy-MM-dd HH:mm:ss"/><br/>

  <%--name=资源文件的名称--%>
  <s:i18n name="Hello">
      <%--name=资源文件中的key--%>
      <s:text name="msg">
          <%--给资源文件中key=msg的值传递参数给占位符--%>
          <s:param>小鱼仙倌</s:param>
          <s:param>锦觅</s:param>
      </s:text>
  </s:i18n><br/>

  <s:if test="cities!=null">
      <s:iterator value="cities" var="c">
          <%--id的获取利用了JSTL,这里是想说明可以用JSTL,也可以用struts标签--%>
          <li>城市名称:<s:property value="cityName"/>城市编号:${c.id} </li>
      </s:iterator>
  </s:if>
  </body>
</html>

UI标签

EchoAction:传递cities给echo.jsp。

List<City> cities=new ArrayList<>();
        for (int i=0;i<5;i++){
            City c=new City();
            c.setCityName("城市"+i);
            c.setId(i);
            cities.add(c);
        }
 ServletActionContext.getRequest().setAttribute("cities",cities);

echo.jsp:

  <s:form action="test" method="POST">
      <%--<s:select list="#request.cities" name="city" listKey="id" listValue="cityName" 
      id="city"></s:select>--%>
      <s:checkboxlist list="#request.cities" listKey="id" listValue="cityName" name="c" 
      id="c"></s:checkboxlist>
      <s:submit ></s:submit>
  </s:form

TestAcion:接收echo.jsp设置的参数

public class TestAction extends ActionSupport {
    private Object[] c;

    public void setC(Object[] c) {
        System.out.println(c[0].getClass());
        this.c = c;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(Arrays.toString(c));
        return "test";
    }
}

多业务处理

学到多业务处理了,我只想感叹,struts2是什么鬼,太麻烦了吧,各种配置问题,这是要死记硬背么?

吐槽完毕,回归正题。

介绍两种method分发:

1.利用通配符*:

struts.xml配置:

<action name="*echo" class="struts2.EchoAction" method="{1}">
       <allowed-methods>update,delete</allowed-methods>
</action>

一开始,总是执行不了Action里的update方法,后来加上<allowed-method>就可以了,原因好像是struts2的版本关系,我是2.5版本的。

EchoAction:

import com.opensymphony.xwork2.ActionSupport;

public class EchoAction extends ActionSupport {
    private String msg;

    public String getMsg() {
        System.out.println("getMsg...");
        return msg;
    }

    public void setMsg(String msg) {
        System.out.println("setMsg...");
        this.msg = msg;
    }



    public String update(){
        System.out.println("list...+msg="+msg);
        return null;
    }

    public void delete() {
        System.out.println("delete...msg="+msg);
    }


    @Override
    public String execute() throws Exception {
        System.out.println(this);
        return "echo";
    }
}

然后就可以访问:

http://localhost:8080/struts2/updateecho?msg=hello

http://localhost:8080/struts2/deleteecho?msg=world

注意,要访问的方法返回值只能是null或者是String,比如返回值是int,将会报错:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

而且方法必须是无参的。

2.动态方法

在struts.xml的<struts>标签里加上:

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

另外:

<action name="test" class="struts2.TestAction">
         <result name="test">test.jsp</result>
         <allowed-methods>fun</allowed-methods>
</action>

TestAction中的fun()方法我就不贴了。

然后就可以访问:

http://localhost:8080/struts2/test!fun

struts2与Ajax

虽说是struts2与Ajax,但好像并没有涉及到struts2的知识,仍旧是jsp页面利用jquery异步请求,只不过这回请求的不是一个servlet,而是一个action,访问路径变了而已,其他没什么变化。

jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>echo</title>
    <script src="http://apps.bdimg.com/libs/jquery/1.6.4/jquery.js"></script>

  </head>
  <body>
    <script>
      $(function () {
          $.get(
              "updateecho",
              function (result) {
                  for (var i=0;i<result.cities.length;i++){

                      $("#city").append("<tr><td>"+result.cities[i].name+"</td><td>"+result.cities[i].id+"</td></tr>")
                  }

              },
              "json"
          )
      })
    </script>
  <table id="city">
      <tr>
          <td>城市名称</td>
          <td>城市编号</td>
      </tr>
  </table>
  </body>

</html>

 EchoAction中的update方法:

public void update(){
        ServletActionContext.getResponse().setCharacterEncoding("utf-8");

        JSONObject jsonObject=new JSONObject();
        jsonObject.put("name","浙江");
        jsonObject.put("cityCount",2);

        JSONArray jsonArray=new JSONArray();
        JSONObject c1=new JSONObject();
        c1.put("name","宁波");
        c1.put("id",1);
        JSONObject c2=new JSONObject();
        c2.put("name","杭州");
        c2.put("id",2);

        jsonArray.add(c1);
        jsonArray.add(c2);
        jsonObject.put("cities",jsonArray);

        try {
            ServletActionContext.getResponse().getWriter().print(jsonObject);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

struts.xml中的action配置:

<action name="*echo" class="struts2.EchoAction" method="{1}">
            <allowed-methods>update</allowed-methods>
</action>

访问:

http://localhost:8080/struts2/echo.jsp

运行结果:


城市名称	城市编号
宁波	1
杭州	2

数据验证及错误显示

题外话:之前听李兴华的课程里说struts2自定义的过滤器无用,但是刚刚自己定义了一个,发现当我直接访问jsp页面的时候是有被我定义的过滤器给拦截的。于是我又试了一下,直接访问Action是否会被拦截,发现不会。百度了一下,得知如果要想访问Action也经过自定义的过滤器,必须在web.xml中配置<filter-mapping>的顺序为自定义过滤器在struts2带的过滤器之前。

ActionSupport有一个方法validate()是数据验证方法,作用是验证页面提交过来的数据是否符合要求。

在自定义的Action中重写validate()就能调用此方法,此方法会在数据赋值之后,Action的execute()方法(或者其他定义的方法)之前执行。

接着我们就要在validate()中编写验证数据的代码了。

在AcitonSupport中有一个增加错误信息的方法:

public void addFieldError(String fieldName,String errorMessage)

这个方法是往一个Map集合——fieldErrors中增加错误信息,这个Map集合可以通过ActionSupport提供的以下方法取得:

public Map<String,List<String>> getFieldErrors()

每次执行完validate()之后,如果fieldErrors为空,那么继续执行Action的其他方法,如果不为空,说明有错误信息,那么将直接跳转到result name="input"配置的跳转页去,不再执行Action的其他方法。

示例:

echo.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>echo</title>
  </head>
  <body>
    <form action="updateecho" method="post">
        <input type="text" name="msg">${fieldErrors['msg'][0]}
        <input type="submit">
    </form>
  </body>

</html>

EchoAction:

package struts2;

import com.opensymphony.xwork2.ActionSupport;

public class EchoAction extends ActionSupport {
    private String msg;

    public String getMsg() {
        System.out.println("getMsg...");
        return msg;
    }

    public void setMsg(String msg) {
        System.out.println("setMsg...");
        this.msg = msg;
    }

    public String update(){
        System.out.println("update...+msg="+msg);
        return "show";
    }

    @Override
    public String execute() throws Exception {
        System.out.println("execute...");
        return "echo";
    }

    @Override
    public void validate() {
        System.out.println("validate...");
        if (this.msg==null||"".equals(this.msg)){
            super.addFieldError("msg","msg不能为空");
        }else if (this.msg.length()<5){
            super.addFieldError("msg","msg必须超过5个字符");
        }
    }
}

show.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>show</title>
</head>
<body>
    <s:property value="msg"></s:property>
</body>
</html>

 

struts.xml :

<?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>

    <package name="test"  extends="struts-default">
        <action name="*echo" class="struts2.EchoAction" method="{1}">
            <result name="input">echo.jsp</result>
            <result name="show">show.jsp</result>
            <allowed-methods>update</allowed-methods>
        </action>
    </package>

</struts>

1.访问:http://localhost:8080/struts2/echo.jsp

2.不填写任何内容,点击提交:

页面显示:

控制台输出:

setMsg...
validate...

3.填写hi,点击提交:

页面显示:

控制台输出:

setMsg...
validate...

4.填写hello world,点击提交:

页面成功跳转,显示:

控制台输出:

setMsg...
validate...
update...+msg=hello world
getMsg...

需要注意到的是,validate都是在setMsg也就是赋值之后才执行的,所以假设填写的内容不符合要求,validate也没能阻拦你赋值。

验证框架基础

之前是在Action里面重写validate方法来验证数据,还可以用配置文件的方式来验证。

在EchoAction的包目录下创建一个名为EchoAction-validation的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator 1.0.3//EN"
        "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <field name="msg">
        <field-validator type="requiredstring" >
            <message>msg不能为空</message>
        </field-validator>
    </field>
</validators>

然后将之前EchoAction中的validate方法注释掉。

运行项目……

效果会和之前一样:

1.访问:http://localhost:8080/struts2/echo.jsp

2.不填写任何内容,点击提交:

页面显示:

控制台输出:

setMsg...
getMsg...

这里比上面多执行了多输出了一行getMsg...,我想应该是利用配合利用配置文件检验数据会先自动调用get方法获取数据。

3.填写hello world,点击提交:

页面成功跳转,显示:

控制台输出:

setMsg...
getMsg...
update...+msg=hello world
getMsg...

利用配置文件只是方便简单了一点,运行机制还是一样的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值