设置一个入口,前端控制器本就是一个过滤器,替服务器完成访问数据资源入口的 操作
一.导入struts2 jar包 (需要什么包就导入什么包,有一些包需要配置,不配置找不到action)
二.在web.xml中配置前端控制器因为它是一个过滤器,新建一个Folder包名classes字节码到WebContext下然后更换项目中默认的字节码文件
三.在项目下创建一个Source Folde同级的字节码包resources,和src同级其实可以把文件放在src下但是为了规范使用所以需要建包,放struts.xml
在web.xml中配置Struts2的前端控制器(对所有资源进行过滤)
配置文件的细节使用
配置文件的拆分,可以在创建一个xml然后在struts.xml中引用子文件
六大配置文件:
1.default.properties
2.struts-default.xml(4.struts.xml 中需要继承的xml文件)
3.struts-plugin.xml(插件)
==============
4.struts.xml (配置子控制器与常量)推荐使用修改常量
5.struts.properties(修改常量)
6.web.xml(配置主控制器)
排列顺序
1.框架自带:default.properties /struts-default.xml/struts-plugin.xml
default.properties配置的编码,访问后缀名以及其他常量
2.可以修改:struts.xml / struts.properties/web.xml
2.1struts.properties可以修改default.properties中的常量配置
在resources中新建一个file文件名struts.properties
在default.properties复制需要修改的配置文件到struts.properties
2.2第二种修改方式在struts.xml中修改
2.3如果多个文件配置了同一个struts2常量,则后一个文件中配置的常量值会覆盖前面文件配置的常量值
注:我们一般只在是struts.xml中修改常量
Struts2中常见的常量:
1)指定默认编码集,<constant name="struts.i18n.encoding" value="UTF-8"/>
注:在struts 2 中post请求参数的编码方式为UTF-8
2)该属性指定需要Struts 2处理的请求后缀
<constant name="struts.action.extension" value="hjm"/>
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号隔开
3)设置浏览器是否缓存静态内容,默认值为true(生产环境下使用)开发阶段最好关闭
<constant name="struts.serve.static.browserCache" value="false"/>
4)当struts的配置文件修改后,系统是否自动重新加载改文件默认值为false(生产环境下使用),开发阶段最好打开
<constant name="struts.configuration.xml.reload" value="true"/>
5)开发者模式下使用,这样可以打印出更详细的错误信息
<constant name="struts.devMode" value="true"/>:修改struts.xml之后,不需要重启服务器(包含第四段功能)
6)默认是视图主题
<constant name="struts.ui.theme" value="simple"/>
7)是否支持动态方法的调用(通配符需要打开)
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
package,action,result 的相关配置
<package>元素:是<struts>根元素的子元素。
用来对多个<action>元素分类管理,和Java中的package没有关系
常见的属性:
<package name="" extends="" namespace="" abstract=""></package>
name: 表示<package >的名字 但是要保证不同的<package >元素name不同,可以通过改名字被其他包继承
extends: 指定当前包继承哪一个package,通常是直接继承strute-default
namespace:和action的name属性一起决定访问的是那个action
abstract:表示当前package是抽象的,表实package中配置action不能够直接使用,当namespace="true"时只能用来被继承
action的元素:是package的子元素
需要struts 2 框架帮我们管理action的生命周期。
1.对象的创建,使用反射方式来创建action对象
专门用来配置action对象的
<action name="" method="">
常见的属性:
name : action的名称,在同一个package中,action的名字必须唯一,和package的namespace共同决定了一个action的访问路径
注:一个action的name值不能以/打头
class:全路径名:默认值:Action Support类
method:当前Action动作访问的方法 默认值:execute
如果请求只需要一个简单的跳转,可以使用默认值,默认execute返回的结果集为success
result中的属性:
dispatcher:转发
redirect:重定向
chain:转发到另一个action
redirectAction:重定向到另一个action
stream:表示返回流,文件下载时使用。
param标签:(在result标签中)
跳转页面不用,直接跳转到当前action不要写
如果跳转到另外一个package中的action,需要写
全局结果视图(必须在action前面)
如果在多个action中有相同的result那么我们就可以使用这个全局结果视图标签
使用标签<global-results>中间放置全局的结果视图</global-results>
Action类的三种编写方式:
1.使用公用的pojo类作为Action 提供的无参的Action方法(不推荐)
2.定义一个类,实现于com.opersymphony.xwork2.Action接口并覆写execute方法即可(不推介)初始化了一些方法
缺点:不支持国际化,数据校验,消息机制。
3.定义一个类,继承与com.opersymphony.xwork2.ActionSupport类(推荐)
原因是:ActionSupport类中实现的类多
真实开发中,我们却往往在提供一个BaseAction类,
--BaseAction extends ActionSupport
然后其他的Acton都继承BaseAction 就好了
多方法调用:(2.3之后的版本必须配置<allowed-methods>.../...</allowed-methods>方法名)
1.DMI动态方法调用:官方不推荐。
格式:action名!方法名
2.使用通配符的方式类配置:通配符:*
<action name="emp_*" class="com.hjming.struts.action.HelloAction" method="{1}">
{1}的意思是把地址栏访问的_后的字符串了{1},把字符串映射到通配符上
*-*多个通配符的使用第一个*为{1}第二个*为{2}
访问ServletApi三种方式
在action类中操作Servlet中相关的对象,如requrst,session,cookie等
方式一.让Action类实现感知接口。(struts2框架提供)
ServletRequrstAware: 感知HttpServletRequrst对象
ServletResponseAware:感知HttpServletResponse对象
ServletSessionAware: 感知HttpSession对象
存在问题耦合严重
问题:action中感知接口的方法是----》servletConfig拦截器(优先于action执行 在struts-default.xml中)
方式二.通过servletActionContext工具类。
通过servletActionContext类中的静态方法,得到servlet相关的API
操作简单,但是action有可能和servletAPI有耦合。因为静态方法获取的requrst使用servletrequrst接收API后就会耦合。(只要不去接受API就不会耦合,使用类去点出方法 ,可以使用)
方式三.通过Action Context工具类
Struts2将作用域对象重新使用map集合进行封装,所以现在操作作用域中的共享数据就直接操作对应的Map集合。
理解:ActionContext从字面上分析,表示Action的上下文对象。
ActionContext封装每一次请求的相关信息。ActionContext相当与请求对象:ActionContext ctx = ActionContext.getContext();(提供静态方法创建对象)
在ActionContext中把requst,sesstion,application 三大作用域作为Map对象。如何操作三大对象:因为是使用Map集合进行封装所以Map怎么操作三大对象就怎么操作。Map<String,String[]> Params = ctx.getParameters();
添加作用域直接获取需要作用域的API然后.put("","");
获取直接使用.get("");
特点:与API完全没有耦合性
//框架帮我们做看类型的转换
Action获取参数的三种方式,归功于拦截器(ParametersIntercepter):
第一种:Action本身作为Model对象,通过Setter方法封装(属性注入)
需要在Action中定义需要接受的参数属性如何进行set封装(数据多了就麻烦)
第二种:创建一个独立Model对象,页面通过ognl表达式封装(属性注入)
创建一个对象进行封装,在Action中只需要定义一个对象属性进行封装,解决了第一种Action数据臃肿,但是在请求地址栏的name中需要告诉Action给那个对象进行赋值,告诉对象属性名。
第三种:使用ModelDriven接口,对请求数据进行封装(模型驱动)
有一定的局限性,因为ModelDriven接口使用的是泛型所以只能封装一个对象
第一种适合与参数少的请款下,第二种使用与参数多的情况下
第三种适用与单个对象的情况下(一般情况下不推荐使用)
注:可根据业务需求来采用1+2或者1+3但是不推荐3
数组或者集合类型数据如何接收:
数组类型参数接收:
Action中定义一个数组的属性进行接收 ,需要写get和set方法
集合类型参数接收:
Action中定义一个集合属性进行接收,需要写get和set方法
list集合对象类型接收:
定义于上相同:但是传递参数时需要告诉Action比如集合的对一条对象
User[0].name="..."&User[0].age=10&User[1].name="..."&User[1].age=12
Map类型参数的封装:
页面中的OGNL表达式的书写
定义相同,传递的参数需要:
map['a'].name="..."a是Map的键name是Map中a键对应值的其中一个属性