一、struts2是由Webwork2发展而来的相比struts1具有如下优点
1、在软件设计上Struts2没有像struts1那样跟Servlet API和strutsAPI有着紧密的耦合,Struts2的应用可以不依赖于ServletAPI和struts API。 Struts2的这种设计属于无侵入式设计,而Struts1却属于侵入式设计。
2、Struts2提供了拦截器,利用拦截器可以进行AOP编程,实现如权限拦截等功能。
3、Strut2提供了类型转换器,我们可以把特殊的请求参数转换成需要的类型。在Struts1中,如果我们要实现同样的功能,就必须向Struts1的底层实现BeanUtil注册类型转换器才行。
4、Struts2提供支持多种表现层技术,如:JSP、freeMarker、Velocity等
5、Struts2的输入校验可以对指定方法进行校验,解决了Struts1长久之痛。
6、提供了全局范围、包范围和Action范围的国际化资源文件管理实现
二、搭建struts2开发环境
1、找到开发Struts2应用需要使用到的jar文件,一下是struts2最少需要的jar包
struts2-core-2.x.x.jar :Struts 2框架的核心类库
xwork-core-2.x.x.jar :XWork类库,Struts 2在其上构建
ognl-2.6.x.jar :对象图导航语言(ObjectGraph Navigation Language),struts2框架通过其读写对象的属性
freemarker-2.3.x.jar :Struts 2的UI标签的模板使用FreeMarker编写
commons-logging-1.x.x.jar :ASF出品的日志包,Struts2框架使用这个日志包来支持Log4J和JDK1.4+的日志记录。
commons-fileupload-1.2.1.jar 文件上传组件,2.1.6版本后必须加入此文件
2、编写Struts2的配置文件
struts2的默认配置文件为struts.xml,该文件存放在WEB-INF/classes下,(开发时存放在src下)
<?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="main" extends="struts-default" namespace="/">
<global-results>
<result name="login" type="redirect">/login.jsp</result>
</global-results>
<action name="loginaction" class="org.jyjd.action.LoginAction">
<result name="success">/welcome.jsp</result>
<result name="input">/login.jsp</result>
</action>
<action name="logoutaction" class="org.jyjd.action.LogoutAction"></action>
<action name="registeraction" class="org.jyjd.action.RegisterAction">
<result name="success">/welcome.jsp</result>
<result name="input">/register.jsp</result>
</action>
<action name="loginaction2" class="org.jyjd.action.LoginAction2">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
3、在web.xml中加入Struts2MVC框架启动配置
在struts1.x中,struts框架是通过Servlet启动的。在struts2中,struts框架是通过Filter启动的。他在web.xml中的配置如下
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三、struts2中struts.xml配置
1、struts.xml中包的配置:
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute" >
<result name="success">/WEB-INF/page/hello.jsp</result>
</action>
</package>
struts2中用package来管理action,同一组业务功能的action我们可以放在同一包中。配置包时必须指定name唯一,继承时使用该属性同时每个包都应该继承struts-default包,包的namespace属性用于定义该包的命名空间,命名空间作为访问该包下action路径的一部分,如上访问时路径为:/test/helloworld.action。
2、action的配置:
action中的属性可以用el表达式访问${message}
action中各项的默认配置:
如果没有为action指定class,默认是ActionSupport。
如果没有为action指定method,默认执行action中的execute()方法。
如果没有指定result的name属性,默认值为success。
3、result的配置:
result配置类似于struts1中的forward,但struts2中提供了多种结果类型,常用的类型有: dispatcher(默认值)、 redirect 、redirectAction、plainText。
在result中还可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中的属性。如下:
<resulttype="redirect">/view.jsp?id=${id}</result>
下面是redirectAction 结果类型的例子,如果重定向的action中同一个包下:
<result type="redirectAction">helloworld</result>
如果重定向的action在别的命名空间下:
<result type="redirectAction">
<param name="actionName">helloworld</param>
<paramname="namespace">/test</param>
</result>
plaintext:显示原始文件内容,例如:当我们需要原样显示jsp文件源代码的时候,我们可以使用此类型。
<result name="source"type="plainText ">
<param name="location">/xxx.jsp</param>
<param name="charSet">UTF-8</param><!-- 指定读取文件的编码 -->
</result>
4、为action的属性注入值:Struts2为Action中的属性提供了依赖注入功能,在struts2的配置文件中,我们可以很方便地为Action中的属性注入值。注意:属性必须提供setter方法。
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="cn.itcast.action.HelloWorldAction" >
<param name="savePath">/images</param>
<result name="success">/WEB-INF/page/hello.jsp</result>
</action>
</package>
上面通过<param>节点为action的savePath属性注入“/images”。
5、常量的配置:
常量可以在struts.xml或struts.properties中配置,建议在struts.xml中配置,如我们可以配置struts2只处理.do结尾的请求
<struts>
<constant name="struts.action.extension" value="do"/>
</struts>
常用到的配置如下
<!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 -->
<constant name="struts.i18n.encoding" value="UTF-8"/>
<!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
<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"/>
三、struts2工作原理
1、struts2的处理流程:
StrutsPrepareAndExecuteFilter是Struts2框架的核心控制器,它负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。
默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入Struts 2框架处理,否则Struts 2框架将略过该请求的处理。当请求转入Struts 2框架处理时会
先经过一系列的拦截器,然后再到Action。与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以Struts2中的Action是线程安全的。
2、指定多个struts配置文件<?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>
<include file="struts-user.xml"/>
<include file="struts-order.xml"/>
</struts>
3、在action中访问request、session、application属性
public String scope() throws Exception{
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app
ctx.getSession().put("ses", "session范围");//往session里放入ses
ctx.put("req", "request范围");//往request里放入req
return "scope";
}
输出到jsp页面
<body>
${applicationScope.app} <br>
${sessionScope.ses}<br>
${requestScope.req}<br>
</body>
4、struts2与servlet耦合,获得HttpServletRequest、HttpSession、ServletContext、HttpServletResponse
方法一:通过ServletActionContext类直接获取
public String rsa() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
ServletContext servletContext = ServletActionContext.getServletContext();
request.getSession()
HttpServletResponse response = ServletActionContext.getResponse();
return "scope";
}
方法二:实现指定接口由struts2框架运行时注入
public class HelloWorldAction implements ServletRequestAware, ServletResponseAware, ServletContextAware{
private HttpServletRequest request;
private ServletContext servletContext;
private HttpServletResponse response;
public void setServletRequest(HttpServletRequest req) {
this.request=req;
}
public void setServletResponse(HttpServletResponse res) {
this.response=res;
}
public void setServletContext(ServletContext ser) {
this.servletContext=ser;
}
}
5、自定义拦截器
要自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor接口:
public class PermissionInterceptor implements Interceptor {
private static final long serialVersionUID = -5178310397732210602L;
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("进入拦截器");
if(session里存在用户){
String result = invocation.invoke();
}else{
return “logon”;
}
//System.out.println("返回值:"+ result);
//return result;
}
}
因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。
如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref name=“permissionStack”/>把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用。
<package name="itcast" namespace="/test" extends="struts-default">
<interceptors>
<interceptor name=“permission" class="cn.itcast.aop.PermissionInterceptor" />
<interceptor-stack name="permissionStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name=" permission " />
</interceptor-stack>
</interceptors>
<action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
<result name="success">/WEB-INF/page/hello.jsp</result>
<interceptor-ref name="permissionStack"/>
</action>
</package>