MVC
模型(Model)-视图(View)-控制器(Controller),通常简称MVC,是一种开发web应用程序的软件设计模式。
- 模型——属于软件设计模式的底层基础,主要负责数据维护。
- 视图——这部分是负责向用户呈现全部或部分数据。
- 控制器——通过软件代码控制模型和视图之间的交互。
在MVC模式下,控制器接收了所有来自应用程序的请求后,调用模型去准备视图所需要的数据,然后视图使用由控制器提供的数据最终生成一个可视的响应。
MVC的抽象概念可通过以下图形进行表述:
Struts2架构
从一个高水平角度看,Struts2 是一个MVC拉动的(或MVC2)框架,Struts2 的模型-视图-控制器模式是通过以下五个核心部分进行实现的:
- 操作(Actions)
- 拦截器(Interceptors)
- 值栈(Value Stack)/OGNL
- 结果(Result)/结果类型
- 视图技术
配置文件
- web.xml
<?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_3_1.xsd"
version="3.1">
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<!--拦截所有请求-->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
注:自2.1.3版本开始,ActionContextCleanUp和FilterDispatcher都由StrutsPrepareAndExecuteFilter代替。
- 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>
<constant name="struts.devMode" value="true"/>
<!--设置命名空间,通过myaction/访问action-->
<package name="struts2" namespace="/myaction"
extends="struts-default">
<action name="calSum" class="com.liushiyao.struts2.MyAction">
<!--返回Positive则跳转到positive.jsp-->
<result name="Positive">/positive.jsp</result>
<!--返回Negative则返回negative.jsp-->
<result name="Negative">/negative.jsp</result>
</action>
</package>
</struts>
constant 标签以及name和value属性将用于覆盖default.properties中定义的任一属性,就像我们设置的struts.devMode属性一样。设置struts.devMode属性允许我们在日志文件中查看更多的调试消息。
Actions
作用
- 每个URL映射到特定的action,其提供处理来自用户的请求所需的处理逻辑。
- action在将数据从请求传递到视图(无论是JSP还是其他类型的结果)方面起着重要作用。
- action必须协助框架确定哪个结果应该呈现在响应请求的视图中。
要求
唯一要求是必须有一个无参数方法返回String或Result对象,并且必须是POJO。
package com.liushiyao.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class MyAction extends ActionSupport {
private int num1;
private int num2;
@Override
public String execute() throws Exception {
if(getSum() >=0){
return "Positive";
}else{
return "Negative";
}
}
public int getSum(){
return num1+num2;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
}
拦截器
- 在调用action之前提供预处理逻辑。
- 在调用action后提供后处理逻辑。
- 捕获异常,以便可以执行备用处理。
Struts2框架中提供的许多功能都是使用拦截器实现的,包括异常处理,文件上传,生命周期回调和验证等。
struts自带的拦截器
常用的自带拦截器
序号 | 拦截器和说明 |
---|---|
1 | alias允许参数在请求之间使用不同的别名。 |
2 | checkbox 通过为未检查的复选框添加参数值false,以辅助管理复选框。 |
3 | conversionError将字符串转换为参数类型的错误信息放置到action的错误字段中。 |
4 | createSession自动创建HTTP会话(如果尚不存在)。 |
5 | debugging为开发人员提供一些不同的调试屏幕。 |
6 | execAndWait当action在后台执行时,将用户发送到中间的等待页面。 |
7 | exception映射从action到结果抛出的异常,允许通过重定向自动处理异常。 |
8 | fileUpload便于文件上传。 |
9 | i18n在用户会话期间跟踪选定的区域。 |
10 | logger通过输出正在执行的action的名称提供简单的日志记录。 |
11 | params设置action上的请求参数。 |
12 | prepare这通常用于执行预处理工作,例如设置数据库连接。 |
13 | profile允许记录action的简单分析信息。 |
14 | scope在会话或应用程序范围内存储和检索action的状态。 |
15 | ServletConfig提供可访问各种基于servlet信息的action。 |
16 | timer以action执行时间的形式提供简单的分析信息。 |
17 | token检查action的有效性,以防止重复提交表单。 |
18 | validation提供action的验证支持。 |
使用方法
<action name="calSum" class="com.liushiyao.struts2.action.MyAction">
<interceptor-ref name="params"/>
<interceptor-ref name="timer"/>
<!--返回Positive则跳转到positive.jsp-->
<result name="Positive">/positive.jsp</result>
<!--返回Negative则返回negative.jsp-->
<result name="Negative">/negative.jsp</result>
</action>
用户自定义拦截器
(1)扩展AbstractInterceptor类
package com.liushiyao.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor{
public String intercept(ActionInvocation actionInvocation) throws Exception {
System.out.println("拦截器前置操作");
//action 返回结果(如果不调用则不会执行action中的execute方法)
String result = actionInvocation.invoke();
System.out.println("拦截器后置操作");
return result;
}
}
(2) 配置拦截器
在struts.xml中
<!--配置自定义拦截器-->
<interceptors >
<interceptor name="myinterceptor"
class="com.liushiyao.struts2.interceptor.MyInterceptor"/>
</interceptors>
(3) 引用拦截器
<action name="myInterceptor"
class="com.liushiyao.struts2.action.InterceptorAction"
method="execute">
<!--如果不加params拦截器,则JSP无法获取struts2携带过来的参数-->
<interceptor-ref name="params"/>
<interceptor-ref name="myinterceptor"/>
<result name="success">/interceptor/hello.jsp</result>
</action>
拦截器栈
如果为一个action添加多个拦截器,可以使用“拦截器栈”进行管理。
在struts.xml中
<!--配置自定义拦截器-->
<interceptors >
<!--按照顺序执行-->
<interceptor-stack name="interceptorstack">
<interceptor-ref name="vailable"/>
<interceptor-ref name="mytimer"/>
</interceptor-stack>
<interceptor name="mytimer" class="com.liushiyao.struts2.interceptor.TimerInterceptor"/>
<interceptor name="vailable" class="com.liushiyao.struts2.interceptor.VailableCheckInterceptor"/>
<interceptor name="myinterceptor"
class="com.liushiyao.struts2.interceptor.MyInterceptor"/>
</interceptors>
<action name="myInterceptorStack"
class="com.liushiyao.struts2.action.MyInterceptorStackAction">
<interceptor-ref name="interceptorstack"/>
<result name="success">/positive.jsp</result>
</action>
Result
Struts提供了许多预定义的结果类型,我们已经看到的是默认的结果类型dispatcher,它用于分发到JSP页面。
dispatcher
dispatcher结果类型是默认的类型,如果未指定其他结果类型,则使用此类型。它用于转发到服务器上的servlet,JSP,HTML等页面。它使用RequestDispatcher.forward()方法。
FreeMaker
Freemaker是一个流行的模板引擎,使用预定义的模板生成输出。
让我们创建一个包含以下内容的名为hello.fm的Freemaker模板文件:
Hello World ${name}
在struts.xml中
<action name="hello"
class="cn.w3cschool.struts2.HelloWorldAction"
method="execute">
<result name="success" type="freemarker">
<param name="location">/hello.fm</param>
</result>
</action>
这与JSP视图完全相同,只是我们不绑定使用JSP作为视图技术。
redirect
redirect结果类型调用标准的response.sendRedirect()方法,使得浏览器向给定的位置创建一个新请求。
<action name="myInterceptorStack"
class="com.liushiyao.struts2.action.MyInterceptorStackAction">
<interceptor-ref name="interceptorstack"/>
<result name="success" type="redirect">http://www.baidu.com</result>
</action>
redirectAction
跳转到另外一个Action中,跳转后的请求参数和action处理结果也会丢失
chain
跳转到另外一个Action,跳转后的请求参数丢失,action处理结果保留。
栈值
OGNL(Object-Graph Navigation Language,对象图导航语言)是一种强大的表达式语言,用于引用和操作值栈上的数据,还可用于数据传输和类型转换。
OGNL是基于上下文的,而Struts构建了一个ActionContext映射以供OGNL使用。 ActionContext映射包含以下内容:
- 应用程序 - 应用程序作用域变量
- 会话 - 会话作用域变量
- 根/值栈 - 所有的action变量都存储在这里
- 请求 - 请求作用域变量
- 参数 - 请求参数
- 属性 - 存储在页面,请求,会话和应用程序作用域中的属性
有必要了解的是,Action对象在值栈中总是可用的,因此如果你的Action对象有x和y属性,你可以随时使用。
ActionContext中的对象使用#号引用,但是,值栈中的对象可以直接引用
使用栈值
(1) 创建Action
package com.liushiyao.struts2.ognl;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import java.util.HashMap;
import java.util.Map;
public class OGNLAction extends ActionSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
ValueStack valueStack = ActionContext.getContext().getValueStack();
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "我是Key1");
map.put("key2", "我是Key2");
valueStack.push(map);
System.out.println("ValueStack Size :" + valueStack.size());
return "success";
}
}
(2) 使用栈值
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: liushiyao
Date: 1/29/18
Time: 1:50 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
Hello!OGNL <s:property value="name"/><br>
Key1 value:<s:property value="key1"/><br>
Key2 value:<s:property value="key2"/><br>
</body>
</html>
验证
validate
action 继承ActionSupport,覆写validate方法
package com.liushiyao.struts2.validate;
import com.opensymphony.xwork2.ActionSupport;
public class ValidateAction extends ActionSupport {
private String name;
private Integer age;
@Override
public String execute() throws Exception {
return super.execute();
}
/**
* 验证:当用户按下提交按钮时,Struts2 将自动执行validate方法,
* 如果方法中列出的任何if语句为真,Struts2 将调用addFieldError方法。
* 如果添加了任何错误信息,Struts2 将不会调用execute方法。
* 否则,Struts2 框架将返回input作为调用操作的结果。
*/
@Override
public void validate() {
if(name == null||name.trim().equals("")){
addFieldError("name","name is error!!!");
}
if(age <28||age >50){
addFieldError("age","age is error!!!");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
XML验证
第二种进行验证的方法是在action类旁边放置一个xml文件。Struts2 基于XML的验证提供了更多的验证方式,如email验证、integer range验证、form验证、expression验证、regex验证、required验证、requiredstring验证、stringlength验证等。xml文件需要命名为’[action-class]’-validation.xml。
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="name">
<field-validator type="required">
<message>
The name is required.
</message>
</field-validator>
</field>
<field name="age">
<field-validator type="int">
<param name="min">29</param>
<param name="max">64</param>
<message>
Age must be in between 28 and 65
</message>
</field-validator>
</field>
</validators>