1、struts2是在WebWork2基础发展而来的,是轻量级的框架也是属于MVC框架,特点:多action实例的、不依赖servlet和struts1 API。
2、struts2的配置文件默认是struts.xml,由于struts2通过filter启动的所以配置文件放在类路径下,struts1是通过servlet启动所以配置文件放在WEB-INF下。
servlet过滤器实在java servlet规范定义的,能过对url请求和响应进行检查和修改。
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<!-- 自从Struts 2.1.3以后,上面的FilterDispatcher已经标注为过时,下面的为新的filter -->
<!--<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、自定义过滤器
步骤
一、实现javax.servlet.Filter接口
public void init(FilterConfig config) throws ServletException;//servlet容器创建过滤器实例后调用
//完成实际的过滤操作,返回响应之前的会调用doFilter方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter) throws IOException, ServletException;
public void destroy();//容器在销毁过滤器前调用
二、在web.xml配置
<filter>
<filter-name>过滤器名字</filter-name>
<filter-class>过滤器类</filter-class>
<init-param>
<param-name>参数名字</param-name>
<param-value>参数值</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>过滤器名字</filter-name>
<url-pattern>url</url-pattern>
</filter-mapping>
4、配置action
package元素是用来把actoin分类进行的管理,还可以重用。
package的name属性是不选的,表示该package的名称
package的extends属性是可选的,允许一个包继承一个或者多前面定义的包
package的abstract属性是可选的,设置为true表示抽象包,抽象包不需要action定义,被其他包所继承
package的namespace属性是可选的,将action配置为不同的命名空间。默认命名空间是"/",如果指定了命名空间,请求先去指定的命名空间找action,如果找不到则去默认的命名空间找。
例子:
配置文件
<!--声明抽象包-->
<package name="default" abstract="true" extends="struts-default">
</package>
<!--继承抽象包-->
<package name="package1" extends="default">
<!--没有配置method属性表示执行Action类的默认的方法execute()-->
<action name="default" class="com.TestAction">
<result name="success">/index.jsp</result>
</action>
<!--指明该action执行add方法-->
<action name="add" class="com.TestAction" method="add">
<result name="success">/index.jsp</result>
</action>
</package>
<!--指定命名空间的action,那么访问delete需要加上命名空间:admin/delete-->
<package name="package2" extends="struts-default" namespace="/admin">
<action name="delete" class="com.TestAction" method="delete">
<result name="success">/index.jsp</result>
</action>
</package>
TestAction.java类
public class TestAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("默认的处理方法");
return SUCCESS;
}
public String add(){
System.out.println("add处理方法");
return SUCCESS;
}
public String delete(){
System.out.println("delete处理方法");
return SUCCESS;
}
}
index.jsp页面
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<a href="<%=path %>/default">不指定method属性执行默认的方法</a><br/>
<a href="<%=path %>/add">指定执行add方法</a><br/>
<a href="<%=path %>/admin/delete">指定指定命名空间的action</a><br/>
5、result元素
location:指定逻辑视图
parse:是否允许在实际视图中使用ongl表达式,参数默认为true
success:表示请求处理成功
error:表示请求失败
none:表示请求完成后不跳转任何页面
input:表示输入时如果验证失败调到什么地方
login:表示登录失败时候跳转的目标
chain:用来处理action链
chart:用来整合JFreeChart的结果类型
dispatcher:用来转向页面
freemarker:处理FreeMark模板
httpheader:控制特殊HTTP行为的结果类型
jasper:用于JasperReports整合的结果类型
jsf:JSF整合的结果类型
redirect:重定向到一个url
redirect-action:重定向一个action
stream:向浏览器发送InputStream对象,通常用来处理文件下载的,还可以用于返回ajax数据
titles:与Title整合的结果类型
velocity:处理Velocity模板
xslt:处理XML/XSLT模板
plaintext:显示原始文件内容,如下载源代码
全局result的配置使得连接得到共享
<package ....>
<global-results>
<result name="success">/success.jsp</result>
</global-results>
</package>
6、struts.properties配置
struts.action.extension: 指明action的后缀,如action,do,"struts.action.extension=action,do,"表示后缀为action或者do或者不用点后缀
struts.configuration:配置文件管理器默认为org.apache.struts2.config.DefaultConfiguration类
struts.configuration.files: struts自动加载的一个配置文件列表
struts.configuration.xml.reload:是否加载xml配置值为true、false
struts.continuations.package:含有actions的完整连续的package名称
struts.custom.i18n.resources:指定国际化文件的前缀,多个文件用逗号分开
struts.custom.properties:配置用户自定义配置文件的路径,若有多个可以用逗号隔开
struts.devMode:设置是否为struts开发模式。这样会显示更多友好的错误提示
struts.enable.DynamicMethodInvocation:是否允许动态方法调用,值为true、false
struts.i18n.encoding:指定字符集
struts.i18n.reload:该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false
struts.locale:设置默认的国际化地区信息
struts.multipart.maxSize:multipart请求信息的最大尺寸(文件上传用)
struts.multipart.parser:专为multipart请求信息使用的org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器接口(文件上传用)
struts.multipart.saveDir:设置保存上传文件的目录
struts.tag.altSyntax:是否能在struts2标签中使用表达式,值为true、false
struts.serve.static:表示是否通过jar文件提供静态内容服务,默认为true
struts.ui.templateDir:该属性指定视图主题所需要模板文件的位置,该属性的默认值是template
struts.ui.theme:该属性指定视图标签默认的视图主题,该属性的默认值是xhtml
struts.url.http.port设置http端口
struts.url.https.port:设置https端口,该属性指定的是Web应用的加密服务端口
struts.velocity.configfile:设置velocity框架配置文件路径
struts.velocity.contexts:velocity:该属性指定Velocity框架的Context位置
struts.velocity.toolboxlocation:指定Velocity框架的toolbox的位置
7、获得用户表单与ModelDriven<T>接口
一、不实现ModelDriven接口的例子:
LoginAction.java请求处理类
public class LoginAction extends ActionSupport {
private String username;//用户名,对应表单输入框的name属性值
private String password;//密码,对应表单输入框的name属性值
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 {
System.out.println(username);
System.out.println(password);
return SUCCESS;
}
}
action配置
<package name="login" extends="struts-default" >
<action name="login" class="com.LoginAction">
<result name="success">/index.jsp</result>
</action>
</package>
index.jsp页面
<form action="login" method="post">
用户名<input name="username" type="text"/><br/>
密码<input name="password" type="password"/><br/>
<input type="submit" value="登录"/><br/>
</form>
二、实现ModelDriven接口的例子:
LoginAction.java请求处理类
public class LoginAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();//需要手动new一个User对象
//实现接口的方法,返回User对象
public User getModel() {
return this.user;
}
@Override
public String execute() throws Exception {
System.out.println(user.getUsername());
System.out.println(user.getPassword());
return SUCCESS;
}
}
action配置同上
index.jsp页面同上,这时表单输入框的name属性值对应的是User对象的属性名
8、 拦截器配置
<package name="login" extends="struts-default">
<!--
拦截器栈(或堆)
拦截器栈就是将多个拦截器进行打包,
拦截器包里还可以引用其他的拦截器栈
如果有多个action的话,直接调用栈即可。
比如struts1.xml中也想引用exectue_action_timer_interceptor的话,
struts1.xml中继承login包即可
-->
<interceptors>
<!--定义了一个拦截器名字为timer类型是com.opensymphony.xwork2.interceptor.TimerInterceptor,可以算出action的执行时长-->
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<!--interceptor-stack表示拦截器栈可以包含多个拦截器-->
<interceptor-stack name="exectue_action_timer_interceptor">
<interceptor-ref name="timer" /><!--引用了上面的拦截器timer-->
<interceptor-ref name="defaultStack" /><!--默认的拦截器defaultStack-->
</interceptor-stack>
</interceptors>
<action name="login" class="cn.serup.struts2.login.LoginAction">
<result name="success">/success.jsp</result>
<result name="input">/index.jsp</result>
<result name="error">/error.jsp</result>
<!--如果指定拦截器,那么默认的就没有执行,那么就获取不了表单传来的值。所以指定拦截器时候需要加上默认的拦截defaultStack-->
<interceptor-ref name="exectue_action_timer_interceptor" />
</action>
</package>
9、服务端action跳转chain和客户端action跳转redirectAction
chain例子:
<!--
如果使用chain来跳转到某个Action上,
则需要指定param参数的name属性为actionName,
不指定则默认是location,location是指定某个资源JSP/HTML
-->
<action name="test1" class="cn.serup.struts2.Test1Action">
<result name="success" type="chain">
<!-- name="actionName"表示请求的名字,不需要加后缀 ,告诉我action名称即可-->
<param name="actionName">test2</param><!--服务端跳转到名字为test2的actoin-->
</result>
</action>
<action name="test2" class="cn.serup.struts2.Test2Action">
<result>/test1.jsp</result>
</action>
redirectAction例子
<!--
可以通过Result来传参,可以在struts.xml文件中 编写EL表达式 ${nane}是属性的名称
在Test1Action中获得name的值,然后传到到Test2Action中 在Test2Action中接收
-->
<action name="test11" class="cn.serup.struts2.Test1Action">
<result name="success" type="redirectAction">
<param name="actionName">test22?name=${name}</param>
</result>
</action>
<action name="test22" class="cn.serup.struts2.Test2Action">
<!--
这里获得了test11 请求中的属性name的值, 然后通过URL来传递参数 在页面中通过EL表达式来接收并输入${param.name}
-->
<!--redirect表示客户端重定向到那个页面-->
<result type="redirect">/test1.jsp?name=${name}</result>
</action>
10、获得非servlet绑定的request、session和application
方法一:
ActionContextTest.java类
public class ActionContextTest extends ActionSupport {
private Map request ;//request的键值对
private Map session ;//session的键值对
private Map application ;//application的键值对
/**
* 第一种获取方法:非Ioc(控制反转)
* 通过ActionContext对象的 get(Object) 、getSession() 、getApplication()
* 这三个方法分别能获取Map类型的request 和 session 以及 application
* 获取是首先需要获取一个ActionContext对象,然后再调用上面三个方法
* 注意:如果使用此方法获得,则必须在execute()方法中初始化,或构造方法
*/
public ActionContextTest() {
//非Ioc意思就是自己控制,自己创建对象 ActionContext.getContext();
ActionContext c = ActionContext.getContext() ;
request = (Map)c.get("request") ;
session = c.getSession() ;
application = c.getApplication() ;
}
@Override
public String execute() throws Exception {
request.put("r1","r1_value") ;
session.put("s1","s1_value") ;
application.put("a1","a1_value") ;
return SUCCESS ;
}
}
方法二:
ActionContextTest2.java类
public class ActionContextTest2 extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
private Map request ;//request的键值对
private Map session ;//session的键值对
private Map application ;//application的键值对
/**
* 第二种获取方法:Ioc(控制反转)
* 通过RequestAware、SessionAware、ApplicationAware
* 这三个接口分别能获取Map类型的request 和 session 以及 application
* 需要实现它们的方法。
* 然后由struts容器来注入
*/
public void setRequest(Map<String, Object> request) {
this.request = request;
}
public void setSession(Map<String, Object> session) {
this.request = session;
}
public void setApplication(Map<String, Object> application) {
this.application = application;
}
public String execute() throws Exception {
request.put("r1","r1_value") ;
session.put("s1","s1_value") ;
application.put("a1","a1_value") ;
return SUCCESS ;
}
}
页面显示
<%@page contentType="text/html;charset=utf-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
request-s.tags:<s:property value="#request.r1"/><br/>
request-el:${requestScope.r1} ;<br/>
<p></p>
session-s.tags:<s:property value="#session.s1"/><br/>
session-el:${sessionScope.s1} ;<br/>
<p></p>
application-s.tags:<s:property value="#application.a1"/><br/>
application-el:${applicationScope.a1} ;<br/>
11、获得与servlet绑定的request、session和application
方法一:
ServletActionContextTest.java类
public class ServletActionContextTest extends ActionSupport {
private HttpServletRequest request ;
private HttpSession session ;
private ServletContext application ;
/**
* 第一种获取方法:与servlet容器绑定
* 通过ServletActionContext对象来获得,
* 返回的是HttpServletRequest...
*/
public String execute() throws Exception {
request = ServletActionContext.getRequest() ;
session = request.getSession() ;
application = ServletActionContext.getServletContext() ;
request.setAttribute("r1","r1_value") ;
session.setAttribute("s1","s1_value") ;
application.setAttribute("a1","a1_value") ;
return SUCCESS ;
}
}
方法二:
ServletActionContextTest2.java类
public class ServletActionContextTest2 extends ActionSupport implements ServletRequestAware,ServletContextAware {
private HttpServletRequest request ;
private HttpSession session ;
private ServletContext application ;
/**
* 第一种获取方法:与servlet容器绑定
* 通过ServletActionContext对象来获得,
* 返回的是HttpServletRequest...
*/
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletContext(ServletContext application) {
this.application = application;
}
public String execute() throws Exception {
request.setAttribute("r1","r1_value") ;
session.setAttribute("s1","s1_value") ;
application.setAttribute("a1","a1_value") ;
return SUCCESS ;
}
}
页面显示同上
12、OGNL(Object-Graph Navigation Language)对象图导航语言
功能一、支持对象方法调用,形式如:objName.methodName();
功能二、支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路)]@[方法名 | 值名],struts.ognl.allowStaticMethodAccess=true表示允许静态方法访问。
<s:property value="@java.lang.Math@floor(44.56)"/>调用静态方法和方法(非私有的)
功能三、支持赋值操作和表达式串联
功能四、访问OGNL上下文(OGNL context)和ActionContext
功能五、操作集合对象
#号用于访问非根对象(struts中值栈为根对象)
#号用于过滤和投影集合
#号用于构造一个map,如#{'foo1':'bar1', 'foo2':'bar2'}
%号的用途是在标签的属性值被理解为字符串类型时,告诉执行环境%{}里的是OGNL表达式。
$号在国际化资源文件中,引用OGNL表达式。
$号在Struts 2配置文件中,引用OGNL表达式。
首先在页面中引入<%@taglib prefix="s" uri="/struts-tags" %>标签
访问对象中的属性:
user.name:<s:property value="user.name"/><br/>
user.sex:<s:property value="user.sex"/><br/>
user.addr.address:<s:property value="user.addr.address"/><br/>
访问集合:
<s:property value="arrays"/><BR/>
访问数组某个元素:
<s:property value="arrays[0]"/><p></p>
访问Set集合:
为什么只输出3个,但我的set集合中有6个元7D20?原因:set是无序的,重复的被覆盖<br/>
<s:property value="set"/><br/>
为什么获取不出set集合中的某个属性?原因是set是无序的
<s:property value="set[0]"/><p></p>
获取Map集合:
<s:property value="map"/><br/>
获取Map集合中的某个元素:
<s:property value="map.key1"/><br/>
获取所有Map中的所有Key值:
<s:property value="map.keys"/><br/>
获取所有Map中的所有value值:
<s:property value="map.values"/><br/>
集合中的伪类
list:<s:property value="list.size"/>个<br/>
array:<s:property value="arrays.length"/>个<br/>
set:<s:property value="set.size"/>个<br/>
map:<s:property value="map.size"/>个<br/>
获取List中的所有对象
<s:property value="listObject[0].name"/>
<s:property value="listObject[0].sex"/>
<s:property value="listObject[0].addr.address"/>
<br/>
<s:property value="listObject[1].name"/>
<s:property value="listObject[1].sex"/>
<s:property value="listObject[1].addr.address"/>
<br/>
使用投影来获得集合中的对象
<s:property value="listObject.{name}"/><br/>
<s:property value="listObject.{name}[0]"/><br/>
<s:property value="listObject.{name}[1]"/><br/>
13、ValueStack值栈对象
值栈(Value Stack)是Struts 2框架的核心概念,所有核心组件都以某种方式与之进行交互,它提供对上下文信息和执行环境中元素的访问机制
值栈就是内存空间,栈在内存中是后进先出,先进后出,每个请求都会创建一个值栈。值栈的生命周期是跟request请求一致的。客户端跳转的话无法共享值栈。
ValueStack对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。
当Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点(ValueStack对象相当于一个栈)。只是所有的属性值都是默认的值,如String类型的属性值为null,int类型的属性值为0等。
在处理完上述工作后,Struts 2就会调用拦截器链中的拦截器,如获得请求参数的拦截器是params等,在这些拦截器内部读取相应的值,并更新ValueStack对象顶层节点的相应属性的值。
当调用完所有的拦截器后,最后会调用Action类的Action方法,但在调用Action方法之前,会将ValueStack对象中的属性的值终值赋给Action类的相应属性。
对于值栈,则是通过那些使用OGNL(Object Graph Navigational Language,对象图导航语言)语法所编写的特定表达式来查找,或者是在该表达式之上求值。
14、文件上传
UploadAction.java类
public class UploadAction extends ActionSupport {
private List<File> upload;//上传的文件列表
private List<String> uploadFileName;//文件的名称不能乱写,变量名= 文件变量 + FileName
private List<String> uploadContentType;//该变量不能乱写,File对象变量+ContentType获得文件类型,由struts来填充。同上原理。
public List<File> getUpload() {
return upload;
}
public void setUpload(List<File> upload) {
this.upload = upload;
}
public List<String> getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(List<String> uploadFileName) {
this.uploadFileName = uploadFileName;
}
public List<String> getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(List<String> uploadContentType) {
this.uploadContentType = uploadContentType;
}
@Override
public String execute() throws Exception {
if(upload!=null){
//获得绝对目录
String dir = ServletActionContext.getServletContext().getRealPath("upload");
for (int i = 0; i < upload.size(); i++) {
File file = upload.get(i);
InputStream is = new FileInputStream(file);
//根据要保持的文件来创建输出流
OutputStream os = new FileOutputStream(dir + "/" + uploadFileName.get(i));
byte[] buff = new byte[(int) file.length()];
int len = 0;
while((len = is.read(buff, 0, buff.length)) != -1){
os.write(buff, 0, len);
}
os.close();
is.close();
}
}
return SUCCESS;
}
}
index.jsp页面
<form action="testUpload" method="post" enctype="multipart/form-data">
<input name="upload" type="file" /><br/>
<input name="upload" type="file" /><br/>
<input type="submit" value="上传"/><br/>
</form>
struts配置
<package name="upload" extends="struts-default">
<action name="testUpload" class="com.UploadAction">
<result name="success">/index.jsp</result>
</action>
</package>
<constant name="struts.multipart.saveDir" value="upload"></constant><!--表示上传文件的默认目录-->
<constant name="struts.multipart.maxSize" value="102400000000"></constant><!--限制上传文件的大小-->
15、struts2和spring2.5整合:把struts2的创建交给spring
需要导入struts2的包:struts2-spring-plugin.jar(用途是:在spring容器找到所需要的Action实例,通过class属性值对应bean的id来找。)
web.xml配置文件
<!--listener是servlet的监听器,它可以监听客户端的请求、服务器的操作等。-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
applicationContext.xml配置文件:监听器监听到web容器创建好了就加载applicationContext.xml,这样就加载了bean
<bean id="loginAction" class="bean.LoginAction" scope="prototype"></bean>
struts.xml配置文件:由于Action被spring创建了所以action元素的class属性值直接写bean的id就可以了
<package name="default" extends="struts-default">
<!--loginAction是指哪 个bean-->
<action name="login" class="loginAction">
<result>/index.jsp</result>
</action>
</package>
index.jsp页面
<form action="login" method="post" >
<input name="username" type="text"/><br/>
<input name="password" type="text"/><br/>
<input type="submit"/><br/>
</form>
16、