Java开发之Struts框架项目中应用说明
Struts1最早的一种基于mvc模式的框架;
Struts2 是在Struts1的基础上,融合了xwork的功能;
也可以说,Struts2 = struts1 + xwork Struts2框架预先实现了一些功能:
1. 请求数据自动封装
2. 文件上传的功能
3. 对国际化功能的简化
4. 数据效验功能
SSH框架在mvc模式的的位置作用:
Struts2入门示例
Struts开发步骤:
1. web项目,引入struts - jar包
commons-fileupload-1.2.2.jar 【文件上传相关包】
commons-io-2.0.1.jar
struts2-core-2.3.4.1.jar 【struts2核心功能包】
xwork-core-2.3.4.1.jar 【Xwork核心包】
ognl-3.0.5.jar 【Ognl表达式功能支持表】
commons-lang3-3.1.jar 【struts对java.lang包的扩展】
freemarker-2.3.19.jar 【struts的标签模板库jar文件】
javassist-3.11.0.GA.jar 【struts对字节码的处理相关jar】
注意:使用的struts的struts2-core-2.3.4.1.jar版本不同,核心java培训过滤器类是不一样的!
2. web.xml中,引入struts的核心功能 配置过滤器
<!-- 引入struts核心过滤器 --><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>
3. 开发action
package demo;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport {// 处理请求public String execute() throws Exception {
System.out.println("访问到了action,正在处理请求");
System.out.println("调用service");
return "success";
}
}
注意:
1. action类,也叫做动作类; 一般继承ActionSupport类 即处理请求的类 (struts中的action类取代之前的servlet)
2. action中的业务方法,处理具体的请求 > 必须返回String >方法不能有参数
4. 配置action src/struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="xxx" extends="struts-default">
<action name="hello" class="demo.HelloAction" method="execute">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
执行流程:服务器启动:
1.加载项目web.xml
2. 创建Struts核心过滤器对象, 执行filter init()
struts-default.xml:核心功能的初始化
struts-plugin.xml:struts相关插件
struts.xml:用户编写的配置文件
访问:
3. 用户访问Action, 服务器根据访问路径名称,找对应的aciton配置, 创建action对象
4. 执行默认拦截器栈中定义的18个拦截器
5. 执行action的业务处理方法
struts-default.xml详解
目录:struts2-core-2.3.4.1.jar/ struts-default.xml
内容:
1.bean节点指定struts在运行的时候创建的对象类型
2.指定struts-default包 【用户写的package(struts.xml)一样要继承此包 】 package struts-default 包中定义了:
a. 跳转的结果类型
dispatcher 转发,不指定默认为转发
redirect 重定向
redirectAction 重定向到action资源
stream (文件下载的时候用)
b. 定义了所有的拦截器
定义了32个拦截器!
为了拦截器引用方便,可以通过定义栈的方式引用拦截器,
此时如果引用了栈,栈中的拦截器都会被引用!
defaultStack 默认的栈,其中定义默认要执行的18个拦截器!
c. 默认执行的拦截器栈、默认执行的action
default-interceptor-ref name="defaultStack"/> <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
拦截器:
拦截器功能与过滤器功能类似。
共同点:都拦截资源!
区别: 过滤器,拦截器所有资源都可以;
(/index.jsp/servlet/img/css/js) 拦截器,只拦截action请求。
拦截器是struts的概念,只能在struts中用。
过滤器是servlet的概念,可以在struts项目、servlet项目用。
面试题:拦截器什么时候执行? (访问/启动) 先执行action类创建,先执行拦截器?
1. 用户访问时候按顺序执行18个拦截器;
2. 先执行Action类的创建,再执行拦截器;最后拦截器执行完,再执行业务方法
常量_Action配置路径_通配符
Struts2中常用的常量
指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出
<constant name="struts.i18n.encoding" value="UTF-8"/>
自定义后缀修改常量
<constant name="struts.action.extension" value="do"/>
设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭
<constant name="struts.serve.static.browserCache" value="false"/>
当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开
<constant name="struts.configuration.xml.reload" value="true"/>
开发模式下使用,这样可以打印出更详细的错误信息
<constant name="struts.devMode" value="true" />
默认的视图主题
<constant name="struts.ui.theme" value="simple" />
与spring集成时,指定由spring负责action对象的创建
<constant name="struts.objectFactory" value="spring" />
该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为 false
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
上传文件的大小限制
<constant name="struts.multipart.maxSize" value=“10701096"/>
constants.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><!-- 一、全局配置 -->
<!-- 0. 请求数据编码 --><constant name="struts.i18n.encoding" value="UTF-8"/><!-- 1. 修改Struts默认的访问后缀 --><constant name="struts.action.extension" value="action,do,"></constant><!-- 2. 修改xml自动重新加载 --><constant name="struts.configuration.xml.reload" value="true"/><!-- 3. 开启动态方法调用 (默认不开启)--><constant name="struts.enable.DynamicMethodInvocation" value="true"/><!-- 4. 修改上传文件的最大大小为30M --><constant name="struts.multipart.maxSize" value="31457280"/>
</struts>
Struts2中指定多个配置文件
src/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="constant.xml"></include>
</struts>
Struts2的Action名称搜索机制
1、获得请求路径的URI,例如url是:
/Struts2_01/hello_a/a/b/helloWorld.action
2、首先查询namespace为/hello_a/a/b的package,
如果存在这个package,则在这个package中查询名字为helloWorld的
action,如果不存在这个package则转步骤3
3、查询namespace为/hello_a/a的package,
如果存在这个package,则在这个package中寻找名字为helloWorld的
action,如果不存在这个package,则转步骤4
4、查询namespace为/hello_a的package,
如果存在这个package,则在这个package中寻找名字为helloWorld的
action,如果仍然不存在这个package,则转步骤5
5、查询默认的namaspace的package
查询名字为helloWorld的action(默认的命名空间为空字符串“/” )
如果还是找不到,页面提示404找不到action的异常
Strust2中Action配置项的默认值
Action没有配置class属性的默认值 struts-default.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>
<package name="noClass" namespace="/" extends="struts-default" >
<action name="helloWorld" >
<result name="success">/success.jsp</result> <!--没有指定class属性--></action>
</package>
</struts>
配置访问路径: "/noClass/helloWorld.action
ActionSupport的execute()返回success
result没有指定name那么默认值是success
配置默认的Action处理找不到的Action匹配异常
<default-action-ref name="defaultGoTo">
</default-action-ref>
<action name="defaultGoTo" class="com.loaderman.a_config.UserAction2" >
<result name="success">/index.jsp</result>
</action>
Struts2处理请求后缀机制
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter是Struts2中的核心控制器,该Filter主要的任务是拦截用户/*的所有请求。如果请求的路径中带后缀为.action或没有带后缀,此时将请求交给Struts2框架处理。否则不做任何处理。例如:请求路径为/index.jsp直接访问页面
Struts2配置常量顺序
除了在struts.xml中配置自定义的后缀以外,还可以在项目的src目录下通过创建struts.properties
文件来配置常量:struts.action.extension=action.
Struts2配置文件加载的顺序
struts-default.xml
strtus-plugin.xml
struts.xml
struts.properties (用户自定义配置文件)
因此struts.properties中配置的常量会覆盖struts.xml中的常量配置!
Struts2的resultType
默认的result类型是请求转发
注意: dispatcher只是请求转发,不能转发到外部的资源,只能在本应用中转发,如果要跨应用访问资源,需要使用重定向。
resultType之redirect
resultType之redirectAction
Struts2通配符映射机制
一个 Web 应用可能有成百上千个 action 声明. 可以利用 struts 提供的通配符映射机制把多个彼此相似的映射关系简化为一个映射关系
通配符映射规则
若找到多个匹配, 没有通配符的那个将胜出
若指定的动作不存在, Struts 将会尝试把这个 URI 与任何一个包含着通配符 * 的动作名及进行匹配
若 Struts 找到的带有通配符的匹配不止一个, 最后一个匹配将胜出
被通配符匹配到的 URI 字符串的子串可以用 {1}, {2} 来引用. {1} 匹配第一个子串, {2} 匹配第二个子串… {0} 匹配整个 URI
可以匹配零个或多个字符, 但不包括 / 字符. 如果想把 / 字符包括在内, 需要使用 **. 如果需要对某个字符进行转义, 需要使用 \.
struts2数据处理的几种方式
package com.loaderman.c_data;
import java.util.Map;
import javax.servlet.ServletContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;/**
* 数据处理
*
*/public class DataAction_bak extends ActionSupport{
@Override
public String execute() throws Exception {// 1. 请求数据封装;2. 调用Service处理业务逻辑,拿到结果数据
// 3. 数据保存到域中
/*
*
// Struts中对数据操作,方式1:直接拿到ServletApi, 执行操作
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
ServletContext application = ServletActionContext.getServletContext();
// 操作
request.setAttribute("request_data", "request_data1");
session.setAttribute("session_data", "session_data1");
application.setAttribute("application_data", "application_data1");
*/
// 【推荐:解耦的方式实现对数据的操作】
// Struts中对数据操作,方式2:通过ActionContext类ActionContext ac = ActionContext.getContext();// 得到Struts对HttpServletRequest对象进行了封装,封装为一个map
// 拿到表示request对象的mapMap<String,Object> request = ac.getContextMap();// 拿到表示session对象的mapMap<String, Object> session = ac.getSession();// 拿到表示servletContext对象的mapMap<String, Object> application = ac.getApplication();// 数据request.put("request_data", "request_data1_actionContext");
session.put("session_data", "session_data1_actionContext");
application.put("application_data", "application_data1_actionContext");
return SUCCESS;
}
}
package com.loaderman.c_data;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
import java.util.Map;/**
* 数据处理, 方式3:实现接口的方法
*/public class DataAction 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;
}// 注入session@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}// 注入application@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}
@Override
public String execute() throws Exception {// 数据request.put("request_data", "request_data1_actionAware");
session.put("session_data", "session_data1_actionAware");
application.put("application_data", "application_data1_actionAware"); return SUCCESS;
}
}
Struts2自定义类型转换器
package com.loaderman.d_type;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;/**
* 自定义类型转换器类
*/public class MyConverter extends StrutsTypeConverter {// 新需求:要求项目中要支持的格式,如: yyyy-MM-dd/yyyyMMdd/yyyy年MM月dd日..
// 先定义项目中支持的转换的格式DateFormat[] df = { new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyyMMdd"),
new SimpleDateFormat("yyyy年MM月dd日") };/**
* 把String转换为指定的类型 【String To Date】
*
* @param context
* 当前上下文环境
* @param values
* jsp表单提交的字符串的值
* @param toClass
* 要转换为的目标类型
*/@Override
public Object convertFromString(Map context, String[] values, Class toClass) {// 判断: 内容不能为空if (values == null || values.length == 0) {
return null;
}// 判断类型必须为Dateif (Date.class != toClass) {
return null;
}// 迭代:转换失败继续下一个格式的转换;转换成功就直接返回for (int i=0; i<df.length; i++) {
try {
return df[i].parse(values[0]);
} catch (ParseException e) {
continue;
}
}
return null;
}
@Override
public String convertToString(Map context, Object o) {
return null;
}
}
Struts2中如何自定义类型转换器?实现类 Struts2中如何配置自定义转换器?
1、自定义转换器继承StrutsTypeConverter
2、重写convertFromString和convertToString方法
3、注册转换器
a. 在Action所在包中建立
Action名-conversion.properties
b.在a.文件中添加以下数据
需要转换的字段名=自定义转换器类的权限定名
birthday=cn.loaderman.convertor.DateTypeConvertor
总结:
以上的转换器注册时候是与Action的名字相耦合的,因此只能在自己的Action中内部使 用,称之为局部转换器注册方式。
Struts2中如何自定义全局类型转换器?
实现的接口和继承的类都是相同的,本质上就是配置的方式不同。
1、自定义转换器继承StrutsTypeConverter
2、重写convertFromString和convertToString方法
3、注册转换器
a.在项目src目录下建立以下固定文件
xwork-conversion.properties
b.在3.1文件中添加以下数据 需要转换的类类型=转换器类的权限定名 如:
java.util.Date= cn.loaderman.converter.DateConverter
总结:
该拦截器负责对错误信息进行拦截器
<interceptor name="conversionError“ class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
Struts2中局部和全局转换器的注册文件名为什么是固定的?
1、struts-default.xml
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
2、StrutsConversionErrorInterceptor源码
3、2的父类ConversionErrorInterceptor源码
4、intercept()方法中的XWorkConverter源码
5、 XWorkConverter
Struts2类数据封装
Struts2与Servlet API的解耦访问