1、Struts2是什么
Struts2是在WebWork2基础发展而来的。和Struts1同样, Struts2也是基于MVC的web层框架。
那么既然有了Struts1,为什么还要Struts2?
Struts2和Struts1虽然都是基于MVC的Web框架,可是它们的实现机制彻底不一样。
Struts1是基于Servlet的实现,而且Struts1的API过度依赖容器,致使了Action开发、测试都很是繁琐,而Struts2是基于过滤器的实现,API再也不依赖容器,测试过程当中没必要再模拟Web容器环境,开发、测试较Struts1都有很大的进步。
Struts1的Action是单例模式全部请求共享一个ActionServlet,因此线程必须是安全的,而Struts2每一个请求都会绑定一个Action,再也不有线程安全问题。
Struts2开始支持注解并提供了更为强大的OGNL标签库以及值栈,从类到页面的开发都更加简洁高效。
Struts2和Struts1都是基于MVC的Web层框架,因此,他们工做原理仍是同样的,都是对请求进行拦截、分发、处理,以后返回页面,只不过他们的实现机制不一样罢了。
所以,Struts2的工做原理就再也不过多介绍,下面咱们来看如何使用Sturts2搭建一个Web开发环境。
2、Struts2的使用
让咱们先用Sturts2 展现一个Helloworld。
一、建立web项目struts2_helloworld,添加Struts2的依赖支持
struts2-core-2.3.8.jar
xwork-core-2.3.8.jar
commons-lang3-3.1.jar
ognl-3.0.6.jar
javassist-3.11.0.GA.jar
asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
freemarker-2.3.19.jar
commons-fileupload-1.2.2.jar
commons-io-2.3.jar
二、在web.xml中配置struts2
<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>
三、建立Struts2配置文件struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!
DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package
name="default" namespace="/" extends="struts-default">
<
action
name="hello"
class="com.boya.struts2.web.HelloAction">
<result>
/helloWorld.jsp
</result>
</
action>
</package>
</struts>
注意,与Struts1不一样,Struts2的配置文件并不放在WEB-INF目录下,而须要放置在src源码根目录下
四、建立Action类
public class HelloAction {
public String execute() {
return "success";
}
}
五、建立返回页面helloWorld.jsp
如今就完成了一个简单的Struts2应用。启动Web服务器,访问:
就能够看到咱们建立的helloWorld.jsp页面了。
3、Sturts2的配置介绍
一、在web.xml配置Strut2过滤器拦截
Sturts1是经过servlet映射实现的对请求的拦截,Struts2是经过Filter完成的对请求拦截。前者会在ActionSerlvet中加载核心配置文件,后者会在StrutsPrepareAndExecuteFilter过滤器中加载。所以,与Struts1不一样的是,咱们要在web.xml里面配置Struts2的Filter来拦截请求。
配置方式见上文。
二、Strtus2核心配置文件
Struts2的默认配置文件是struts.xml,须要放置在源码根目录下。
struts.xml中的action标签和Struts1中的做用同样,都是定义了一种映射关系。package标签则代表以包的形式来管理action和拦截器,一般状况下,按将逻辑相关一组业务Action做为一个模块放在同一个package下管理。
package有如下属性;
name:包名称,其余包使用name继承当前包,不能重复
namespace:定义当前包的命名空间,匹配请求URL的路径部分,不一样的命名空间下能够有重名的action
extends:当前包继承的父包,继承以后,当前包拥有父包中所定义的任意类、拦截器等
abstract:定义当前包为一个抽象的包,也就是说不能有action元素在当前包中
action属性:
name:action名称,用来匹配请求URL
class:对应的具体Action实现类,默认为ActionSupport
method:执行action时调用的方法,默认执行execute(),也能够在URL中动态指定,例如:
<a href="${ctx}/system/user!add">添加用户</a>
result标签:定义action的返回跳转页面
name:定义页面跳转名称,默认为success。在action中返回一个对应name的字符串,就会返回到对应的jsp页面
type:设置返回结果类型,默认为dispatcher,用于返回jsp页面
三、URL映射机制
Struts1中,咱们是使用path来映射URL请求的。在Struts2中是使用namespace + action的name来映射URL的。
例如:
namespace="/system" ,
action设置name为"/user"
那么这个action对应的URL就是 http://主机地址/工程名/system/user
namespace寻址机制:
对于咱们的一个URL请求,例如http://主机地址/工程名/path1/path2/path3/user
Struts2会自动将URL中的后缀,以及Host和工程名去掉,将/path1/path2/path3这部分认为是namespace,首先会查找namespace="/path1/path2/path3",若是这个命名空间查找不到,会继续查找namespace="/path1/path2",仍然没有的话,会继续查找上一级命名空间,直到查找到namespace="/"为止。
查找到命名空间,会在该命名空间的package下查找name="/user"的action。最后将这个请求交给action对应的业务处理类处理。
namespace默认为"",当在其余namespace中映射不到的时候,都在这个namespace中寻找。
Struts2是用namespace和actionName来惟一区别一个Action,所以,在同一个namespace下不能配置同名的action,在不一样的namespace下,能够有重名action。
四、映射方式配置
在web.xml的过滤器映射中除了这样配置:
<filter-mapping>
<filter-
name>struts2</filter-
name>
<
url-pattern>/*</
url-pattern>
</filter-mapping>
也可使用扩展名配置:
<filter-mapping>
<filter-
name>struts2</filter-
name>
<
url-pattern>*.action</
url-pattern>
</filter-mapping>
action是struts2默认支持的扩展名。/*在完成*.action的基础映射功能下,提供了额外的支持
a、用于访问classpath中特定的静态资源(若是是/struts、或者/static开始的资源,则在classpath下查找特定的包下面的匹配资源;)
b、支持无后缀的action请求
使用/*方式映射时:
访问/struts或/static目录,不但愿加载strtus的静态资源的配置方式
<constant name="struts.serve.static" value="false" />
但愿强制使用扩展名映射的配置方式
<constant name="struts.action.extension" value="action" />
一样可使用上面的配置修改struts2的默认扩展名
<constant name="struts.action.extension" value="do" />
不但愿映射某个目录时(目录须要是一个正则表达式,所以须要使用.*的方式表示)
<constant name="struts.action.excludePattern" value="/dwr/.*,/noaction/.*" />
五、Action的方法映射
a、Action的方法映射能够经过method指定,未指定method方法时,默认执行execute()方法
b、映射方法还能够在URL中动态指定(动态方法调用DMI)
例如访问 http://localhost:8080/struts2_helloworld/hello!print 会调用hello对应的Action中的print()方法
注:可使用struts.enable.DynamicMethodInvocation参数配置DMI的开启关闭,默认为开启
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
c、使用通配符映射
<action name="*_*" class="com.boya.struts2.web.{1}Action" method="{2}">
<result>
/{0}.jsp
</result>
</action>
使用{1}{2}{3}...{9}的顺序来匹配*,{0}匹配总体
注:Struts2的通配符配置方式,极不灵活,不推荐使用
六、设置返回结果类型
返回结果类型能够经过result标签的type属性配置,默认类型为dispatcher,用于返回jsp页面。经常使用的返回结果类型有redirect、chain、json等
redirect类型配置(重定向到一个新的URL请求):
<result name="success" type="redirect">/hello.jsp?name=${name}</result> <!--重定向到一个jsp页面-->
<result name="success" type="redirect">/hello.action</result> <!--重定向到一个acton请求-->
redirectAction类型配置(重定向到其余action):
<result type="redirectAction">
<param name="namespace">/</param> <!--重定向Action所在的命名空间,默认为当前命名空间-->
<param name="actionName">user</param> <!--重定向的Action名称-->
<param name="method">login</param> <!--重定向Action的方法名称-->
<param name="name">boya</param> <!--重定向传参-->
<param name="password">123456</param> <!--重定向传参-->
</result>
chain类型配置,配置相似redirectAction(链到其余action,也就是转发操做):
<result type="chain">
<param name="namespace">/</param> <!--Action所在的命名空间,默认为当前命名空间-->
<param name="actionName">user</param> <!--Action名称-->
<param name="method">login</param> <!--Action的方法名称-->
</result>
json类型配置
a、添加struts2-json-plugin-2.3.8.jar
b、Action代码(省略getter、setter方法,省略User实体类):
public
class JsonAction
extends ActionSupport {
private Map<String,Object> dataMap;
public String json() {
dataMap =
new HashMap<String, Object>();
User user =
new User();
user.setName("张三");
user.setAge(50);
dataMap.put("user", user);
return SUCCESS;
}
}
c、配置struts.xml
<package
name="json" extends="struts-default,json-default" >
<
action
name="json"
class="com.boya.struts2.web.JsonAction">
<result
type="json">
<
param
name="root">dataMap</
param>
</result>
</
action>
</package>
package须要继承"json-default"
result类型须要配置为json
result参数:
root:指定返回属性,默认返回全部有返回值的getter方法的值
excludeNullProperties:是否返回值为空的属性,值为boolean类型
ignoreHierarchy:是否忽略父类属性,值为boolean类型
includeProperties:指定返回root中的哪些属性,值为正则表达式,可以使用逗号分隔设置多个
excludeProperties:指定排除root中的哪些属性,值为正则表达式,可以使用逗号分隔设置多个
d、返回内容:
{"user":{"age":22,"name":"张三"}}
excludeProperties和includeProperties的验证区别:
首先,假设dataMap中返回结果为:{"users":[{"age":22,"name":"张三","password":"123456"},{"age":40,"name":"李四","password":"654321"}]}
设置了排除或包含的属性后,以上结果须要验证的元素有users、users[0]、users[0].age、users[0].name、users[0].password、users[1]、users[1].age、users[1].name、users[1].password
若是要排除password属性,须要设置<param name="excludeProperties">users.*\.password</param> ,excludeProperties是将正则表达式做为总体分别匹配以上各元素,这样就会把password排除掉。
若是要只包含name属性,则不能设置为<param name="includeProperties">users.*\.name</param>,includeProperties会将正则表达式拆为users.*、users.*\.name(对分隔符,数组索引符合,对象属性间的点链接符等进行分割处理),这两个正则分别与上面各元素匹配,而users.*就会匹配所有元素,因此没法排除。
要精确包含name属性,须要设置为:<param name="includeProperties">users\[\d+\]\.name</param> ,而这时,正则表达式会被拆为users, users\[\d+\], users\[\d+\]\.name ,最终只输出name属性。
4、Action处理
一、接收参数
a、使用属性来接收参数
例如,在UserAction中定义以下属性,并添加getter、setter方法
private String name;
private String password;
jsp使用对应名称的控件
用户名<input type="text" name="name"><br>
密码<input type="password" name="password"><br>
这样就能够把提交的参数值传给UserAction的属性。
也能够经过URL将参数值传递给Action,如:
b、使用DomainModel接收参数
例如,在UserAction中添加实体Bean类型的属性,一样须要添加getter、setter方法
private User user;
jsp的控件名称使用“对象.属性”形式,如
用户名<input type="text" name="user.name"><br>
密码<input type="password" name="user.password"><br>
这样,提交的参数会自动封装如user对象中。在Action方法中,使用user.getName()就能够获取提交的用户名
使用URL传递参数就是这样的形式:
二、获取web容器的request和session
Struts2不像Struts1那样依赖容器,默认状况下,request、session这些容器对象都是隐藏的,而且Struts2层分别使用RequestMap、SessionMap对request、session进行封装,是咱们可使用Map的key-value形式对request、session进行操做。咱们能够获取RequestMap来做为request使用,也能够像传统web开发那样获取一个HttpServletRequest对象。
a、非IoC方式
这种方式主要是利用了com.opensymphony.xwork2.ActionContext类以及org.apache.struts2.ServletActionContext类,分别用于获取RequestMap和HttpServletRequest对象。
获取RequestMap、SessionMap对象
Map request = (Map)ActionContext.getContext().get("request");
Map session = ActionContext.getContext().getSession();
获取HttpServletRequest、HttpSession对象
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
b、IoC方式
这种方式相似SpringIoc控制反转,是使用依赖注入的方式得到request和session对象的。
获取RequestMap、SessionMap对象,Action须要实现RequestAware, SessionAware接口
private Map request;
private Map session;
@Override
public
void setRequest(Map request) {
this.request = request;
}
@Override
public
void setSession(Map session) {
this.session = session;
}
获取HttpServletRequest、HttpSession对象,Action须要实现ServletRequestAware接口
private HttpServletRequest request;
private HttpSession session;
@Override
public
void setServletRequest(HttpServletRequest request) {
this.request = request;
this.session = request.getSession();
}