- 默认情况下使用的是服务器端跳转,而且也发现必须通过*.action跳转到JSP中才可以,同时发现在JSP里面可以直接利用标签访问类中的属性等等.
1-跳转类型配置
- 如果现在希望有Action跳转到JSP页面使用的是客户端跳转,那么则就需要修改跳转类型.在struts2.x中针对于跳转类型一共有三种定义.
- 修改struts.xml文件中的Action映射
<package name="root" namespace="/" extends="struts-default">
<action name="Echo" class="mao.shu.action.EchoAction">
<result name="echo.page" type="dispatcher">echo_show.jsp</result>
</action>
</package>
类型 | 功能 |
---|---|
type=dispatcher | 服务器端跳转 |
type=“redirect” | 进行客户端跳转,此时无法利用标签取得类中的属性 |
type=“redirect-action”,type=“redirectAction” | 跳转到另外一个Action里面,依然执行的是服务器端跳转到另外的Action中. |
2-配置过滤器
- 在整个Struts2.x开发框架之中,所有的用户请求都是通过过滤器来进行处理的.
- 观察web.xml文件中过滤器的定义
- strtus2.3.4左右版本中能够找到 org.apache.struts2.dispatcher.ng 这个包,但是新的版本的strut2中没有 "ng"这个包,但是能够从org.apache.struts2.dispatcher.filter包下找到过滤器
- 而在这一过程之中用户可以选择的过滤器有三种:
过滤器 | 作用范围 |
---|---|
StrutsPrepareAndExecuteFilter | 在Action执行前后处理工作 |
StrutsPrepareFilter | 在页面执行之前执行该过滤器 |
StrutsExecuteFilter | 在页面执行完成之后执行该过滤器 |
- 这三个新的过滤器都有一个共同的特点:必须通过Action跳转到JSP页面上,因为此时页面中使用到了Struts标签.
- 但是如果这个时候不相关联,此时使用老一类的过滤器:在struts2.3.4文档中可以找到
org.apache.struts2.dispatcher.FilterDispatcher
- 示例使用了旧版本的过滤器
- 修改web.xml文件
<filter>
<filter-name>struts2</filter-name>
<!-- 旧版本的过滤器,现在不推荐使用-->
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
3-内置跳转名称
- 此时EchoAction类中的 execute()方法是如下定义的,其中"echo.page"是用户自己定义的名称,此名称对应的是struts.xml文件中配置的Action映射路径的名称
- 当一个Action需要跳转到某一个JSP页面的时候,往往需要一个具体的名称路径来进行定义,但是在struts2中为了方便用户的开发也内置了许多的名字,所有的名字都在Action接口中有定义:
- 在Action接口中定义有一下的几个常量信息
常量 | 内容 | 作用 |
---|---|---|
public static final String ERROR | “error” | 当Action执行出错的时候跳转的页面 |
public static final String INPUT | “input” | |
public static final String LOGIN | “login” | 当用户还未登录的时候跳转的页面 |
public static final String NONE | “none” | 当Action执行的方法没有返回值的时候(例如ajax异步处理)条状的页面 |
public static final String SUCCESS | “success” | 当Action执行成功之后跳转的页面. |
-
在struts2高级开发的时候就需要使用这些常量
-
示例:使用内置常量
-
修改EchoAction.java程序类的execute()方法
@Override
public String execute() throws Exception {
this.msg = "ECHO:"+msg;
return Action.SUCCESS;//返回映射路径名称
}
- 修改web.xml文件的配置
<result name="success" type="dispatcher">echo_show.jsp</result>
-
执行http://localhost:8080/FirstStruts2Project/Echo.action
-
同样也能够执行
4-取得JSP内置对象
- 在Action里面最大的特点就是完全隐藏了内置对象,但是很多的时候对于内置对象程序依然是有开发需求的.对于内置对象使用最多的是:ServletContext,HttpServletRequest,HttpServletResponse
- 如果要取得这些内置对象,需要使用Struts2.x提供的一个程序类完成—ServletActionContext
方法 | 类型 | 功能 |
---|---|---|
public static javax.servlet.http.HttpServletRequest getRequest() | 普通 | 取得HttpServletRequest接口对象 |
public static javax.servlet.http.HttpServletResponse getResponse() | 普通 | 取得HttpServletResponse 接口对象 |
public static javax.servlet.ServletContext getServletContext() | 取得ServletContext接口对象 | |
public static javax.servlet.jsp.PageContext getPageContext() | 普通 | 取得PageContext |
- 观察内置对象处理
- 在EchoAction的execute()方法中取得内置对象
@Override
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
PageContext page = ServletActionContext.getPageContext();
HttpSession session = request.getSession();
ServletContext application = ServletActionContext.getServletContext();
System.out.println("requestUrl = "+request.getRequestURI());
System.out.println("sessionId = "+ session.getId());
System.out.println("ContentPath = " + request.getContextPath());
System.out.println("ContentType = " + response.getContentType() );
System.out.println("realPath = " + application.getRealPath("/") );
this.msg = "ECHO:"+msg;
return Action.SUCCESS;//返回映射路径名称
}
- 执行http://localhost:8080/FirstStruts2Project/Echo.action 后台输出结果
5-多人开发
- 在一个项目开发过程之中一定会有多个开发者同时进行开发,每个开发者都可能有个自己的struts-x.xml文件,而整个Struts2项目最后只需要一个struts.xml文件,于是就可以使用以下的方法包含其他配置文件
<include file="struts-x.xml"/>
- 示例实现多人开发
- 定义一个struts-a.xml文件
<?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>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<package name="root" namespace="/" extends="struts-default">
<action name="Echo" class="mao.shu.action.EchoAction">
<result name="success" type="dispatcher">echo_show.jsp</result>
</action>
</package>
</struts>
- 修改struts.xml文件
<?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>
<include file="struts-a.xml"/>
</struts>
- 执行http://localhost:8080/FirstStruts2Project/Echo.action
- 以后要进行多人开发的时候,每一个开发者都有自己的配置文件.
6-乱码解决
-
如果现在项目使用的编码都是UTF-8的编码,一般不会出现乱码,但如果使用其他编码则可能就会出现乱码的问题.
-
在整个的Struts2.x里面所有使用到的核心配置就在这两个文件中编写:
-
struts.xml
-
struts.properties文件:定义了所有的属性资源.
-
定义struts.properties文件
struts.i18n.encoding=UTF-8
struts.local=zh_CN
- 使用"struts.i18n.encoding"就可以解决乱码问题.但是由于有一个默认的资源文件存在,默认编码就是UTF-8,所以之前不写这个文件也不会出现乱码.
- 默认配置文件在:struts2-core-x.x.x.jar\struts2-core-2.3.37.jar\org\apache\struts2文件之中
- 使用解压文件打开struts2-core-xxx.jar包即可查看到有一个default.properties文件
- 在default.properties文件中的第26行中定义有如下的语句,这是因为有这个设置,所以及时没有在项目中设置struts.properties文件项目也不会出现乱码,但是为了培养一个良好的习惯,建议还是在项目中写出这个struts.properties文件.
7-配置资源文件
- 在任何一个项目里面所有的提示信息以及相对应的路径都应该保存在资源文件之中,在Struts中提供有资源文件的配置方式,只需要按照特定的方式配置好资源文件即可(资源文件的名称最好与类名称相同)
- 定义Messages.properties文件
mao.shu.msg=Hello,maoshu{0},{1},{2}
- 定义Pages.properties文件
mao.shu.page=www.maoshu.com
- 如果此时要正确读取资源文件,那么必须在struts.properties文件之中进行文件名称的设置(不需要后缀名称)
struts.custom.i18n.resources=Messages,Pages
- 但是配置完资源文件之后程序还需要进行读取,使用ActionSuppor类中提供的读取资源方法:
方法 | 功能 |
---|---|
public String getText(String aTextName) | 根据key读取资源文件中对应的value,如果没有找到,则返回key |
public String getText(String aTextName, String defaultValue) | 根据key读取资源文件中devalue,如果没有找到,则返回默认的 defaultValue参数内容 |
public String getText(String key,String[] args) | 根据key读取资源文件的value,并使用 args 数组参数中的内容替换value中的占位符 |
- 读取资源文件信息
- 在一个Action类中的execute()方法中读取资源文件信息
@Override
public String execute() throws Exception {
String info = super.getText("mao.shu.msg",new String[]{"Hello","world","everyone"});
String page = super.getText("mao.shu.page");
this.msg = "ECHO:"+info+"---"+page;
return Action.SUCCESS;//返回映射路径名称
}
- 启动Tomcat,访问http://localhost:8080/FirstStruts2Project/Echo.action,成功读取资源文件的数据.
- 利用getText()方法最大的好处是,不用区分资源文件了,只要存在有key,就可以进行读取处理.
结合vo输入
- Struts2.x中已经完整的实现了参数于vo的转换处理操作,并且支持多级关系的自动属性复制于类型转换.
- 定义vo类
- 定义Dept.java
public class Dept implements Serializable {
private Integer deptno;
private String dname;
private String loc;
//getter和setter方法
}
- 定义Emp.java类
package mao.shu.vo;
import java.io.Serializable;
public class Emp implements Serializable {
private Integer empno;
private String ename;
private String job;
private String hiredate;
private Double sal;
private Double comm;
private Dept dept = new Dept();
//setter和getter
}
-
如果要想实现多级的赋值操作,那么对象一定要实例化完成
-
随后定义一个新的EmpAction类,该类要求可以实现自动赋值处理
package mao.shu.action;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
import mao.shu.vo.Emp;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;
import org.apache.struts2.*;
public class EmpAction extends ActionSupport {
private Emp emp;
public Emp getEmp(){
return this.emp;
}
public void setEmp(Emp emp){
this.emp = emp;
}
@Override
public String execute() throws Exception {
System.out.println(this.emp);
return null ;//表示没有返回值
}
}
- 在struts.xml文件中配置action
<action name="Emp" class=" mao.shu.action.EmpAction"/>
- 对于之前的程序代码可以发现有一个问题,那么就是说,必须通过Action跳转到JSP之后,JSP才能够正常执行.
- 定义emp_add.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"">
<title>echo</title>
</head>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort()+path+"/";
String addUrl = basePath + "Emp.action";
%>
<body>
<form action="<%= addUrl%>" method="post">
雇员编号:<input type="text" id="emp.empno" name="emp.empno" value="7745"/><br/>
雇员姓名:<input type="text" id="emp.ename" name="emp.ename" value="xiemaoshu"/><br/>
雇员职位:<input type="text" id="emp.job" name="emp.job" value="程序员"/><br/>
入职日期:<input type="text" id="emp.hiredate" name="emp.hiredate" value="2019-10-01"/><br/>
雇员工资:<input type="text" id="emp.sal" name="emp.sal" value="4500.5"/><br/>
雇员佣金:<input type="text" id="emp.comm" name="emp.comm" value="50.2"/><br/>
部门编号:<input type="text" id="emp.dept.deptno" name="emp.dept.deptno" value="1"/><br/>
部门名称:<input type="text" id="emp.dept.dname" name="emp.dept.dname" value="开发部"/><br/>
部门地区:<input type="text" id="emp.dept.loc" name="emp.dept.loc" value="上海"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
- 添加提交之后,控制台的输出结果
- 但是如果出现错误的数据输入操作,则会自动找到input的跳转结果.例如输入错误的数据类型
-
"input"是内置的处理跳转,当内容输入错误了之后会自动跳转到"input"对应的路径中.
-
错误提示信息,没有input的返回结果
-
修改struts.xml文件的EmpAction映射路径,添加"input"返回路径
<action name="Emp" class="mao.shu.action.EmpAction">
<result name="input">/emp_add.jsp</result>
</action>
- 重启tomcat,访问emp_add.jsp页面,此时及时输入了错误的数据类型,就会跳回到 emp_add.jsp页面中
- 通过以上的代码可以发现虽然有vo的转换处理操作,但是这种支持是有缺点的,如果数据有问题,则支持将会无效,而且跳转的控制页不方便.