struts2 笔记 1

来源:互联网 发布:文字图片编辑软件 编辑:程序博客网 时间:2024/06/06 02:20

1.Struts2简介

Struts2是一个WEB端MVC框架。
MVC模式:
模型 视图 控制器
模型:分为业务模型和数据模型
视图:负责显示页面,渲染模型
控制器:接收用户请求,调用模型处理用户请求,选择视图显示页面、

目前在Model2中我们使用Servlet作为控制器:
Servlet主要负责:
1.接收用户发送的请求
2.将请求参数封装为Java中的对象
3.调用service来处理业务逻辑
4.根据service返回的结果,选择视图

Servlet可以作为控制器,那么,Filter可以不可以?
- 作为一个控制器的最基本要求,就是可以获得HttpServletRequest对象和HttpServletResponse对象
- 同时还要可以接收到用户请求
- 这些特点Filter都满足,同时Filter中还多了一个FilterChain
- 所以使用Filter作为控制器,只会比Servlet更强。

3.Struts2的HelloWorld

    1.解压apps目录下的struts2-blank.war的压缩包    2.在Eclipse中创建一个新的动态web工程    3.将struts2-blank项目下jar导入动态web工程    4.在项目添加Struts2的核心控制器,接管发送到向所有请求        Struts2的核心控制器就是过滤器,只需要在web.xml文件中引入该过滤器    5.创建自己的Action类,Struts2中的Action就是一个POJO(普通的Java类)    6.在项目中导入Struts2的配置文件,将struts.xml放入到项目src下

Struts2默认会处理没有扩展名和扩展名为.action的请求,这些内容在default.properties中进行了配置

struts.action.extension=action,,

4.Action类

1) Struts2的Action类只要是一个普通的Java类
2) 我们需要为这个Action类提供一个无参的构造器
Struts2会为每一次请求都创建一个Action的实例,所以Action没有线程安全的问题
3) 如果我们需要在Action中来获取请求参数,那么我们需要为请求参数设置一个属性,并要为属性设置响应get和set方法,并且属性名和请求参数名要一致。
这里我们不用考虑为属性赋值,和转型的时,Struts会自动替我们完成。
4) 我们至少要为struts提供一个方法,在处理请求的时候调用。
5) 同一个Action类中可以处理多种的请求。

Action接口(不常用)
我们也可以通过实现Action接口来创建一个Action类。
这个接口中为我们提供了几个结果类型的常量
还提供了一个抽象的execute方法

我们开发中大部情况Action类都会继承ActionSupport类。
- ActionSupport实现类Action等接口。
- ActionSupport对国际化、验证等做了很好的支持。

5.获取Servlet相关API

在Action类中获取Servlet相关的API:
request
session
application

1) ActionContext
ActionContext对象保存当前Action上下文内容,也就是当前Action的相关对象都可以通过ActionContext获取。
ActionContext内部维护了一个Map集合,我们这些对象在Map集合中保存,可以通过key获取value。
在ActionContext中保存对象都是域对象中的Map,而不是我们属性HttpServletRequest、HttpSession、ServletContext
我们通过操作Map实际上就是间接的操作域中的属性

获取ActionContext对象  ActionContext context = ActionContext.getContext();获取application对应的mapMap<String,Object> application = context.getApplication()获取session对应的MapMap<String,Object> session = context.getSession();

注意session的真实类型是SessionMap,它的内部保存一个Session对象
- 我们可以通过该对象invalidate方法来使session失效

获取request对应的Map                Map<String,Object> request = (Map<String,Object>)context.get("request");获取parameter对应的Map                Map<String, Object> parameters = context.getParameters();

2) XxxAware接口
我们还可以通过实现: ApplicationAware,SessionAware,RequestAware, ParameterAware四个接口来获取到对应的Map对象
这四个接口都有对应set方法,当我们实现了这些接口,Struts会自动调用set方法,将对应的Map设置进Action对象
前两种方式获取到都是域对象等对应的Map对象,有的时候我们希望获取到Servlet原生的对象:

ServletContext HttpSession ServletRequest ServletResponse       

3) ServletActionContext
ServletActionContext可以获取到原生Servlet相关的API。
直接获取ServletContext HttpSession ServletRequest ServletResponse这些对象。

//获取ServletContext对象            ServletContext application = ServletActionContext.getServletContext();            //获取HttpServletRequest对象            HttpServletRequest request = ServletActionContext.getRequest();            //通过request对象获取到session对象            HttpSession session = request.getSession();

4) ServletXxxAware接口
我们可以让Action实现ServletRequestAware , ServletContextAware和两个接口,
这两个接口中定义相关对象set方法,当我们这些接口时,Struts会自动调用方法设置相应的对象

6.统计在线人数练习

统计已经登录的人数
1.登录成功以后将用户信息放入Session域中
- 在线人数+1
2.在线人数的信息保存到Application域中。
3.登出时使session直接失效
- 在线人数-1

这里写图片描述

1.result-type 结果类型

Struts2中我们已经不再需要手动跳转到的指定资源,而是Struts2在框架内部替我们完成。
我们可以在action标签配置多个result,并为result指定一个name属性
我们只需要在action方法中返回一个result的那么,则Struts2会自动调到对应result指定资源。
Struts2默认以转发的形式跳转到目标资源,我们也可以通过type属性来指定跳转的方式。
我们比较常用的type属性:
dispatcher 通过转发的形式跳转到目标资源,默认值
例子:

<result name="success" type="dispatcher">                        <param name="location">/WEB-INF/pages/success.jsp</param>                    </result>

dispatcher需要指定一个location属性,指向一个目标资源的地址,
location是默认属性,可以直接在result标签中配置,也可以额通过param标签单独配置

redirect 通过重定向的形式跳转到目标资源
例子:

<result name="success" type="redirect">/success.jsp</result>

注意:重定向时不能重定向到WEB-INF下资源。
使用redirect同样也可以重定向到一个Action

redirectAction 通过重定向的形式跳转到一个Action
例子:

<result name="success" type="redirectAction"><!-- 指定要重定向到action的名字 --><param name="actionName">add</param><!-- 重定向到action的namespace,如果不指定则默认使用当前action的namespace --><param name="namespace">/atguigu</param></result>

chain 将请求直接转到一个Action(通过转发的形式跳转的一个Action)
例子:

<result type="chain"><!--  actionName目标action的名字  --><param name="actionName">add</param><!-- 目标Action的namespace --><param name="namespace">/atguigu</param><!-- method可以指定要调用Action的方法 --><param name="method">update</param></result>

我们还可以在package标签中来映射全局的result

<global-results><result name="success">/WEB-INF/pages/success.jsp</result></global-results>

global-results标签配置到package标签,它可以对当前package中的所有action起作用。
如果action中有和global-results相同名字的result,则会优先使用当前action中配置的result。

2.通配符映射

在配置action的name时可以使用*作为通配符来匹配一个action
比如: user_* 就会匹配以user_开始的所有的action
然后我们可以在action中引用这个, {1}代表第一个号 {2}代表第二个*号
例子:

<action name="user_*" class="com.atguigu.struts2.action.UserAction"                method="{1}"><result>/WEB-INF/pages/{1}.jsp</result> </action>

如果有多个action的name都可以匹配当前请求:那么,会优先匹配没有通配符Action

<action name="user_*" class="com.atguigu.struts2.action.UserAction"                    method="{1}">                    <result>/WEB-INF/pages/{1}.jsp</result> </action>
<action name="user_delete" class="com.atguigu.struts2.action.UserAction"                    method="delete">                    <result>/WEB-INF/pages/success.jsp</result> </action>

如果所有的action都有通配符,则会匹配最上边的action

<action name="user_*" class="com.atguigu.struts2.action.UserAction"                method="{1}">                <result>/WEB-INF/pages/{1}.jsp</result> </action>
<action name="*" class="com.atguigu.struts2.action.UserAction" method="delete">    <result>/WEB-INF/pages/hello.jsp</result>   </action>

3.动态方法调用(DMI)

目前当我们访问一个Action时,action的method属性是啥怎么就会调用啥。
我们可以在地址中传递一个请求参数,来决定到底调用Action中的哪个方法。
调用方式:actionName!methodName
目前动态方法调用在Struts2中默认是关闭,我们如果想使用该功能,需要将DMI打开
打开方式:

<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

4.值栈

当我们通过Action处理完用户请求以后,可以直接在页面中获取到action的属性值。
但是我们自己又没有在域中进行设置,经过研究发现request域中出现了一个奇怪属性
属性的名字:struts.valueStack
属性的类型:OgnlValueStack

ValueStack翻译过叫做值栈,顾名思义就是存储值的栈
Struts在每次处理请求都会创建一个新的ValueStack用来存储这个请求过程中所要用到的属性及对象。
像我们熟悉ActionContext就是值栈的一部分。
同时在值栈中还包含类型的CompoundRoot,这个对象就是模拟了一个栈结构的集合。
值栈实际是由两部分组成 Object Stack 和 Map Context
在Struts调用Action处理请求之前会先将Action对象放入到栈顶
将Action对象放入到对象栈中以后,同时会将值栈对象放入的request域中,方便我们可以在jsp页面中获取到值栈中的属性。

在Servlet我们属性HttpServletRequest实际已经被Struts2用StrutsRequestWrapper给包装了(装饰者模式)
我们的request的getAttributes方法已经被Struts重写。
getAttributes()方法被重写以后,
1.他会先去request中查找指定属性,如果有直接返回
2.如果没有则先去 对象栈 中的栈顶对象开始找起查找,如果有直接返回,不再查找.

Map栈中的内容:parameters Map<String , String[]> 获取当前的请求参数request Map<String , Object> 获取当前request域中的属性session Map<String , Object> 获取当前session域中的属性application Map<String , Object> 获取当前WEB应用的属性attr Map<String,Object> 包含了三个域中的属性,当使用attr来获取属性时,会默认按照域的从小到大查找属性谁先找到就返回谁

5.OGNL(Object-Graph Navigation Language)

OGNL表达式用来从值栈中查找属性
我们需要通过标签来使用OGNL
我们直接在property标签的value属性中传一个OGNL表达式,即可根据表达式去值栈中查找对象。
语法:

属性名 `<s:property value="usename"/>`

这样会默认从对象栈的栈顶对象开查找,直到找到对应属性。如果没找到则返回null

[索引].属性名 <s:property value="[1].usename"/>

从指定索引位置开始查找,如果我们不写索引相当于[0]属性名一些特殊的属性名 [‘属性名’]
如果希望从map栈中查找属性,只需要在表达式的开头加个#
例如:我们要从session域中查找一个属性
session.hello
通过OGNL表达式可以获取到类中静态属性
@全类名@静态属性名

还可以调用静态方法
@全类名@方法名(参数)
注意:Struts默认不支持静态方法调用,需要在配置文件中做如下的配置:

<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

还可以调用非静态方法
一般调用栈顶对象的方法

<s:property value="sayYou()"/> 可以调用栈顶对象的方法            <s:property value="#request.list.size()"/> 可以调用map栈中对象的方法

6.异常处理

当项目中出现异常时,页面会直接显示异常信息,并抛出500状态码。
我们不希望异常在页面中直接显示,
而是应该将异常交给Struts2处理,
并返回给用户友好的错误页面
例子:
局部的异常映射:
局部异常映射要配置到action标签中,只对当前action生效

<!-- exception-mapping用来映射异常处理 -->            <!-- 它有两个参数 exception是要映射的异常类型  result 是指出现异常以后要跳转到哪个页面 -->            <exception-mapping result="input" exception="java.lang.ArithmeticException"></exception-mapping>

如果捕获到异常以后我们异常信息会被Struts2作为栈顶对象放到值栈中,我们可以从值栈中直接获取到异常信息。

全局的异常映射
全局异常映射写在package标签中,会对当前包中的所有action都有效

<global-exception-mappings>                <exception-mapping result="input" exception="java.lang.ArithmeticException"></exception-mapping>            </global-exception-mappings>
0 0
原创粉丝点击