Struts2的简介
Struts2是一款基于MVC模式的轻量级Web框架,是Struts1的下一代产品。实质上,Struts2是以WebWork为核心的,采用拦截器的机制来处理用户的请求。Struts2框架的核心组件是Action和拦截器。
Struts2的优势
- Result方式的页面导航,通过Result标签很方便地实现重定向和页面跳转。
- 提供简单、统一的表达式语言来访问所有可供访问的数据。
- 提供标准、强大的验证框架和国际化框架。
- 提供强大的,可以有效减少页面代码的标签。
- 通过简单、集中的配置来调度业务类,使得配置和修改都非常容易。
Struts2的环境配置
步骤:
1. 下载并引入有关Struts2的jar包。
2. 配置web.xml.
3. 写Action类(struts2用action取代servlet从而处理用户请求、响应).
4. 配置struts.xml.
Struts2的执行流程图
项目启动,一系列配置文件被加载,如web.xml、struts.xml文件等。用户通过客户端浏览器发送了一个helloWorld.action请求,该请求被核心控制器拦截到,通过匹配struts.xml文件中的配置,找到请求对应的执行类HelloWorldAction,并默认调用HelloWorldAction中的execute()方法,返回逻辑视图名,然后再通过匹配找到并转发到对应的物理视图页面success.jsp中,最后响应并输出返回结果。
Struts2的核心配置
常量配置的3种方式
1.在struts.xml文件中通过元素配置常量,在配置时,需要指定两个必填的属性name和value。1
<struts>
<!--设置默认编码集为UTF-8 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!--设置使用开发模式 -->
<constant name="struts.devMode" value="true" />
</struts>`
2.在struts.properties文件中配置常量。每个key对应一个value,key表示的是Struts2框架中的常量,而value则是其常量值。
#### 设置默认编码集为UTF-8
struts.i18n.encoding=UTF-8
####设置不使用开发模式
struts.devMode=false
3.在web.xml文件中通过初始化参数配置常量。通过< filter >元素的< init-param >子元素指定,每个
< init-param >元素配置了一个Struts2常量。
``<filter>
<!--指定Struts2的核心过滤器 -->
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<!--通过init-param元素配置Struts2常量,配置默认编码集为UTF-8 -->
<init-param>
<param-name>struts.i18n.encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
实现Action控制类的方式
- POJO的实现
POJO(Plan Ordinary Java Object简单的JAVA对象,只要具有一部分getter/setter方法的类就可以称
作POJO
public class LoginAction {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String execute() throws Exception {
return "success";
}
2 . 实现Action接口
Action接口只定义了一个execute()方法,提供了5个字符串常量”success”,”none”,”error”,”input”,”login”,它们的作用是统一execute()方法的返回值。
import com.opensymphony.xwork2.Action;
public class LoginAction implements Action {
public String execute() throws Exception {
return "success";
}
}
3 . 继承ActionSupport类
提供了数据校验、获取国际化信息等默认方法
``import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
public String execute() throws Exception {
return "success";
}
}
Struts2中Action访问servletAPI有3种方法
1. 通过 ActionContext类访问
2. 通过特定接口访问
3. 通过ServletActionContext访问
在实现业务逻辑的时候,经常要访问Servlet中的对象,如session/request/application等。Struts2中
把调用service返回的结果,保存到域中,有三种方式
方式1:struts2提供ActionContext类来访问Servlet API,ActionContext是Action执行的上下文对象,在ActionContext中保存了Action执行所需要的所有对象。 struts2把request、session、servletContext对象,封装为一个个的map,往map里面放数据,其实就是往域中放数据!
ActionContext ac=ActionContext.getContext();
ac.put("name","sam");
ac.getApplication().put("name","sam");
ac.getSession().put("name","sam");
方式2:通过特定接口的方式(同方式1类似)
(实现RequestAware,SessionAware,ApplicationAware接口)
public class AwareAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
// struts在运行时期会传入表示request域的map集合
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}
// struts在运行时期会传入表示session域的map集合
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
// struts在运行时期会传入表示application域的map集合
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}
@Override
public String execute() throws Exception {
// 往map中设置数据!
request.put("requestData", "requestData");
session.put("sessionData", "sessionData");
application.put("applicationData", "applicationData");
return SUCCESS;
}
}
方式3: 通过ServletActionContext访问,原生态的ServletApi,拿到域对象,再操作!
public class DataAction implements Action{
@Override
public String execute() throws Exception {
// 获取request对象
HttpServletRequest request = ServletActionContext.getRequest();
// 获取session对象
HttpSession session = request.getSession();
// 获取application对象
ServletContext application = ServletActionContext.getServletContext();
// 往域中存储数据
request.setAttribute("requestData", "requestData");
session.setAttribute("sessionData", "sessionData");
application.setAttribute("applicationData", "applicationData");
return SUCCESS;
}
}
实现接口Action后,可以选择的返回值常量
public interface Action {
public static final String SUCCESS = "success";
public static final String NONE = "none";
public static final String ERROR = "error";
public static final String INPUT = "input";
public static final String LOGIN = "login";
public String execute() throws Exception;
}
Action处理请求参数
在Struts2中,页面的请求数据和Action有两种基本的对应方式,分别是字段驱动(属性驱动)方式和模型驱动方式
1. 字段驱动(字段驱动FieldDriven)
基本数据类型字段驱动方式的数据传递
public class LoginAction {
// 每次访问都创建实例(多例)
public LoginAction(){
System.out.println("创建Action实例!");
}
// 自动封装login.jsp页面提交的参数:用户名、密码
private String userName;
private String pwd;
public void setUserName(String userName) {
this.userName = userName;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String login(){
System.out.println(userName);
System.out.println(pwd);
return "success";
}
}
<body>
<form action="${pageContext.request.contextPath }/login" method="post">
用户名: <input type="text" name="userName"> <br>
密码: <input type="text" name="pwd"> <br>
<input type="submit" value="提交到struts">
</form>
</body>
- 直接使用域对象字段驱动方式的数据传递
public class LoginAction {
// 自动封装为对象(注意:如果是自动封装为对象类型,需要给get/set方法!)
private User user;
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
…..
}
public class User {
private String userName;
private String pwd;
}
<body>
<form action="${pageContext.request.contextPath }/login" method="post">
用户名: <input type="text" name="user.userName"> <br>
密码: <input type="text" name="user.pwd"> <br>
<input type="submit" value="提交到struts">
</form>
</body>
- 模型驱动
public class RegisterAction extends ActionSupport implements ModelDriven<User>{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public User getModel() {
if(user == null) {
user = new User();
}
return user; // 返回的对象,就是要封装的对象!
}
@Override
public String execute() throws Exception {
System.out.println(user); // 测试看模型驱动是否应用成功!
return super.execute();
}
}
<form action="/day30/register.action" method="post">
用户名: <input type="text" name="name" > <br/>
Email:<input type="text" name="email"> <br/>
<input type="submit" value="提交">
</form>
拦截器的工作原理
从上图可以看出,Struts2拦截器的实现原理与Servlet过滤器的实现原理类似,它以链式执行,对真正要执行的方法(execute())进行拦截。首先执行Action配置的拦截器,在Action和Result执行之后,拦截器会再次执行(与先前调用顺序相反),在此链式执行的过程中,每一个拦截器都可以直接返回,从而终止余下的拦截器、Action及Result的执行。
拦截器的配置是在struts.xml文件中完成的,它通常以标签开头,以标签结束。定义拦截器的语法格式如下:
<interceptor name="interceptorName" class="interceptorClass">
<param name="paramName">paramValue</param>
</interceptor>
上述语法格式中,name属性用来指定拦截器的名称,class属性用于指定拦截器的实现类。有时,在定义拦截器时需要传入参数,这时需要使用标签,其中name属性用来指定参数的名称,paramValue表示参数的值。
拦截器的概述
Interceptor, 拦截器!
1. Struts2提供的功能,都是通过一个个拦截器实现的! (共:35个拦截器!)
2. Struts2有默认执行的拦截器, (默认执行: 18个拦截器!)
用struts2框架必须使用的功能!
3. 如果的默认的拦截器不能满足功能,用户可以自由扩展!即用哪些功能,引用相应的拦截器就行了!
4. 用户也可以自定义拦截器,完成相应的功能!
拦截器执行流程
- 服务器启动:
- 创建拦截器实例
- 执行init初始化方法
- 用户访问
- 创建Action实例
- 执行拦截器interceptor方法
- Interceptor方法放行
- 执行action的业务处理方法
- 执行完毕,又回到拦截器
Struts2提供的常用的拦截器
Params 拦截器,
这个拦截器会把请求数据,自动填充到action类的属性中!
<interceptor
name="params"
class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
文件上传
Struts默认支持文件上传的功能!
<interceptor
name="fileUpload"
class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
Struts2的标签库
对于一个MVC框架来说,重点是实现两部分,业务逻辑控制器部分和视图页面部分。
Struts2标签库分两类:
1. 普通标签:Control标签和Data标签
2. UI标签:Form标签、Non-Form标签、Ajax标签
OGNL表达式
ognl表达式,在struts.xml中设置
<constant name="struts.ui.theme" value="simple"></constant>
ValueStack对象
- 值栈对象是struts2中最重要的对象,存储了struts在运行时期产生的数据!
包含了域中数据、Action对象! - 在struts运行时候,数据都存储到值栈中,最后把值栈放在请求中传给jsp页面,那么jsp页面就可以获取值栈数据!
- 值栈中存储的具体内容?
request、session、application域数据
action对象
其他对象!
获取值栈对象的两种方式
`@Override
public String execute() throws Exception {
// 获取值栈,方式1: 通过HttpServletRequest对象获取
ValueStack vs_request =
(ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
// 获取值栈,方式2:(推荐) 通过ActionContext对象获取
ActionContext actionContext = ActionContext.getContext();
ValueStack vs = actionContext.getValueStack();
return SUCCESS;
}
``
Struts2中的文件上传和下载
- Struts2中文件上传
大大简化了文件上传的代码!在action中可以直接拿到要上传的文件!
原理: fileUpload拦截器! - Struts2文件下载:
方式1:采用servlet的方式; 通过设置http响应头实现文件下载!
(方法返回值类型:void)
方式2:
Struts2提供的文件下载!
关键点:
Action的处理方法结果返回stream !