您的位置:首页 > 编程语言 > Java开发

struts2 笔记 1

2016-04-11 21:53 453 查看

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对应的map
Map<String,Object> application = context.getApplication()
获取session对应的Map
Map<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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: