Struts2总结
31 Struts2
-
springnvc和三层结构的关系:
浏览器发出请求,根据actionmapping分析请求路径然后交给actionProxy,proxy读取配置文件,找到请求的action,把interceptors和action交给actionInvocation处理,经过拦截器后执行action,根据返回的string处理jsp,再经过拦截器,最后返回给客户端显示。struts的核心是拦截器采用了aop思想,实现了可插拔。
-
配置流程:struts2就是替代表现层,大致流程和springmvc差不多,配置如下:
1# 导包 struts2-core.Jar,maven会把它的依赖包导进去
2# 在web.xml中配置StrutsPrepareAndExecuteFilter前端控制器(部署描述文件),struts2最早是使用FilterDispatcher当做控制器的,这时把filter当作servlet,这里不用写struts的配
置文件地址,它会自动找classpath下包中的struts.xml配置文件,这个文件名必须写成这样。
<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>//struts里习惯用.action
</filter-mapping>
<!--Filter过滤器的doFilter方法中其实就可以当作Servlet使用,反之不行。-->
3# 配置struts.xml文件。 请求路径:http://localhost:8080/S/test/hello
<struts>
<!-- 这个包用来配置请求路径和控制器的匹配关系 -->
<!--namespace中属性:
name属性值:包的标识,唯一
namespace属性:/test 表示一级处理路径
extends表示继承struts的另一个配置文件,是必选的-->
<package name="test" namespace="/test" extends=”struts-default”>
<!--hello表示处理二级请求,交给class这个类中的execute方法处理,execute方法返回string,常用success或者error,表示成功或者失败-->
<!-- 不写class就是说发出请求路径就直接调用jsp,默认调用类里的execute方法, 如果需要指定自定义的方法,可以添加method=”方法名”指定执行的方法 ,达到一个控制器可以执行多个请求-->
<!--struts中有action中class默认aciontsupport类,method默认的execute方法,result默认的success-->
<action name="hello" class="com.tarena.web.HelloAction">
<!--result用于转发,重定向,默认定向,这里表示成功后转发到jsp页面-->
<result name=”success”>/WEB-INF/jsp/hello.jsp</result>
</action>
</package>
<!---一级路径不同,写不同package,二级路径不同写多个action->
</struts>
4#写业务控制器Action类和jsp文件
Public class HeAction extends ActionSupport{
Public string execute{
Return “success”;}}
3。修改struts的常量配置,struts2的jar包里有一个default.properties配置文件,配置了struts2的常量,下面的方式也是struts执行的顺序
方式一:在struts.xml根标签下使用 (常用)
<!--国际化,解决post提交的乱码-->
<constant name="struts.i18n.encoding" value="utf-8"/>
<!-- 1.热加载配置(不需要重启即可生效),2提供更多的错误信息输出,方便开发时的调试 -->
<constant name="struts.devMode" value="true"/>
<!-- struts访问后缀名,这是默认的后缀名可以为空或action,如http://../hello.action或者//hello都可以访问 -->
<constant name="struts.action.extension" value="action,,"/>
方式二:在src下新建一个struts.properties,修改常量值
方式三:在web.xml配置
<context-param>
<param-name>struts.url.https.port</param-name>
<param-value>443</param-value>
</context-param>
4.如何动态调用方法。
4.1方式一:在struts.xml中配置,常量开启动态配置,访问路径http://..test/actionName!方法名.后缀
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
4.2方式二:(常用)
<action name="dynamic_*" class="heima.zy.DAction" method="{1}">
访问路径:http://../test1/dynamic_方法名.后缀名
这里的_不是必须,只是*号是传给后面的method
5. 传值:Struts设计的每次请求创建新的action对象。是线程安全的。struts支持把页面的8大基本数据类型自动转换包装,对于页面的string能自动转成java.util.Date类型。
5.1 如何从页面获取值(原理:属性封装在action类中)
在类中声明页面的值的name,有getset方法,(实质是set方法给属性赋值)
5.2对象驱动:(原理:User对象存在action对象中)
例子:
#在页面的name属性设置成user.name user.pwd (user是小写)
#建一个类User 有name pwd属性和get set方法不
#在action类中 ,写User属性,生成getset方法
class JAction(){
Private User user;
Public setUser(User user){
This.user=user;}
execute(){
方法中就可以直接使用user的get方法取值 }}
这样在大量重复的数据中能重用user这个原理就是表单通过set方法设置。
5.3 模型驱动:(原理:实现了这个接口,就是调用了拦截器,在参数接收之前把User压入ValueStack的root栈顶)
新建一个User类,把页面的name值age、name等全封装,Action类实现接口,这样就能传值了,User类不需要getset方法。
public class HAction implements ModelDriven<User>{
private User user=new User();
public User getModel() {
return user;}}
5.4封装List Map对象,User类已经定义。
5.4.1List对象
5.4.2 Map<String,User>对象
6.数据消息中心:ActionContext,保存的Map对象,有request、session、application、param、attr(前三个合一)、ValueStack等等。其中前面几个都是封装了的Map对象,每次接受http请求就创建一个actioncontext,请求处理完就销毁,但不会影响其中的对象,它只是保存对象而已。ActionContext设计的原理是和当前线程绑定在一起,所以使用ThreadLoacl就可以获取它。 在创建ActionContext时,就是把ValueStack.getContext()作为ActionContext的构造函数的参数。struts2不推荐使用request域,struts对request进行了封装,actioncontext和request生命周期相同,放actionccontext中就行,ActionContext.getContext().put("sex", "man");
7.如何获取session
在登录思路中,通过页面传递表单的值,经过三层结构成功验证之后就把值绑定在session上,struts的session方法获取有两种:
7.1 方式一:通过ActionContext 获取
ActionContext a = ActionContext.getContext();
Map<String,Object> session=a.getSession();
Session.put(s,v);
方式二:实现serssionawaer接口
-
Result的type返回值,每种类型是一个类在处理。(可查看相应result的类的源码的javadoc看使用方法。)
2.1 默认type是dispatcher,转发到jsp
<result name="success">
/WEB-INF/hello.jsp
</result>
2.2 返回值是redirectAction,语法如下,
<result name="error" type="redirectAction">
<param name="namespace">/命名空间名</param>
<param name="actionName">action名</param>
</result>
2.3result返回值是stream,用于显示图片或者下载word、excel,视频等,配置如下
2.4 result返回值为json,用于处理ajax请求。
## 导入插件struts-json-plugin.jar
## 写action控制器,需要返回的json数据,因为action中的数据不都是需要发送过去的,所以可以在里面定义一个集合或者对象,然后再result中配置一个param指定发送的数据,如果不指定param会把action所有数据当作json发送。
@Controller
public class JsonAction {
private String message;
private int id;
private Map<String, Object> map = new HashMap<String, Object>();
public Map<String, Object> getMap() {
return map;
}
public String getMessage() {
return message;
}
public int getId() {
return id;
}
public String execute(){
id=44;
message="你好";
map.put("id",id);
return "success";
}}
## struts配置文件,这里extends=”json-default”,result的返回类型是json,如果不配置param这个root,json返回的是全部属性。
<package name="ttt" namespace="/test" extends="json-default">
<action name="json" class="jsonAction">
<result name="success" type="json">
<param name="root">map</param>
</result>
</action>
</package>
11、OGNL表达式:对象导航语言,struts的参数都是通过ognl引擎处理。
OGNL中有两个区域,一个root对象,一个context区域,存放Map对象.
11.1 数据准备
//准备user类,Map类
User user = new User("zhouyang", 20);
Map<String,User> map = new HashMap<String,User>();
map.put("user1",new User("张三", 21));
map.put("user2", new User("李四", 22));
//新建ognl类
OgnlContext context = new OgnlContext();
//设置root栈和context区域
context.setRoot(user);
context.setValues(map);
11.2 取root区域和context区域值
String name=(String) Ognl.getValue("name",context,context.getRoot()); //取root栈
Integer age=(Integer)Ognl.getValue("#user1.age",context,context.getRoot()); //取context域
11.3 设置root值和context值
Ognl.getValue("name='chenchen'",context,context.getRoot()); //在setvale中直接使用=''就能设置值
Ognl.getValue("#user1.age=22",context,context.getRoot()); //同上
String name=(String) Ognl.getValue("name='晨晨',name",context,context.getRoot()); //设置值的同时候,取root栈,之间用逗号隔开
Integer age=(Integer)Ognl.getValue("#user1.age=22,#user1.age ",context,context.getRoot()); //设置值的同时候,取context域
11.4 调用方法
Ognl.getValue("setName('aaaa'),getName()",context,context.getRoot()); //root栈的对象的方法
Ognl.getValue("#user1.setName('aaaa'),#user1.getName()",context,context.getRoot()); //context域的对象的方法
11.5 调用静态方法 (@类名@方法||常量)
Ognl.getValue("@java.lang.Math@abs(22)",context,context.getRoot());
Ognl.getValue("@java.lang.Math@PI",context,context.getRoot());
11.6 创建List和Map对象
Integer n=(Integer)Ognl.getValue("{'1','2','3'}.size()",context,context.getRoot()); // 用{}创建
Integer n=(Integer)Ognl.getValue("#{'1':1,'2':2,'3':3}.size()",context,context.getRoot()); //用#{键值对}创建
12 valueStack(值域) ,由OGNL框架实现;
11.1域值有连个区域,一个区域是root的List栈存储值。默认存Action类。是Action类中通过set方法设置的属性值(表单传过来的值等)
#添加进域值的办法有action类的变量或者获取valueStack 再把对象push进去。
ActionContext actionContext = ActionContext.getContext();
ValueStack valueStack = actionContext.getValueStack();
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "周杨");
valueStack.push(map);
#Context区域:就是ActionContext的数据中心
补充:Struts中扩展了request的getAttribute()
12.2 如何在jsp中获取值
12.2.1使用EL表达式,struts拦截了EL表达式,使其从valueStack中获取数据,el查询顺序是原始域》valueStack(root》context)
12.2.2使用OGNL表达式获取valuestack中的值
在jsp中导入标签库 <%@taglib prefix="s" uri="/struts-tags" %> <s:debug></s:debug>是显示valueStack,
读取root区域值:<s:property value="name"/>,从栈顶依次读取属性,找到就输出
读取Context区域值:<s:property value="#session.name">
12.3 valueStack的作用,是软件的消息中心,作用相当于jsp的pageContext
#控制器向页面输出数据的缓冲区
#获取环境变量
13、拦截器,struts本身在struts-default.xml中定义了很多拦截器,action都启用了这些defaultstack,拦截器的生命周期和项目相同。
13.1 创建拦截器
方式一:
##写一个类实现interceptor接口,实现接口方法。
public String intercept(ActionInvocation invocation) throws Exception {
//action前的处理
invocation.invoke();//拦截器的放行。
//后处理
return null; //拦截器实现的源码是递归调用拦截器,当没有了拦截器在调用action,action执行的返回值赋值给这里的string,根据string值做相应的result判断处理,如果不想放行,就返回相应的string交给result处理。就不会执行后面的拦截器和action。想放行就return invocation.invoke();
}
##在struts.xml的package下注册拦截器
<interceptors>
<!--注册拦截器 -->
<interceptor name="myInterceptor" class="zy.action.DemoInterceptor"/>
<!-- 注册拦截器栈 -->
<interceptor-stack name="myStack">
<!--引用拦截器,建议自定义放前面,执行顺序-->
<interceptor-ref name="myInterceptor"/>
<!--引用默认拦截器-->
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!---给当前包指定默认拦截器,也可以给action下指定自己的拦截器,- ->
<default-interceptor-ref name="myStack"/>
方式二:继承AbstractInterceptor类,其他和方式一相同。
方式三:继承抽象类MethodFilterInterceptor类,其他同上。
13.2 为拦截器指定拦截方法(自定义的拦截器必须继承MethodFilterInterceptor类)
<interceptor-ref name="myInterceptor">
<param name="excludMethods">add,delete</param> <!--指定action中那些方法不拦截-->
<param name="includMethods">add,delete</param> <!--指定action中那些方法拦截,这两个参数不能同时指定-->
</interceptor-ref>
13.3全局结果集:拦截器拦截后,是在对象的action中找result,所以可以配置一个全局结果集
<global-results>
<result name="toLogin">/toLogin.jsp</result>
</global-results>
14.struts2对异常的处理
在service抛出异常给struts后,可以通过配置实现异常的封装
##1 在struts.xml的package下,action上配置
<global-exception-mappings>
<!-- 此包下的action遇到这种异常就转到error的result结果去 -->
<exception-mapping result="error" exception="java.lang.RuntimeException"/>
</global-exception-mappings>
##2 action遇到异常会把异常封装到root栈顶去,有一个exception属性,所以在jsp页面中使用ognl<s:property value="exception.message"/>获取异常信息。
补充:可以把action一些通用的属性单独放在一个类,其他action继承这个类。比如把可能需要的session request aplication先创建出来,一般action需要继承ActionSupport,能更好的服务action
15 struts2标签
itrator if elseif else form textfiled 等等
技巧:在配置result类型,打开类型对应的类的源码,在javadoc下查看配置方法。
Spring整合struts
1.开发步骤:
1#导包 struts-spring-plugin.jar,这个包倒进去会自动把spring的相关包都导进去,注意这个包进去了就找spring容器,找不到抛出异常。
2#在web.xml中配置ContextLoaderListener,它会自动从/WEB-INF/下寻找一个applicationContext.xml的配置文件,也可以配置一个contextparam指定spring文件位置,用来启动spring
<!-- 配置Listener,用于web容器启动的时候自动初始化spring容器, -->
<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>
ContextLoaderListener继承contextloader类实现servletcontextliistener接口,用于监听context上下文,这个监听器的实现主要是依靠contxtloader类,根据配置文件,实例化一个webapplicationcontext容器,再把它放在serverletcontext中,达到一个项目只有一个spring容器,这个webapplicationcontext也是applicationcontxt的子类,这样spring容器就随着项目一起启动了。
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext())
ac1.getBean("beanId");
3#在spring的配置文件中,添加组件扫描,在struts的组件类上写注解@Controller把它注入到spring容器中。@ scope="prototype"保证每次请求一个action处理。
4#其他和struts的写法都一样,只是在action的class上写的是这个action的beanId(首字母小写),照原来写类名也可以表示按类名查找。
5# 导入这个整合插件后,可以开启一个常量
<constant name="struts.objectFactory" value="spring">
这样spring就引发了另一个常量struts.objecdtFactory.autowried=true,
在actin类中,注入就直接自动引用,不用注解获取了。
private User user;
public User getUser(){}
Spring struts Mybatis整合
在spring整合struts之后,在action中调用mybatis的service和dao。。。

浙公网安备 33010602011771号