第6章 Struts2进阶
第6章 Struts2进阶
6.1 认识Struts2的基本配置
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 声明包 -->
<package name="myPackge" extends="struts-default">
<!-- 配置Action -->
<action name="query" class="com.hwp.QueryAction">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
</struts>
6.1.1 配置web.xml
<!-- Struts2过滤器 -->
<filter>
<!-- 过滤器名称 -->
<filter-name>struts2</filter-name>
<!-- 过滤器类 -->
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- Struts2过滤器映射 -->
<filter-mapping>
<!-- 过滤器名称 -->
<filter-name>struts2</filter-name>
<!-- 过滤器映射 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
6.1.2 配置struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 声明包 -->
<package name="myPackage" extends="struts-default">
<!-- 定义action -->
<action name="first">
<!-- 定义处理成功后的映射页面 -->
<result>/first.jsp</result>
</action>
</package>
</struts>
6.1.3 配置struts.properties
struts.properties文件用于配置struts2中所需的大量属性,一般存放在src根目录下,可以通过default.properties了解,实例代码
struts.i18n.encoding=ISO-8859-1
struts.locale=de_DE
struts.multipart.saveDir=\temp
struts.multipart.maxSize=12345
### Load custom property files (does not override struts.properties!)
struts.custom.properties=test,org/apache/struts2/othertest
# added the MockTag to the path of Tags that the TagDirective will search through
struts.velocity.tag.path = org.apache.struts2.views.velocity.ui, org.displaytag.tags
struts.ui.templateDir = template
### Load custom default resource bundles
struts.custom.i18n.resources=testmessages,testmessages2
### XSLT Cache
struts.xslt.nocache = true
也可以省略配置 struts.properties,直接通过struts.xml配置文件的常量来配置Struts2属性
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 通过标签来配置编码格式-->
<constant name="struts.il18.encoding" value="GBK"></constant>
</struts>
6.1.4 学习Struts2的DTD
6.2 深入认识Struts2的配置元素
6.2.1 配置bean
struts-default.xml中的示例代码
<bean type="com.opensymphony.xwork2.conversion.impl.CollectionConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.CollectionConverter" scope="singleton"/>
<bean type="com.opensymphony.xwork2.conversion.impl.ArrayConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.ArrayConverter" scope="singleton"/>
<bean type="com.opensymphony.xwork2.conversion.impl.DateConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.DateConverter" scope="singleton"/>
<bean type="com.opensymphony.xwork2.conversion.impl.NumberConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.NumberConverter" scope="singleton"/>
<bean type="com.opensymphony.xwork2.conversion.impl.StringConverter" name="struts" class="com.opensymphony.xwork2.conversion.impl.StringConverter" scope="singleton"/>
<bean>标签有如下几个属性
- class(必选):表示Bean的类名
- type(可选),表示Bean实现的接口
- name(可选),表示Bean的实例名字,对应相同类型的多个Bean来说,它们的name属性值必须唯一。
- socpe(可选),表示Bean实例的作用域,这个属性值必须是default、singleton、request、session或thread其中之一
- static(可选):该属性指定Bean是否使用静态方法注入,当指定type属性是,该属性不能为true
- ooptional(可选):表示Bean是否为一个可选Bean
6.2.2 配置常量(constant)
- struts.properties 配置(不建议使用)
- struts.xml (推荐使用)
- web.xml配置(不建议使用)
在实际开发中推荐使用struts.xml中配置常量,其他两种方式不推荐使用
6.2.3 配置包含(include)
struts2允许将一个配置文件分解成多个配置文件,默认装载struts.xml,其他的使用<include>引用
<struts>
<include file="struts-help.xml"/>
</struts>
6.2.4 配置包(package)
<!-- 声明包 -->
<package name="myPackage" extends="struts-default">
<!-- 定义action -->
<action name="first">
<!-- 定义处理成功后的映射页面 -->
<result>/first.jsp</result>
</action>
</package>
- name(必选) 指定包的名字
- extends(可选) 指定该包继承其他包的名字
- namespace(可选) 指定包的命名空间
- nabstract(可选) 指定一个包是否为一个抽象包,抽象包不能包含Action
6.2.5 配置命名空间
命名空间来解决在同一个Web应用中Action重名问题,Struts2的命名空间相当于java中的package关键字
6.2.3 配置拦截器
如struts-default.xml代码片段
<interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
</interceptors>
6.3 掌握Struts2 注释(Annotation)
6.3.1 设置当前包的父包—————ParentPackage注释
6.3.1 指定当前包的命名空间—————Namespace注释
6.3.1 指定当前Action结果—————Results与Result注释
6.3.1 通过注释配置Action
6.4 掌握Struts2的Action
6.4.1 了解Action类的getter和setter方法
public class CompanyAction{
private String employee;
private float salary;
... 省略setter和getter方法
public String execute(){
System.out.println(employee);
System.out.println(salary);
return "success";
}
}
浏览器输入以下地址,会输出对应的数据
http://localhost:8080/webdemo/company.action?employee=bill&salary=2000
6.4.2 实现Action接口
public MyAction implements Action{
public String execute(){
if(...){
return SUCCESS;
}else{
return ERROR;
}
}
}
6.4.3 继承ActionSupport类
略
6.4.4 实例:用ActionContext访问Servlet API
- login.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!-- 引用Struts2标签 -->
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>用户登录</title>
</head>
<body>
<s:form action="login">
<s:textfield label="用户" name="username"/>
<s:textfield label="密码" name="password"/>
<s:submit value="登录"/>
</s:form>
</body>
</html>
- LoginAction.java
//处理用户登录信息的LoginAction类
public class LoginAction implements Action {
//封装username请求参数的属性
private String username;
//封装password请求参数的属性
private String password;
//setter和getter方法
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;
}
//保存用户信息的Map对象
private static Map<String, String> users=new HashMap<>();
static{
users.put("a","1234");
users.put("b", "4321");
}
//用户处理用户请求的execute方法
@Override
public String execute() throws Exception {
try {
//获取ActionContext对象,可以通过该对象实例访问Servlet API
ActionContext ctx=ActionContext.getContext();
//获取Map对象,可以用这个Map对象访问Servlet对象
Map<String, Object> application = ctx.getApplication();
//获取Map对象,可以用这个Map对象访问HttpSession对象
Map<String, Object> session = ctx.getSession();
//从ServletContext获取计数器变量
Integer count=(Integer) application.get("count");
//将用户名保存在HttpSession对象
session.put("username", getUsername());
//此处逻辑,通过输入的用户名去找密码,如果,密码存在则用户不为空
String pw=users.get(username);
if(pw==null){
ctx.put("info", "用户不存在");
return ERROR;
}else{
//密码比较,找到的密码和输入的密码比较,一样说明登录成功
if(pw.equals(getPassword())){
if(count==null){
count=1;
}else{
count++;
}
application.put("count",count);
ctx.put("info","已登录成功");
return SUCCESS;
}else{
ctx.put("info","用户不存在,登录失败");
return ERROR;
}
}
} catch (Exception e) {
return ERROR;
}
}
}
- success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>登录成功</title>
</head>
<body>
本站访问次数:${applicationScope.count}<p/>
用户名:${sessionScope.username}<p/>
${requestScope.session.info}
</body>
</html>
- error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>Insert title here</title>
</head>
<body>
${requestScope.info} <p/>
<h1>登录失败</h1>
</body>
</html>
- web.xml 配置
略 - struts.xml
略
6.4.5 实例:通过aware拦截器访问Servlet API
- ApplicationAware接口:获取ServletContext关联的Map对象
- CookieAware 接口:获得和Cookie数组关联的Map对象
- ParameterAware接口:获取和请求参数关联的Map对象
- ServletRequestAware接口:获得HttpServletRequest对象
- ServletResponseAware接口:获得HttpServletResponse对象
- LoginAwareAction.java,其他的代码一样
//LoginAwareAction实现了Action接口、ServletRequestAware、ApplicationAware接口
public class LoginAwareAction implements Action ,ServletRequestAware,ApplicationAware{
//封装请求参数的usernam属性
private String username;
//封装请求参数的password属性
private String password;
//HttpServletRequest类型变量
private HttpServletRequest request;
//Map类型变量
private Map application;
//setter和getter方法
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;
}
private static Map<String, String> users=new HashMap<>();
//封装用户信息
static{
users.put("bill", "1234");
users.put("mike", "4321");
}
@Override
public void setApplication(Map<String, Object> application) {
this.application=application;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request=request;
}
@Override
public String execute() throws Exception {
try {
//获取HttpSession对象
HttpSession session = request.getSession();
//获取计数器变量
Integer count=(Integer) application.get("count");
session.setAttribute("username",getUsername());
//此处根据账号来获取密码,获得得到密码说明账号存在
String pw=users.get(username);
if(pw==null){
request.setAttribute("info","用户不存在,登录失败");
return ERROR;
}else{
System.out.println(pw+"-----"+getUsername());
//密码比较,密码一样返回成功,计数加 1
if(pw.equals(getPassword())){
if(count==null){
count=1;
}else{
count++;
}
application.put("count",count);
request.setAttribute("info","登录成功");
return SUCCESS;
}else{
request.setAttribute("info",getUsername()+"---"+pw);
return ERROR;
}
}
} catch (Exception e) {
return ERROR;
}
}
}
6.4.6 实例:利用动态方法处理多个提交申请
比如一个表单有多个提交,例如分别有登录和注册
LoginRegisterAction.java
public class LoginRegisterAction implements Action{
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;
}
//处理登录请求
@Override
public String execute() throws Exception {
return SUCCESS;
}
//处理注册信息
public String register() throws Exception {
return "register";
}
}
struts.xml配置,主要代码
<action name="loginregister" class="com.hwp.LoginRegisterAction">
<result name="success">/success1.jsp</result>
<result name="error">/error1.jsp</result>
<result name="register">/register.jsp</result>
</action>
web.xml
略
success1.jsp
略
error1.jsp
略
register.jsp
略
loginrigister.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>用户登录</title>
</head>
<body>
<s:form action="loginregister">
<s:textfield label="用户" name="username"/>
<s:textfield label="密码" name="password"/>
<s:submit value="登录"/>
<!-- 此处还要重新配置action,即表单action+惊叹号+Action类中的方法名 -->
<s:submit value="注册" action="loginregister!register"/>
</s:form>
</body>
</html>
6.4.7 实例:利用menthod属性处理多个提交请求
略
6.4.8 使用通配符
1、2数字表示匹配第几个通配符
action类
public class ActionTest {
//添加方法
public String userAdd(){
return "success";
}
//修改方法
public String userUpdate(){
return "success";
}
//删除方法
public String userDelete(){
return "error";
}
//查询方法
public String userSel(){
return "success";
}
}
struts.xml配置,主要代码
方法一
<action name="ActionTest*" class="com.hwp.ActionTest" method="{1}">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
方法二
<action name="*_*" class="com.hwp.ActionTest" method="{2}">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
请求路径 类名字_方法名.action
<a hrft="ActionTest_userAdd.action">添加</a>
<a hrft="ActionTest_userUpdate.action">修改</a>
<a hrft="ActionTest_userDelete.action">删除</a>
<a hrft="ActionTest_userSel.action">查询</a>
6.4.8 设置默认的Action
配置完默认的Action后,对于系统无效的请求,系统都会调用forwardAction,但要注意,默认Action一定要在所有的<action>
之前配置,也就是说
<default-action-ref>
标签要放在<action>
标签之前
<struts>
<!--配置一个默认的Action -->
<default-action-ref name="forwardAction"/>
<!--默认的Action的配置-->
<action name="forwardAction" class="com.hwp.ForwardAction">
...
</action>
</struts>
6.5 配置跳转结果
典型的结果配置代码
<action name="loginregister" class="com.hwp.LoginRegisterAction">
<result name="success" type="dispatcher">
<param name="location">/success.jsp</param>
</result>
</action>
简写形式
<action name="loginregister" class="com.hwp.LoginRegisterAction">
<result name="success" type="dispatcher">/success1.jsp</result>
</action>
全局配置
<struts>
<package name="Struts2" extends="struts-default">
<!-- 定义全局结果-->
<global-results>
<result name="success" >/success.jsp</>
</global-results>
<action name="query" class="action.QueryAction"/>
</package>
</struts>
上面代码配置了一个全局结果和一个Action,这个Action没有配置任何结果,当Action返回success时,就会转入全局结果success中定义的success.jsp页面
全局结果对当前包中所有的Action有效,如果某个结果不是在大多数Action中使用,就没必要配置全局结果。
6.5.1 了解Struts 2的配置结果
6.5.2 Struts2支持的处理结果类型
查看struts-default.xml
文件,找到如下代码片段
<result-types>
<!-- Action链式处理的结果类型-->
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<!-- 用于转发URL的结果类型,一般转发的是JSP页面-->
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
<!-- 用于与FreeMarker整合的结果类型-->
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<!-- 用于控制http头的结果类型-->
<result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
<!-- 用于重定向的结果类型-->
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
<!-- 用于重定向到其他Action的结果类型-->
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
<!-- 用于向客户端输出字节流的结果类型-->
<result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
<!-- 用于整合Verlocity的结果类型-->
<result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
<!-- 用于整合XML/XSLT的结果类型-->
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<!-- 用于显示页面原始代码的结果类型-->
<result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
<!-- 定义全局结果-->
<result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
</result-types>
6.5.3 配置带有通配符的结果
略
6.5.4 通过请求参数的指定结果
ForwardAction.java
public class ForwardAction implements Action{
private String forward;
...省略setter/getter
public String execute() throws Exception{
return SUCCESS;
}
}
struts.xml
<struts>
<package name="Struts2" extends="struts-default">
<!-- 配置动作-->
<action name="forwardAction" class="com.hwp.ForwardAction">
<!-- 从请求参数中获得JSP文件名-->
<result name="success">/WEB-INF/${forward}.jsp</result>
</action>
</package>
</struts>
在浏览器输入如下URL,会在浏览器中输出web1.jsp,等号后面的就是请求参数指定的jsp文件名
http://localhost:8080/Struts2_demo3/forwardAction.action?forward=webi
6.6 掌握模型驱动
6.6.1 了解驱动模型----ModelDriven
驱动模型,简单理解就是把常说的setter/getter的bean提取出
UserForm.java ,实体类
public class UserForm{
private String name;
... 省略setter和getter方法
}
MyAction.java
public class MyAction implements Action,ModelDriven<UserForm>{
//初始化 UserForm
private UserForm userForm=new UserForm();
//处理用户请求的代码
public String execute(){
return SUCCESS;
}
//实现 ModelDriven接口的getModel方法,用于获得UserForm对象
public UserForm getMOdel(){
return userForm;
}
}
6.6.2 实例:使用模型驱动改进登录程序
略
6.7 处理Struts2的异常
6.7.1 了解Struts2处理异常的原理
略
6.7.2 实例:登录系统的异常处理
略
网友评论