Struts2 MVC基础介绍
流程介绍
我们模拟一个请求/响应的情景,来介绍Struts的工作流程。注意,下面的序号和图中的序号没有严格的对应关系。
- 浏览器向系统发出请求,请求的地址是ac.action
- 请求被StrutsPreparedExecuteFilter拦截,去掉.action后缀,所得结果ac作为action的name。
在Struts框架中,负责处理用户请求的称为action,这里的name用于获取action,找到他,让他干活。 - StrutsPreparedExecuteFilter在struts.xml中查找action映射相关的配置,根据ac查到action的类pkg.AcAction。
- StrutsPreparedExecuteFilter实例化pkg.AcAction,并调用其execute方法。
- pkg.AcAction工作完成之后,汇报工作结果:返回一个字符串success,称之为result。
- StrutsPreparedExecuteFilter使用success去查struts.xml中的结果映射部分,获取到对应的物理视图资源是ac-success.jsp。
- StrutsPreparedExecuteFilter使用forward的方式,将ac-success.jsp展示给用户。
仔细看一下上面的图和内容,在脑海中回忆一下整个流程,最好能够闭眼将整个流程复述一遍,然后再继续。
我们的工作
在上述的流程描述中,几乎都是框架要做的事,但是为了能让框架顺利的工作,我们要提供支持性的工作。使用框架基本都是这样,我们按照框架的模式提供支持,框架自行工作。
接下来看一下我们需要做的事:
- 配置StrutsPreparedExecuteFilter。
StrutsPreparedExecuteFilter是整个流程中的核心,这个指挥中心不是自行启动的,我们需要在web.xml中启动它。这件事只需要做一次。 - 创建Action类
action负责处理用户的请求,具体怎么处理,需要我们创建一个Action类来实现。 - 创建视图
Action实现之后,我们要考虑返回怎样的视图给用户。在这里,我们需要创建1到多个jsp文件,担任视图的角色。 - 配置action映射
配置name和class的对应关系,让Struts知道该把哪些请求分派给哪个action。 - 配置result映射
Action返回的是一个普通的字符串,我们称之为处理结果或者逻辑视图,不管叫什么,总之它不是物理视图,不指定任何视图文件。Struts为了将Action类和视图文件解耦,将返回结果和物理视图的对应关系,我们称之为result映射,在配置文件中配置。
上面五个工作,第一个只需要做一次,相对的,后面四个每创建一个action都需要做一次。
在上面五个工作中,视图文件是jsp,我们将之视为基本知识,并不打算介绍。result映射一般是在action映射内部配置的,所以配置result将包含在配置actioin中。所以,我计划分下面三个主题,介绍上面的工作:
- 配置核心过滤器
- 创建Action
- 配置action
1.配置核心过滤器
这里使用Maven管理项目,如果要使用Struts框架,你需要引入依赖。你可以在http://mvnrepository.com/中输入struts2-core来查找可用的版本,从中选择一个并获取其依赖配置:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.28</version>
</dependency>
在web.xml中配置下面的内容:
<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>
2.创建Action
2.1.参数获取
2.2.创建Action
- POJO
Action不需要实现任何接口,不需要继承任何类,但是需要包含一个方法:public String execute() throws Exception。这个方法是处理请求的入口,由Struts框架调用。这个方法的名字可以自行定义,但是execute是默认的名字,使用这个可以省去一项属性配置。 - 实现Action接口
全称com.opensymphony.xwork2.Action,这个接口定义了几个字符串常量,作为result;还定义了execute方法。 - 继承ActionSupport
全称com.opensymphony.xwork2.ActionSupport,实现了Action。
2.3.demo设计
为了介绍上面3种方式,这里设计一个demo。
2.3.1.POJO
package cn.ljl.note.struts2.login.actions; public class LoginPOJO {
private static final String VALID_USER = "admin";
private static final String VALID_PWD = "admin"; private static final String SUCCESS = "success";
private static final String LOGIN = "login"; private String username;
private String password;
private String tip; 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 getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
} public String execute() throws Exception {
boolean validUser = VALID_USER.equals(getUsername());
boolean validPwd = VALID_PWD.equals(getPassword()); if (!validUser) {
setTip("用户不存在!");
return LOGIN;
} if (!validPwd) {
setTip("密码不正确!");
return LOGIN;
} setTip(null);
return SUCCESS;
}
}
2.3.2.实现Action接口
Action接口的类图如下:
源代码:
package cn.ljl.note.struts2.login.actions; import com.opensymphony.xwork2.Action; public class LoginAction implements Action{
private static final String VALID_USER = "admin";
private static final String VALID_PWD = "admin"; private String username;
private String password;
private String tip; 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 getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
} @Override
public String execute() throws Exception {
boolean validUser = VALID_USER.equals(getUsername());
boolean validPwd = VALID_PWD.equals(getPassword()); if (!validUser) {
setTip("用户不存在!");
return LOGIN;
} if (!validPwd) {
setTip("密码不正确!");
return LOGIN;
} setTip(null);
return SUCCESS;
} }
LoginAction
2.3.3.继承ActionSupport类
package cn.ljl.note.struts2.login.actions; import com.opensymphony.xwork2.ActionSupport; public class LoginActionSupport extends ActionSupport { private static final long serialVersionUID = 8451980703294866793L; private static final String VALID_USER = "admin";
private static final String VALID_PWD = "admin"; private String username;
private String password;
private String tip; 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 getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
} @Override
public String execute() throws Exception {
boolean validUser = VALID_USER.equals(getUsername());
boolean validPwd = VALID_PWD.equals(getPassword()); if (!validUser) {
setTip("用户不存在!");
return LOGIN;
} if (!validPwd) {
setTip("密码不正确!");
return LOGIN;
} setTip(null);
return SUCCESS;
} }
LoginActionSupport
2.4.三种方式的比较
3.配置action
3.1.配置文件
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts> </struts>
3.2.命名空间
一次请求的地址,像这个样子:
<package name="login" extends="struts-default" namespace="/login">
......
</package>
- name
name唯一标识一个package - extends
package有继承的特性,使用extends指定另一个package的name,就会继承彼package下所定义的内容。
这里继承的struts-default是在struts2-core的struts-default.xml中定义的。通常,建议继承struts-default。 - namespace
配置命名空间。
默认的命名空间
namespace不是必需的属性,如果没有配置,那就是默认的命名空间。默认的命名空间有特殊的作用:如果在请求的URL中解析出来的命名空间里找不到对应的action,就到默认的命名空间里找。默认命名空间是一个抽象的概念,不是默认值,你不能说“我可以通过配置namespace等于默认值,来指定默认命名空间”。比如"/"被称为根命名空间,但是它不是默认命名空间,它也没有任何特殊的性质,就和其他命名空间一样。
3.3.action
即配置action映射,struts框架需要查找这个映射,才能根据URL找到实际的处理Action。action是在<package>元素内配置的,下面是一个demo:
<action name="check" class="cn.ljl.note.struts2.login.actions.LoginActionSupport" method="execute">
......
</action>
- name
它同时也是action的url请求地址的一部分,同一个命名空间下,action的name要唯一 - class
它是Action类,负责处理用户的请求。这是一个非必需的属性,默认为com.opensymphony.xwork2.ActionSupport;你可以看下这个类的execute方法,只是直接返回SUCCESS。 - method
它是Action的方法名,对于框架来说,相当于回调方法。框架会调用这个方法,以达到通知请求到达的效果。这是一个非必需的属性,默认值为execute,所以上面的demo完全不用配置这个属性。
3.4.result
即配置result映射,根据这个映射,struts框架才能根据Action返回的逻辑结果(字符串)找到对应的视图资源。result是在<action>元素内配置的,下面是一个demo:
<result name="success">/index.jsp</result>
<result name="login">/login/login.jsp</result>
<result>元素的属性name代表Action返回的逻辑结果;<result>体的内容,代表物理视图的路径。其中name的默认值是"success",所以第1行不用配置name属性。
3.5.异常
public String execute() {
try {
// ...
} catch(异常1 e1) {
return 结果1;
} catch(异常2 e2) {
return 结果2;
}
}
然后我们会在struts.xml中这样配置result映射:
<result name="结果1">视图1.jsp</result>
<result name="结果2">视图2.jsp</result>
这样是可以的,实际上在我们已知的知识上,想到这种方式来解决新的问题,能体现我们是会灵活变通的。不过Struts也提供了正统的配置方法,让我们只需要配置异常和返回结果的映射关系,而不需要捕获Action处理方法中抛出的异常。
3.5.1.异常映射
在<action>元素下,使用<exception-mapping>元素来配置,下面上一个demo:
<result name="exception">/exception/exception.jsp</result>
<exception-mapping result="exception" exception="java.lang.Exception" />
- result
对应的异常类型发生时,要返回什么逻辑结果 - exception
配置什么类型的异常
- 配置的异常类型,对其子类型异常是否有效?
- 两种异常类型(继承关系)配置的先后顺序,对异常抛出的返回结果是否有影响?
抛出的异常可以是父类型、子类型、两者的子类型。
3.5.2.拦截器
我们虽然提供了异常到逻辑结果的映射,但是还需要一个拦截器来做这样的工作:拦截抛出的异常,查映射关系,改为返回对应的逻辑结果。这样的拦截器已经在struts-default中使用了,所以只需要保证定义的<package>,直接或间接的继承了struts-default就好了
3.5.3.输出异常
我们可以在jsp中使用el来输出异常,像这样${exception }。不过,Struts2也提供了相关的标签,下面是一个demo:
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<s:property value="exceptionStack"/>
</body>
</html>
- exception
输出异常本身,相当于${exception } - exception.message
输出异常的信息,相当于${exception.message } - exceptionStack
输出异常的堆栈信息,正是demo中所用到的。
3.6.总结
好了,让之前出现过的几位也上来吧,我们来张合照:struts.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="login" extends="struts-default" namespace="/login">
<action name="check" class="cn.ljl.note.struts2.login.actions.LoginActionSupport">
<result name="success">/index.jsp</result>
<result name="login">/login/login.jsp</result>
<result name="exception">/exception/exception.jsp</result>
<exception-mapping result="exception" exception="java.lang.Exception" />
</action>
</package>
</struts>
4.使用config-browser查看配置
你可能想浏览配置的情况,当然对于一个简单的项目,直接看struts.xml可能更快、更专业。接下来要出场的是一个插件,config-browser,它可以提供通过前台查看配置情况的功能。这不是它唯一的优点,但是我们不需要为其优点列一个清单,暂时知道这一个吧,剩下的自己体会。
4.1.添加依赖
我们使用的struts2-core是2.3.28版本,我们也使用相同版本的config-browser:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>2.3.28</version>
</dependency>
4.2.使用
重新打包、部署,重启服务,输入访问地址:http://localhost:8080/note-struts2/config-browser/actionNames.action,可以看到下面的内容:
注意左侧导航栏,Namespaces下是所有的命名空间,其中/config-browser是插件定义的,/login是我们之前定义的。右侧默认显示默认命名空间下的action。
点击左侧Namespaces/login链接,可以看到:
右侧列出了这个命名空间下的action,点进去会看到:
注意:这里的内容是按照标签页组织的,默认显示的是Results标签页,切换到Eception Mappings,可以看到:
我们关于config-browser入门的介绍就到这里了,其他的靠大家自己了。
5.扩展
前面已经对框架的基本流程中涉及到的工作,做了基本的介绍,下面这些内容会深入一下。
5.1.action
5.1.1.多个处理方法
一个Action类中可以有多个处理方法,只需要在配置<action>的时候使用method指定不同的方法名,就可以定义多个action。比如,我们假想一个Action,它的类图是这样的:
我们可以在struts.xml中这样配置:
<package name="imagination" extends="struts-default" namespace="/imagination">
<action name="addUser" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="add">
...
</action>
<action name="saveUser" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="save">
...
</action>
<action name="deleteUser" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="delete">
...
</action>
</package>
5.1.2.使用通配符
在满足一定的模式的情况下,使用通配符可以使用最少的配置量,配置多个action。比如对于上面的情况,也可以使用下面的配置:
<package name="imagination" extends="struts-default" namespace="/imagination">
<action name="*User" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="{1}">
...
</action>
</package>
line 2,name属性值中使用了*,method属性值中的{1}表示使用第1个*所匹配的字符串。这个配置和上文的配置效果是一样的,但是配置工作更少。
class也可以和name满足一定的模式,比如下面的配置:
<package name="imagination" extends="struts-default" namespace="/imagination">
<action name="*User" class="cn.ljl.note.struts.imaginary.actions.{1}UserAction">
...
</action>
</package>
- 完全匹配优先于模式匹配
- 模式匹配中,前面的优先
5.1.3.默认的action
*可以匹配一切,所以我们可以使用*来配置默认的action。另外,我们还可以像下面这样配置:
<package name="imagination" extends="struts-default" namespace="/imagination">
<default-action-ref name="default" />
<action name="default" class="...">
...
</action>
...
</package>
在特定命名空间下配置,只能作为当前命名空间的默认action;在默认的命名空间下配置,可以作为全局的默认action。
5.1.4.默认的class
配置<action>时,默认的class是com.opensymphony.xwork2.ActionSupport,你可以修改这项配置:在<package>下添加<default-class-ref class="" />。
5.1.5.动态方法调用
在form标签的action属性,可以同时指定action的name和方法,比如:
<form action="user!add">
...
</form>
就指定name为user的action的add方法,来处理请求。
5.2.result
Struts2支持多种result-type,基本的result-type都是在struts2-core的struts-default.xml中配置的。
5.2.1.多种结果类型
1.dispatcher
disparcher是默认的result-type,以指定的jsp作为视图。最原始的配置方式是这样的:
<result name="success" type="dispatcher">
<param name="location">/success.jsp</param>
</result>
因为result的name默认就是success,type默认就是dispatcher,而视图的location可以直接在<result>的体配置。所以可以简化成这个样子:
<result>/success.jsp</result>
2.plainText
plainText将指定的视图以文本的形式显示给浏览器。使用这种方式,需要指定视图的location;如果视图文件中包含非西欧字符,还要指定charSet。
<result name="success" type="plainText">
<param name="location">/success.jsp</param>
<param name="charSet">GBK</param>
</result>
3.redirect
重定向。这个类型可以指定一个location,浏览器重定向到指定的视图。
<result name="success" type="redirect">/index.jsp</result>
4.redirectAction
重定向到Action。这个类型专门重定向到Action,与redirect算是被包含关系。这个类型可以指定namespace和actionName:
<result type="redirectAction">
<param name="namespace">/login</param>
<param name="actionName">check</param>
</result>
暂时,就介绍这几种吧。
5.2.2.使用通配符
在配置result映射的时候,也可以使用通配符,比如:
<package name="imagination" extends="struts-default" namespace="/imagination">
<action name="*User" class="cn.ljl.note.struts.imaginary.actions.UserAction" method="{1}">
<result>/imagination/result-{1}.jsp</result>
</action>
</package>
按照上面的配置,addUser对应cn.ljl.note.struts.imaginary.actions.UserAction的add方法,返回的视图是/imagination/result-add.jsp。
5.2.3.使用OGNL表达式
OGNL表达式的具体内容,计划放在后面讲,这里只介绍几个简单的用法。配置result映射时,可以使用action的属性值(要提供getter方法),比如:
<result>/imagination/result-add.jsp?username=${username}</result>
在计算物理视图时,就会使用action的username属性,替换其中的${username}。
如果属性是复杂属性,比如bean,而在result中需要的是属性bean的属性,也可以按照这样的方式获取:${user.name}。
5.2.4.全局配置
在之前的配置里,都是针对action的一个逻辑结果进行配置;全局配置是在<package>范围,提供一个配置,对所有action都有效。
全局配置是在<package>下,使用<global-results> - <result>来配置,比如:
<package ...>
<global-results>
<result name="exception">/exception.jsp</result>
</global-results>
...
</package>
这样一来,这个package下所有的action,如果没有指定"exception"的映射,就使用全局的映射;如果指定了,就覆盖全局的配置。
5.3.异常的全局配置
在<package>范围,异常也可以使用全局配置。使用<global-exception-mappings> - <exception-mapping>。异常映射是把异常的类型映射到result,所以它依赖于result,全局的异常映射应该只使用全局的result,像下面这样:
<package ...>
<global-results>
<result name="exception">/exception.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="exception" />
</global-exception-mappings>
...
</package>
Struts2 MVC基础介绍的更多相关文章
- Struts2框架基础
Struts2框架基础 1.Java的框架 1.1.框架简介 在大型项目开发过程中,经常会使用到一些框架,这样做好的好处是能够提高工作效率,在java中最常用的的框架就是SSH,这其实是三个框架的简称 ...
- Spring MVC 使用介绍(十三)数据验证 (一)基本介绍
一.消息处理功能 Spring提供MessageSource接口用于提供消息处理功能: public interface MessageSource { String getMessage(Strin ...
- 重温MVC基础入门
重温MVC基础入门 简介 本文主要是作者回顾MVC基础的文章,整合个人认为基础且重点的信息,通过简单实践进行复习. 相关代码地址:https://github.com/OtherRuan/Revi ...
- laravel基础课程---1、laravel安装及基础介绍(laravel如何安装)
laravel基础课程---1.laravel安装及基础介绍(laravel如何安装) 一.总结 一句话总结: [修改composer镜像地址].[明确laravel的安装要求].[安装指定版本的la ...
- ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现
ASP.NET MVC 学习笔记-2.Razor语法 1. 表达式 表达式必须跟在“@”符号之后, 2. 代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...
- Spring MVC基础了解
参考网址:https://www.yiibai.com/spring_mvc/springmvc_overview.html Spring框架相关 Spring Security 一个灵活强大的身份验 ...
- XML基础介绍【一】
XML基础介绍[一] 1.XML简介(Extensible Markup Language)[可扩展标记语言] XML全称为Extensible Markup Language, 意思是可扩展的标记语 ...
- Web3D编程入门总结——WebGL与Three.js基础介绍
/*在这里对这段时间学习的3D编程知识做个总结,以备再次出发.计划分成“webgl与three.js基础介绍”.“面向对象的基础3D场景框架编写”.“模型导入与简单3D游戏编写”三个部分,其他零散知识 ...
- jsp学习---mvc模式介绍和el表达式,jstl标签库的使用入门
一.mvc模式介绍 下图是常用的mvc分层模式: 项目中的包命名规则,一般如下: com.amos.domain 封装JavaBean,一般我喜欢用model命名这个包com.amos.dao 封装d ...
随机推荐
- 哪些window你不知道的却实用的小技巧----window小技巧
前言 一直想要整理一篇有关于window比较全的使用小技巧,却又不知道从哪里开始写起.而让我准备动手写这边随笔的动力,还是在加入虫部落<一个绿色环保,充满朝气的好地方>,从大家的分享中,我 ...
- [USACO14MAR] Counting Friends
题目描述 Farmer John's N cows (2 <= N <= 500) have joined the social network "MooBook". ...
- 数学:随机素数测试(Miller_Rabin算法)和求整数素因子(Pollard_rho算法)
POJ1811 给一个大数,判断是否是素数,如果不是素数,打印出它的最小质因数 随机素数测试(Miller_Rabin算法) 求整数素因子(Pollard_rho算法) 科技题 #include< ...
- POJ 3304 Segments 基础线段交判断
LINK 题意:询问是否存在直线,使得所有线段在其上的投影拥有公共点 思路:如果投影拥有公共区域,那么从投影的公共区域作垂线,显然能够与所有线段相交,那么题目转换为询问是否存在直线与所有线段相交.判断 ...
- python匹配某个中文字符
python2.7对中文的支持不好是众所周知的,现在遇到这样一个需求,要匹配某个中文字符.查了一个资料,思路就是转化为unicode进行比较,记录如下: line = '参考答案: A' # gbk ...
- 【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2
[题意]数列满足an=an-1+an-2,n>=3.现在a1=i,a2=[l,r],要求满足ak%p=m的整数a2有多少个.10^18. [算法]数论(扩欧)+矩阵快速幂 [题解]定义fib(i ...
- parseInt
本文地址:http://www.cnblogs.com/veinyin/p/7647863.html 先来个简单的 console.log(parseFloat("8")); 嗯, ...
- 引用类型 ( 对象定义 )——Object 类型
本文地址:http://www.cnblogs.com/veinyin/p/7607100.html 创建实例 new 操作符后跟构造函数 var people = new Object(); pe ...
- Shodan 使用
本文来自:Shodan新手入坑指南, 记录简要用法,以便使用. 文章先给出搜索过滤方法,然后再简单介绍两种使用shodan的方法:使用命令和编写代码. 搜索过滤 hostname:搜索指定的主机或域名 ...
- input只读属性readonly和disabled的区别
主要区别: 参考: http://bbs.html5cn.org/forum.php?mod=viewthread&tid=84113&highlight=input http://b ...