■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ Struts2框架↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Struts2;
为什么要有?
在项目开发的过程中会有大量的代码出现类似,
只是作用的位置不同,从而导致出现大量冗余代码,
使得开发效率的降低,并且使得每一次在进行开发的时候
都要再次写这些重复的代码,而这些代码如果抽取
出来写成每一个通用的方法那么则可以节省每一次
开发的效率,以及不需要每一次都要进行写。
是什么?
就是一个通用方法集合在一起。
作用;
可以节省开发人员的开发效率,而且便于维护,
因为只是需要通过维护配置文件,找到对应的业务方法即可。
特点;
1.对于追求处理速度的,
那么Struts2框架处理较慢,
因为底层进行了很多的封装。
2.维护较为方便
3.使得代码页面更加整洁
思想;
Struts2核心思想;约定大于配置。。。。。
注;Struts1就是因为配置过多,也是业界不使用的原因之一。
而Struts2就是位于Struts1中找一个平衡点。。。。。。
◆◆注;配置多则代码少,
配置少则代码多。
而;约定多则代码少,
约定少则代码多。
◆◆◆◆◆注;而所有框架的基本要求都是,以◆最少的代码,做◆最多的事。
-----------------------------↓↓↓↓↓↓↓↓↓ Struts2和Strus1区别↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
区别;
1.Struts2不是基于Struts1的升级,
Struts2和Struts1是两个完全不同的框架
◆Struts2是基于webwork框架的进行研发,
并且集成了一些别的框架,如;freemarker
2.Struts1的配置较为复杂,而代码更少,封装的更彻底
3.Struts2是位于Struts1中找一个平衡点的。
4.Struts1依赖Servlet_API的
5.Struts2是不依赖Servlet_API的
--------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架设计原理↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
Struts2框架设计基本原理;
底层对所有的代码进行了封装,
而这个代码都是依赖于.xml文件进行配置的,
而这些代码,为了减少耦合度,使用了大量的中间类。
所以这也是Struts2的框架的核心思想的体现,约定大于配置
因为.xml文件的所有配置都是要按照Struts2框架的约定进行配置。
而Struts2框架主要的组件是拦截器,因为所有初始化的操作都是依赖于拦截器的。
通过配置一个核心的过滤器用于启动所有的初始化操作
--------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架开发步骤↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
开发步骤;
1.导包;
---> 最少需要导入8个必须包
1.commons-fileupload-1.2.2.jar---> 文件上传包
2.commons-io-2.0.1.jar
---> 文件上传辅助包
3.commons-lang3-3.1.jar---> Struts2框架字符包
4.freemarker-2.3.19.jar---> freemarker框架包
5.javassist-3.11.0.GA.jar---> 字节码包
6.ognl-3.0.5.jar---> ognl框架包
7.struts2-core-2.3.4.1.jar---> Struts2核心包
8.xwork-core-2.3.4.1.jar---> xwork框架包
2.配置Struts2的核心过滤器
---> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
3.自定义一个业务处理类
5.必须在src目录下创建一个struts.xml文件
6.在struts.xml文件中编写配置信息
----------------------------↓↓↓↓↓↓↓↓↓ Struts2框架基本开发代码实现↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
代码实现;
1.导包 ---> 8个必备包
2.配置配置核心过滤器
Xx
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
Xx
◆注;
1.在<url-pattern>中使用/*,则在访问的时候可以加上.action或不加都可以
2.在<url-pattern>中使用*.action,
则在访问的时候必须要加上.action
因为这是在Struts2框架中的配置文件中,默认是.action的
<url-pattern>/* 或*.action
3.自定义一个类,定义一个业务处理方法
4.在src目录下创建一个struts.xml文件
5.配置struts.xml配置文件
/index.jsp
--------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架基本执行过程 —— 1↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
执行过程;
1.服务器启动
2.加载web.xml
3.加载web.xml文件中配置的Struts2框架的核心过滤器
A_ 加载所有Struts2框架的过滤器
B_ 加载src下的struts.xml配置文件
i) 检查配置文件
C_ 执行配置文件中的业务方法
-------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架配置文件细节↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
配置文件细节;
在Struts2框架中定义了很多的约定配置,
而修改这些配置可以达到想要完成的业务,
而在修改这些配置的时候可以参考,
Struts2框架的核心包下的文件。
代码;
<!-- 引入位于Struts2框架核心包下的2.3.dtd约束文件-->
"-//Apache Software Foundation//DTDStruts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<!-- 创建在dtd约束文件中定义的根标签-->
<!-- 自定义常量配置-->
常用的struts-default常量定义文件中的常用的常量
struts.i18n.encoding === 定义编码集,默认是UTF-8,只是作用在post提交
struts.multipart.parser === 解析上传文件
struts.multipart.saveDir === 缓存文件的目录
struts.multipart.maxSize === 设置上传文件的大小,默认是2M
struts.action.entension === 设置访问的后缀,默认是action,和空格
struts.enable.dynamicMethodinvovation === 动态方法调用,默认是true,
在上线运行的时候···必须要关闭,
因为不安全。
语法;访问的路径加 !方法名
struts.ui.theme === strus页面的主体
◆◆◆◆◆注;配置常量基本都是使用<constant>标签
而这个标签的name属性是配置的常量名
value是配置的值
书写;
<constant name="default.properties文件中的常量" value="值">
-->
<!-- 常量;编码集-->
<!-- 常量;访问后缀-->
<!-- 常量;动态方法调用 语法 在访问后缀加上
!方法名 上线关闭,不安全-->
<!-- 设置上传文件的缓存目录,默认是在服务器下的缓存目录或在系统下的临时文件中-->
<!-- 设置最大的上传文件的大小 ,默认是2M-->
创建一个package,用于存放业务处理类方法,
也是避免多个action的重名和便于管理
name 是这个package的唯一标识符,是不可选的
extends 继承这个Struts2框架下的struts-default文件,
才可以使用这个默认文件的元素
namesapce 是访问这个包的域名空间,是可选的,默认是/
-->
action 是用于标识一个类的业务处理方法的
name 是用于表示这个action,
在这个包下的唯一标识符,是不可选的,
也是访问这个action的域名空间。
如果有多个name相同的action则使用后面定义的那个
class 是这个业务处理方法的类的路径,
包名+类名,是可选的,默认是ActionSupport
method 是这个业务处理方法的名,
是可选的,默认是execute()
-->
<param>这个标签类似于web.xml文件中的局部变量配置
而这个也叫做action属性的注入,
而可以通过这个值时刻修改,
当时name必须是和Action类定义的,
成员变量名一样而这个成员变量,
必须要提供一个setter方法。
-->
/xxx
result 是根据这个业务处理方法返回的结果进行操作
name 是这个业务处理方法返回的结果,
是可选的,默认是SUCCESS
type 是这个业务处理方法的类型(方式)
是可选的,默认是dispatcher(转发)
常用的类型;
stream --- 流
dispatcher --- 转发
chain --- 转发到别的Action类中
redirect --- 重定向
redirectAction --- 重定向到别的Action类中
plainText --- 以纯文本的方式写出
◆注;可以参考Struts2框架下的core核心包下
的struts-default.xml文件定义的type属性值
◆每一个type值对应一个类
内容 是这个业务处理方法返回的结果后的操作
-->
/stack.jsp
小结;
如果在<result>中需要进行的处理是页面必须要加上/
◆当分不清什么时候提供set或get方法,建议都提供get和set方法。
◆ 注意name属性等各个属性的值的大小写问题
◆◆◆◆◆特别注意name属性值在访问的时候的大小写的问题
-------------------------↓↓↓↓↓↓↓↓↓ 在MyEclipse中引入dtd约束文件提示↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
dtd约束文件提示;
1、打开MyEclipse,找到菜单栏“Window”---->“Preferences(首选项)”;
2、在左侧导航菜单栏找到“MyEclipse”---->“Files
and Editors”---->“XML”--->“XML Catalog”;
3、在右边的界面中,选择“User Specified Entries”,点击右边的“Add...”;
4、在弹出的“Add
XML Catalog Element”的对话框中点击“File System...”,
为Location输入框添加DTD文件所在路径,也可以点击“Workspace”,
为Location输入框添加DTD文件所在路径;
5、使用文本编辑器打开此DTD文件,找到相应的<!DOCTYPE ...>文档类型声明,
比如说Hibernate的配置文件:hibernate.cfg.xml所需要的DTD文件为:
hibernate-configuration-3.0.dtd
打开hibernate-configuration-3.0.dtd后,找到如下内容:
"-//Hibernate/Hibernate ConfigurationDTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
6、“Key Type:”右边的下拉框中(有三个类型:Public ID,System ID,URI),
根据hibernate-configuration-3.0.dtd中的<!DOCTYPE...>中的PUBLIC,
选择Public ID(或者直接选择“URI”也可);
7、“Key:”右边的文本框中,将hibernate-configuration-3.0.dtd中的
中的PUBLIC后的双引号内的内容复制,然后粘贴到“Key:”右边的文本框中,
◆注;COPY的内容不带双引号"";
-------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架执行过程 —— 2↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
Struts2框架执行过程;
一、项目启动
1.加载web.xml文件,创建一个Struts2框架的核心过滤类对象
2.调用核心过滤器的init()方法
A.读取default.properties
---> Struts2默认常量文件
B.读取默认的struts-default.xml ---> Struts2框架默认配置文件
C.读取默认的struts2-plugin.xml ---> Struts2框架的插入配置文件
D.读取常用的struts.xml ---> 位于src下的业务配置文件
二、发出请求
1.根据请求名称在struts.xml文件中找到的<action>标签对应的类,
说明;而是根据这个name属性值的唯一性来查找的,
因为这个name属性也是这个action类的域名空间之一。
2.如果没有匹配成功则抛出NotActionMapped的异常
说明;如果抛出这个异常说明映射有问题。
2.1 找到;
A.找到则根据这个action标签的calsss字符串,
创建一个对应的Action操作类的实例,
▲ 都会先创建对象在调用方法。
B.根据<action>标签的method属性调用对应的Action类的对应的方法
C.执行完毕操作业务方法后会返回一个视图标记的字符串
D.根据这个视图标记字符串在当前的action标签内部,
根据这个result标签的name属性值查找对应的result标签,
◆注;如果2个result标签的name一样则使用后面那个
E.根据这个<result>标签的type属性进行操作
———————=============———————=======〓〓〓Struts2框架核心功能 〓〓〓======——————————=============———————————————————————————————————
----------------------------------↓↓↓↓↓↓↓↓↓Action类三种写法↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
写法;
写法一;不继承任何的类和是实现任何的接口
class Test(){
}
弊端;
无法使用struts2框架下的一些其他功能,如表单验证等。。。。。。
写法二;实现Struts2框架定义的Action接口,并且实现这个接口的execute()方法
class Test implementsAction(){
public String execute(){
return SUCCESS;
}
}
好处;
提供了一个标准的execute()方法,
因为在struts.xml文件中的<action>,
标签中的method属性默认是execute()方法。
◆这个接口提供了常用的视图标记
弊端;
必须要实现这个接口下的所有方法。。。。。。
写法三;继承Action接口的实现类ActionSupport类
class Test extendsActionSupport{
}
好处;
这个类内部实现了Action接口,
并且重写了一个空的execute()方法,
和实现了这个接口定义的常用的视图标记。
◆推荐使用
◆如果有多个需要实现的类则使用接口。【变通】
----------------------------↓↓↓↓↓↓↓↓↓ Struts2框架接收请求参数方式↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
接收请求参数的方式;
方式一;在业务处理类中,
定义和页面的某一些需要,
◆提交的参数的name属性值同名的成员变量,
并且必须要提供对应的set的方法。
class Test extendsActionSupport{
private String xx;
public voidsetXx(String xx){
this.xx = xx;
}
}
好处;
简易,简便的
弊端;
不适合多参数提交,多参数则不便于管理等问题。
方式二;为了解决方式一的弊端,
所以使用JavaBean的方式,
定义所有需要接收的成员变量到一个JavaBean中,
◆ 和成员变量名必须要和提交的参数的name属性值同名,
并且必须要提供对应的set方法。
而在业务处理类中则只是需要将JavaBean作为成员变量,
◆ 在页面的提交参数的属性名需要使用这个JavaBean的,
◆ 成员变量名.对应的name属性名。
JavaBean;
class GetSubmitBean{
private StringuserName;
public voidsetUserName(String userName){
this.userName =userName();
}
}
业务处理类;
class Test extends ActionSupport(){
private GetSubmitBeanbean;
public voidsetBean(GetSubmitBean bean){
this.bean = bean;
}
public GetSubmitBeangetBean(){
return this.bean;
}
}
页面;◆
好处;
解决了方式一的管理等一系列的问题
弊端;
修改了原表单,破坏了原有的结构。
方式三;在业务处理类中实现ModleDriven接口,
使用这个接口下的getModle方法返回,
当前这个JavaBean的成员变量对象,
JavaBean;
class GetSubmitBean{
private StringuserName;
public voidsetUserName(String userName){
this.userName =userName();
}
}
业务处理类;
class Test extends ActionSupportimplements ModleDriven{
private GetSubmitBeanbean;
◆ public Object getModle(){
return bean;
}
public voidsetBean(GetSubmitBean bean){
this.bean = bean;
}
public GetSubmitBeangetBean(){
return this.bean;
}
}
好处;
不需要破坏原有的页面结构值,◆
◆ 并且解决了方式一和方式二的弊端
弊端;
只能接收一个表单
小结;
如果是获取值则必须要提供setXx()方法。
◆ 不知道什么时候提供get和set方法的时候,则每次提供get和set方法
------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架数据共享方式↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
数据共享方式;
方式一;使用ServletActionContext的方法获取到对应的Servlet域对象
class Share extendsActionSupport{
public String text(){
//1.
HttpServletRequest req =ServletActionContext.getRequest();
//2.通过HttpServletRequest类的方法获取到HttpSession对象
HttpSession session =req.getSession();
//3.
HttpServletContext con =ServletActionContext.getContext();
return SUCCESS;
}
}
好处;
直接获取到Servlet的域对象,简便。
◆ 便于习惯使用了Servlet对应的域对象的而言是很不错的。
弊端;
与Servlet_API的联系过于紧密,耦合性非常的高。
方式二;使用Struts2框架的ActionContext类中定义的对象 ---> 局部
class Test extendsActionSupport{
//使用这个类的静态方法获取到这个类的对象
ActionContext ac =ActionContext.getContext();
//通过这个类对应的方法获取到对应的需要进行数据共享到页面的对象
Map request = (Map)ac.get("request");
//设置这个request数据共享中的映射数据,
//和HttpServletRequest的set差不多。
request.put("r_key","r_values");
//获取到Session
Map session =ac.getSession();
//设置映射数据
session.put("s_key","s_values");
//获取到Context= Application
Map application =ac.getApplication();
//设置映射数据
application("a_key","a_values");
}
好处;
降低了和Servlet_API的耦合性
弊端;
只能在一个方法中使用则变得局限性过大。
方式三;使用Struts2框架定义的对应的接口,
---> 全局
通过定义好的对应的Map成员变量类型,
作为这个接口下的set方法的值获取到共享数据对象。
class Text extendsActionSupport implements RequestAware,SessionAware,ApplicationAware{
private Map request;
private Map session;
private Map application;
@Override
public void setApplication(Map application) {
this.application = application;
}
@Override
public void setSession(Map session) {
this.session = session;
}
@Override
public void setRequest(Map request) {
this.request = request;
}
//业务方法
public String handle(){
request.put("r_key","r_values");
session.put("s_key","s_values");
application.put("a_key","a_values");
}
}
好处;
解决了方式二的局限性的弊端,降低了耦合性。
◆建议;使用一个通用的类来获取到这些对象,使得不需要每次都要进行重写
弊端;
较为复杂
小结;
使用Struts2框架定义对应的域对象,是为了降低耦合性。
————=============——————=======〓〓〓 Struts2框架常用的业务配置处理〓〓〓========——————————=============———————————————————————————————————
--------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架文件上传↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件上传;
Struts2框架思想是约定大于配置的一个,
所有在文件上传的也是定义了约定。
约定;
1.在业务处理类中定义对应的属性接收
↓↓↓↓↓↓↓↓↓ 必须要提供set()方法↓↓↓↓↓↓↓↓↓
A.接收文件必须是File类型属性---> File
B.接收文件名必须是File类型属性名+ FileName ---> String
C.接收上传文件类型必须是File类型+ ContentType ---> String
D.使用上传文件工具类FileUtils的copyFile()方法将这个文件写出到硬盘中
◆建议;创建一个String属性,
用于在struts.xml配置文件做注入操作,用于修改保存的路径
◆◆◆◆◆注;如果是多个文件则使用··数组·或·集合··接收,
而Struts2框架底层会自动进行操作。
2.在struts.xml配置文件中进行配置
A.在配置文件中可以配置一些上传文件的常量配置
i_ struts.multipart.saveDir 配置这个上传文件的缓存目录,
默认是window系统下的temp文件夹
代码;
ii_ struts.multipart.maxSize 配置这个上传文件最大大小,默认是2M
代码;
◆◆◆◆◆注;
1.建议提供一个文件路径的注入属性
2.在配置文件中配置一个全局的<result>视图,标记是input返回值
因为Struts2框架中定义了在上传文件和下载文件的过程出错默认返回input视图标记
----------------------------↓↓↓↓↓↓↓↓↓ Struts2框架文件上传实现代码↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件上传实现代码;
class Test extends ActionSupport{
private File attach;
private String attachFileName;
private String attachContentType;
private String save;
public void setSave(String save) throwsException {
this.save = save;
}
//提供对应的set方法
public void setAttach(File attach) {
this.attach = attach;
}
public void setAttachFileName(StringattachFileName) {
this.attachFileName = attachFileName;
}
public void setAttachContentType(StringattachContentType) {
this.attachContentType = attachContentType;
}
//处理方法
public String test(){
System.out.println("文件名;" + attachFileName);
System.out.println("文件大小;" + attach.length());
System.out.println("文件类型;" + attachContentType);
System.out.println("======= " +attach);
FileUtils.copyFile(save + attachFileName);
return SUCCESS;
}
}
配置文件;
<!-- 设置文件上传缓存目录-->
<!-- 设置文件上传的最大大小-->
定义一个全局的表单提交错误,跳转到错误页面
而Struts2的视图标记如果是input那么出现错误则会自动跳转
-->
/actionerrorpage.jsp
路径注入属性
-->
c:/
/updata_one.jsp
--------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架文件下载↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件下载;
在Struts2框架中是约定大于配置,
而框架的出现就是为通过配置文件可以简化开发代码。
但是具体的实体还是需要开发人员提供的。
约定;
业务处理类;
↓↓↓↓↓↓↓↓↓ 必须要提供get()方法↓↓↓↓↓↓↓↓↓
1.提供下载的文件输入流
2.提供下载文件的其他附加属性(文件名)
3.提供一个业务处理方法
配置文件;
1.提供对应的<action>和<result>标签
2.在<result>标签中定义type的属性值为stream
3.在<result>标签中定义这个stream类型对应的Struts2框架定义的类成员变量
A.通过注入的方式给这个stream类型对应的类的属性注入值
B.而这些值则是这个业务处理类对应的get方法
----------------------------↓↓↓↓↓↓↓↓↓ Struts2框架文件下载实现代码↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件下载实现代码;
业务处理类;
class Down extends ActionSupport{
private FileInptuSteam fis;
private String name;
//提供对应的get()方法
public InputStream getFileInputStream()throws Exception{
fis = new FileInputStream(newFile("c:/1.jpg"));
return fis;
}
//提供下载的这个文件名的get方法,因为是提供给struts.xml文件使用的所以是通过get方法
public String getFileName(){
name = "1.jpg";
return name;
}
}
配置文件;
<!-- 获取到业务逻辑处理方法的返回视图标识符,并且设置这个返回标识符的类型是Stream -->
通过这个Struts2的内置的stream视图类型对应的类的属性提供文件给用户下载
而通过param标签定义下载的一些值,如下载的文件等。。。。
◆这个类在Struts2框架下的核心包中的struts-default.xml文件中可以找到
-->
<!-- contentType 下载的文件类型,一般都会设置为二进制类型,因为便于操作-->
application/octet-stream
<!-- contentDisposition 提供一个下载提示框给用户,从业务处理类中获取${fileName} -->
attachment;filename=${fileName}
<!-- inputName 提供一个文件输出流给用户下载,从业务处理类中获取-->
fileInputStream
<!-- bufferSize 定义下载缓存大小-->
512
小结;
在struts.xml配置文件中给一个业务处理类的成员变量设置值,则必须要提供set()方法,
如果是给struts.xml文件中的<param>获取到这个成员变量的值则提供get()方法
—————————————————————————————————↓↓↓↓↓↓↓↓↓ Struts2框架类型转换器↓↓↓↓↓↓↓↓↓↓↓————————————————————————————————————
类型转换器;
为什么要有?
Struts2框架底层定义了很多的功能,
在做某些操作的时候则会自动触发这些功能。
如;表单提交的时候可以,
根据业务处理类的属性,
获取到这些提交的数据。
而这个是通过底层ParemetersInterceptor参数拦截器获取的
◆因为在Struts2框架这个拦截器中定义的转换类型时单一的。
如;日期类型,有一些用户习惯使用 ( / ) 有一些习惯使用 ( - )符号分隔.....
是什么?
是Struts2框架的一个组件。
作用;
◆但是当提交表单的数据类型不符合需求的时候,
则需要对这个提交的数据类型进行扩展。
特点;
使用*.properties文件做关联
◆核心类;
继承StrutsTypeConverter抽象类,
通过重写这个类的两个转换转换方法。
------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架类型转换器分类↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
分类;
局部转换器;
只作用在当前包下的某一个Action业务处理类
而在做关联的时候,文件名为;Action类文件名+ -convertion.properties
而这个文件则是位于当前这个类的包下。
全局转换器;
作用在整个项目下
而在做关联的时候,文件名为;xwork-convertion.properties
而这个文件则是位于src包下
◆注;遵循就近原则
---------------------------↓↓↓↓↓↓↓↓↓ Struts2框架类型转换器开发步骤↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
类型转换器开发步骤;
1.自定义转换类,继承StrutsTypeConverter抽象类
2.根据具体需求分析在那个重写方法中对需要进行转换的类型扩展
3.根据需求创建一个 全局/局部 关联文件
◆ 4.根据业务处理类接收参数的方式不同,对关联文件进行配置
5.测试
-------------------------↓↓↓↓↓↓↓↓↓ Struts2框架类型转换器关联文件细节↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
关联文件细节;
当接收参数的方式不同则对配置文件的配置也不同。
方式一;
key value
属性 转换器类【类路径】
方式二;JavaBean方式
key value
JavaBean类.属性 转换器类【类路径】
◆注;必须要有一个空参构造器
方式三;ModleDriven方式
★在当前的包下创建一个【JavaBean类名 + -converconvertion.properties】文件
key value
属性 转换器类【类路径】
◆注;是一个局部绑定
---------------------------↓↓↓↓↓↓↓↓↓ Struts2框架类型转换器实现代码↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
类型转换器实现代码;日期
1.转换器类;
class TypeContertion extendsStrutsTypeConverter{
//1.需要进行转换的类型属性 -------> 单个
private SimpleDataFormat sim = newSimpleDataFormat();
//1.进行转换类型属性
-------> 多个
private SimpleDataFormat[] moreSim = newSimpleDataFormat(){
newSimpleDateFormat("yyyy/MM/dd"),
newSimpleDateFormat("yyyy-MM-dd"),
newSimpleDateFormat("yyyy#MM#dd")
};
//★★★将String类型进行转换成别的类型★★★
@Override
public Object convertFromString(Map map,String[] string, Class clazz) {
/*
* 获取到数组中的第一个字符串进行格式化,
* ◆因为参数类型拦截器对日期默认是根据浏览器的语言而定的
* 如;中国语言--- 1998-8-8
*
美国--- 08-8-1995
*/
//=================多个
//遍历所有的格式化对象
for (SimpleDateFormat format : formats) {
try {
//调用方法解析为日期类型
Date date = format.parse(string[0]);
//解析成功则返回
return date;
} catch (ParseException e) {
//如果出现类型不匹配则进行下一个
continue;
}
}
//============== 单个
// try {
//
// //将数组中的第一个字符串转换(解析)为Date类型
// Date date = format.parse(string[0]);
//
// //返回这个解析为日期的字符串
// return date;
//
// } catch (ParseException e) {
// e.printStackTrace();
// }
return null;
}
//★★★将别的类型转换成String类型★★★
@Override
public String convertToString(Map map,Object obj) {
return null;
}
}
2.定义接收参数的方式 ---> 演示方式一
3.配置关联文件
A.局部配置;
i_ 在当前的包下创建一个 业务处理类名-conversion.properties 文件
★★★如;TestConverType-conversion.properties
ii_ 配置关联文件 ---> 根据接收参数方式
key value
需要转换成员变量
业务处理类路径
★★★如;key value
time com.struts.converter.TestConverType-converter
B.全局配置;
i_ 在当前的src路径下创建一个
xwork-conversion.properties 文件
★★★如;xwork-convertion.properties
ii_ 配置关联文件 ---> 根据接收参数方式
key value
需要转换成员变量 业务处理类路径
★★★如;key value
time com.struts.converter.TestConverType-converter
———————————————————————————————————↓↓↓↓↓↓↓↓↓ Struts2框架国际化↓↓↓↓↓↓↓↓↓↓↓————————————————————————————————————
国际化;
为什么要有?
但一些业务涉及与国际相关的时候则需要进行国际化的操作。
如;时间,货币,语言等。。。。。。
是什么?
国际化是常见的业务需求之一,则这个业务的实现是在web层实现的
■ 而Struts2框架定义的国际化是通过通过配置文件的,
而且如果要获取到国际化的数据必须要继承ActionSupport类。
作用;
可以使得业务多样性,可延生性。。。。。。
特点;
底层依然是依赖翻译文件
------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架国际化开发步骤↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
国际化开发步骤;
1.拥有对应的资源包 message_语言_国家.properties
2.统一绑定资源包
2.1配置文件全局配置struts.custom.i18n.resources
3.通过方法获取到国际化内容
4.在jsp页面通过<s:text>标签获取到国际化对应的值
◆注;如果是ui标签则是使用key而这个key显示的是label
★★★细节;而在绑定的国际化资源文件中是根据用户浏览器的语言选择对应的国际化资源包
------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架国际化实现代码↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
国际化实现代码;
业务处理类;
/**
* 继承ActionSupport这个类,
* 因为只有继承这个类才可以使用这个上下文类的方法,
获取到国际化资源包的对应的值。
* @author LeviWei
*
*/
public class _01International extendsActionSupport{
//业务处理类
public String i18n(){
//使用ActionSupport类的方法获取到国际化资源文件对应的值
System.out.println(getText("login"));
System.out.println(getText("password"));
return SUCCESS;
}
}
语言文件配置;
login=登录
struts.xml文件配置;
<!-- 绑定国际化标签 -->国际化文件路径 + 国际化文件前缀
页面获取国际化数据;
<%--
Struts2框架的的UI标签使用国际化是通过key这个key就是label
--%>
<%--
使用Struts2框架的<s:text>标签获取到国际化的数据
--%>
◆◆◆◆◆注;是使用<s:text></s:text>标签的时候绝对不可以使用HTML的注释,只能使用JSP注释,否则会报错
———————————————————————————〓〓〓 Struts2框架Ognl表达式和值栈的关系 〓〓〓————————————————————————————————————————————————————
Ognl和值栈的关系;
Ognl表达式;本身也是一个框架,而Struts2框架整合了这个框架
值栈;是Struts2框架定义的数据共享的方式,
而Struts2框架定义值栈这个组件是为了,
【★】减少与Servlet_API的耦合关系。
关系;
为了减少与Servlet_API的耦合关系,
◆◆◆◆◆ 那么则需要建立一个在页面获取值栈这个组件数据数据新方式。
★★★而Ognl表达式是依赖Struts2标签库的,
★★★★★ 而获取值栈的数据也是通过Struts2标签的标签结合Ognl表达式获取。
————————————————————————————————————〓〓〓 Struts2框架Ognl表达式 〓〓〓————————————————————————————————————————————————————
Ognl表达式;
为什么要有?
Struts2框架的出现了为了简化Java开发人员的代码和提高效率,
而Struts2框架开发人员认为SUN公司提供标签库和EL表达式不够简化。
是什么?
Ognl表达式也是一个框架,而Struts2框架整合了这个Ognl表达式框架
作用;
1.获取到值栈的数据
2.创建集合
3. ......
特点;
★★ 和Struts2框架的标签是融合使用的
---------------------------↓↓↓↓↓↓↓↓↓ Struts2框架Ognl表达式使用细节↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
Ognl表达式细节;
1.当每一个标签不不支持Ognl表达式的时候,
可以使用 %{表达式} 强制这个标签使用Ognl表达式。
如;%{5>3}
2.在创建集合的时候,如果是List集合则{ }
如;{'a','b','c'}
3.在创建集合的时候,如果是Map集合则是#{ }
如;#{'a':'aa','b':'bb','c':'cc'}
建议;每次在使用Ognl表达式的时候都加上%{ },避免出错
----------------------------------↓↓↓↓↓↓↓↓↓Ognl表达式常用符号解析↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
Ognl符号解析;
1.#符号;用途一般有三种。
i_ 问非根对象属性,
例;#session.msg表达式,
由于Struts
2中值栈被视为根对象,
所以访问其他非根对象时,需要加#前缀。
实际上,#相当于ActionContext.getContext();
#session.msg表达式相当于ActionContext.getContext().getSession().getAttribute(”msg”)
ii_ 用于过滤和投影(projecting)集合,
如;persons.{?#this.age>20}。
iii_ 用来构造Map,例如示例中的#{’foo1′:’bar1′, ’foo2′:’bar2′}
2.$符号;主要有两个方面的用途。
i_ 在国际化资源文件中,引用OGNL表达式,
如;国际化资源文件中的代码:
reg.agerange=国际化资源信息:
年龄必须在${min}同${max}之间。
10
100
<message>BAction-test校验:数字必须为${min}为${max}之间!
3.%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。
如;
-----------------------------↓↓↓↓↓↓↓↓↓ Ognl表达式和EL表达式区别↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
Ognl和EL的区别;
A.构建数据;
Ognl表达式可以创建集合对象,构建数据
EL表达式不可以创建对象,不可以构建数据
B.JavaScript应用;
EL表达式可以用在···内部文件的JavaScript代码中,
不可以用在外部文件的JavaScript代码中,
因为在解析的时候,内部的JS代码也是被解析的,
而外部的JS文件是在客户端执行的,不是由服务器执行解析的。
C.标签库;
Ognl表达式需要Struts2框架的标签库
EL表达式需要JSTL标签库
D.用法区别;
Ognl表达式结合Struts2标志使用,不可以单独使用
EL表达式可以单独的在JSP页面使用
E.取值的区别;
Ognl表达式有Struts2框架约定的规则
EL表达式根据Servlet约定的规则
——————————————————————————————————〓〓〓 Struts2框架Jsp页面标签 〓〓〓————————————————————————————————————————————————————
页面标签;
为什么要有?
Struts2框架的出现是,
为了简化Java程序开发人员的代码,
提高Java程序开发的效率,
而Struts2框架认为SUN公司定义的,
标签库不够简化开发人员的开发代码,
和提高开发人员的效率。
所以Struts2框架自定义了一套标签库。
是什么?
是Struts2框架定义的一套标签库。
作用;
简化开发人员的代码,提高开发人员的开发效率。
特点;
融合了Ognl表达式
-----------------------------↓↓↓↓↓↓↓↓↓ Struts2框架Jsp页面标签分类↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
JSP页面标签分类;
逻辑标签;
判断,循环等等。。。。。。
常用的逻辑标签;
<s:set></s:set> ---> 添加数据到映射栈
<s:property></s:property> ---> 获取数据
<s:debug></s:debug> ---> 查看整个值栈信息
<s:if></s:if><s:elseif></s:elseif>......<s:else></s:else>
---> 条件判断
<s:iterator></s:iterator>
---> 循环
UI标签;
用于简化HTML表单的使用
常用的UI标签;
<s:form></s:form> ---> 表单
<s:textfield></s:textfiel> ---> 文本输入框标签
<s:password></s:password> ---> 密码输入框标签
<s:submit></s:submit> ---> 表单提交标签
。。。。。。
<s:checkboxlist></s:checkboxlist> 多个多选框标签
<s:select></s:select> 多个单选框标签
--------------------------↓↓↓↓↓↓↓↓↓ Struts2框架Jsp页面标签代码实现↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
标签代码实现;
逻辑标签;
添加数据到映射栈中
默认是在ContextMap下的
name 是设置的名
value 是这种的值,必须有有引号,不然默认是在映射栈中查找这个元素
scope 是设置位于的映射栈位置,默认是ContextMap
-->
获取到值栈中的某一个映射类的数据
value 是获取的数据的ognl表达式
-->
进行逻辑判断,根据所需要的数据进行判断,没有empty
test 是进行判断的语句,可以是ognl 表达式
根据所需的要求进行标签的选择在进行判断
-->
判断语句1
判断语句2
判断语句3
遍历;
这个变量是和C的变量类似只不过名不一样了
而是ognl获取到对象栈的
-->
编号;
书名;
价格;
查看整个值栈的数据
-->
UI标签;
常用的表单标签;属性基本都是和html标签的属性类似,因为都是对这个html标签进行一个封装而已
默认是使用xhtml模板的可以通过设置属性,
每一个Struts2框架的ui标签都有theme属性,值为simple则是普通表单的格式
如果要···全局修改则使用struts.ui.theme 设置sturs.xml配置文件
◆在某一些属性中是不支持ognl表达式的,如textfield标签的value属性,
那么则可以使用%{}强制ognl表达式编码
-->
form 表单的 action是自动加上了当前项目路径的则只需要指定当前项目路径的要访问的具体
-->
label属性是设置这个表达的外部提示内容
-->
<!-- 输入框标签-->
<s:textfield name="userName"
value="zhangsan" label="账号">
<!-- 密码框标签-->
<s:password nmae="pwd"
label="密码">
<s:submit value="注册">
使用常用的多个表单设置标签
在ognl表达式中可以使用{'x','x'},创建一个List集合
必须要有引号因为那么才是符合ognl表达式的语法的
如果是使用{'x','x'}创建一个List集合的话,那么则会使得name和内容一样,
如果要name和内容不一样则使用Map集合{'x':'a','f':'g'}
而如果在value属性的值设置为某一个这个value对应的值,
则可以选中当前这个value值,这个value只能是数字,
所以一般都是应用在Map集合中的
-->
—————————————————————————————————————〓〓〓 Struts2框架值栈 〓〓〓————————————————————————————————————————————————————
值栈;
为什么要有?
Struts2框架的出现是为了解决开发人员在web层开发的效率和简化代码的问题。
而Struts2框架是一个自成体系,为了减少对Servlet_API的耦合关系问题,
和解决Struts1框架与Servlet_API耦合过于紧密的关系则自定义了,
如何将数据传递到页面,如何从页面获取数据等一系列的功能。
虽然这些功能的底层还是使用Servlet_API,
但是在经过代码的处理后,减少了对Servlet_API的依赖。
同时也在Servlet_API的基础上对这些代码进行了功能性的增强。
是什么?
是Struts2框架的一个重要的组件,◆是Struts2框架存储数据的核心。
作用;
可以用于保存数据,传递···动态···数据到页面。
特点;
通过Ognl表达式获取数据,
而Ognl表达式依赖Struts2框架的标签。
接口;
ValueStack
实现类;
OgnlValueStack
--------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架值栈结构↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
值栈结构;
分为两个数据结构;
Object Stack 对象栈 ---> ArrayList + 栈结构 --- FIFO 先进先出
作用;主要用于保存Action对象,国际化对象,类型转换对象等。。。。。
Context Stack 映射栈---> HashMap
作用;主要用于保存映射数据
映射栈和Servlet对应的对象;
Servlet ContextStack
request RequestMap
session SessionMap
application ApplicationMap
映射栈对象和页面取值对应的对象;
页面ContextStack
request RequestMap
session SessionMap
application ApplicationMap
parameters
ParamtersMap ---> 自动获取表单提交的数据
attr
AttributeMap ---> 获取到R/S/A三个对象
-------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架值栈存储数据↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
值栈存储数据;
ObjectStack;对象栈
//通过ActionContext上下文类方法获取到这个ActionContext对象,因为这个类只有一个参数的构造方法
ActionContext ac =ActionContext.getContext();
/*
* 对象栈的底层依然是如同Servlet域的,
* 但是不是使用Servlet中的域
* 而是Stuts框架定义好的,必须要和Ognl表达式一起使用
*
*/
//通过这个ActionContext上下文类方法方法获取到对象栈的对象
ValueStack vs =ac.getValueStack();
//添加数据到这个对象栈的中
vs.push(book);
ContextStack;映射栈
//通过ActionContext上下文类方法获取到这个ActionContext对象,因为这个类只有一个参数的构造方法
ActionContext ac =ActionContext.getContext();
/*
* ContextMap映射栈底层还是使用Servlet_API的域对象的,
* 但是在Strut2框架中基本都是配合ognl一起使用,因为ognl比EL强大
*
* 而映射栈栈中的基本使用的栈对象,
* 都是可以通过ActionContext上下文类获取到,
* 因为在启动的时候就创建了ContextMap对象,
* 而这个对象下的映射类是通过ActionContext的方法获取到对应的引用
*/
//获取到映射栈中的requestMap映射类---> requestMap
Map requestMap = (Map)ac.get("request");
//添加数据到这个映射类的栈中
requestMap.put("r_book", book);
//获取到映射栈的sessionMap映射类---> SessionMap
Map sessionMap = ac.getSession();
//添加数据到这个映射类的栈中
sessionMap.put("s_book",book);
//获取到映射栈中的applicationMap映射类---> applicationMap
Map applicationMap = ac.getApplication();
//添加数据到这个映射类的栈中
applicationMap.put("a_book",book);
———————————————————————————〓〓〓 Struts2框架Ognl表达式和值栈的关系 〓〓〓————————————————————————————————————————————————————
Ognl和值栈的关系;
Ognl表达式;本身也是一个框架,而Struts2框架整合了这个框架
值栈;是Struts2框架定义的数据共享的方式,
而Struts2框架定义值栈这个组件是为了,
【★】减少与Servlet_API的耦合关系。
关系;
为了减少与Servlet_API的耦合关系,
◆◆◆◆◆ 那么则需要建立一个在页面获取值栈这个组件数据数据新方式。
★★★而Ognl表达式是依赖Struts2标签库的,
★★★★★ 而获取值栈的数据也是通过Struts2标签的标签结合Ognl表达式获取。
----------------------------↓↓↓↓↓↓↓↓↓ Struts2框架Jsp页面获取值栈数据↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
JSP页面获取值栈数据;
ObjectStack;对象栈
<!-- 通过Struts2框架定义的标签加上Ognl表达式获取到对应的值栈中的数据-->
获取到ObjectValue对象栈的数据
对应的ognl语法;
=== 不需要带#
[下脚标].属性 获取到对应的栈的数据
◆注;在使用[下脚标]是获取到当前这个下脚标开始到最后一个下脚标位置的所有数据
规则;
不需要带#号
从当前的指定的第一个下脚标元素开始查找,直到最后一个元素为止,
-->
OS
OS
ContextMap;映射栈
获取到ContextMap映射栈的数据
对应的ognl语法;
=== 必须要带#
语法一;对应的映射栈.映射栈的数据名key
语法二;对应的映射栈['映射栈的数据名key']
规则;
如果是使用语法二,则必须要加上引号,
如果没有加上则会到当前的映射栈中找这个值,
加上了才是符合ognl语法
结;如果某一个语法是ognl表达式则必须要加上引号
而有一个数据的属性是不认ognl表达式的,
则使用%{ognl表达式}声明强制为ognl表达式
-->
<!-- 获取到requestMap映射栈的数据-->
R
<!-- 语法二;获取到sesionMap映射栈的数据-->
S
<!-- 获取到application映射栈的数据-->
AP
语法二;获取到Parameters映射栈数据
只有表单数据提交会自动使用Paramters栈接收
-->
P
获取到attr映射栈数据
attr 映射栈是用于获取RSA的三个映射栈的对象
-->
AT
—————————————————————————————————〓〓〓 Struts2框架表单数据校验 〓〓〓————————————————————————————————————————————————————
表单验证;
为什么要有?
因为在用户客户端进行验证是非常不安全的,
因为源代码等都是体现给用户的。
所以需要在后台再次进行验证,否则会非常不安全。
是什么?
是Struts2框架定义的一个功能组件。
作用;
可以对表单提交的数据进行再次验证。
特点;
依然是使用逻辑代码进行验证
------------------------------↓↓↓↓↓↓↓↓↓ Struts2框架表单数据校验分类↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
表单验证的分类;
1.代码验证;
A.代码局部验证;
只需要把这个validate方法后,
加上业务逻辑处理方法的方法名,
如;validateTest(),会在执行这个类的业务逻辑方法之前执行
B.代码全局验证;
必须要实现ActionSupport方法,
因为表单验证是依赖Validataeble接口,
而类是实现了这个接口,也实现了validate方法,
而只要在这个方法中写验证逻辑代码。
因为这个方法会在执行这个类的业务逻辑方法之前执行。
◆◆代码验证细节;必须要继承ActionSupport这个类,
因为这个类实现了Validateble接口,
而这个接口的validate方法会在执行业务,
处理方法之前执行validate方法内部的逻辑代码验证。
使用addFieldError这个方法如果出现不符合业务逻辑验证,
则会返回一个input是视图标签。
而在页面则使用<s:fieldError>方法返回一个标签
2.配置文件验证;
A.配置文件局部验证;
在当前业务处理类下创建文件名为;
★ Action类-<action>访问路径-validation.xml
B.配置文件全局验证;
在当前业务处理类下创建文件名为;
★ Action类-validation.xml
--------------------------↓↓↓↓↓↓↓↓↓ Struts2框架表单数据校验实现代码↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
表单校验实现代码;
1.代码验证;
A.代码局部验证;
/**
* 局部;
* 在validate方法名后加上要进行验证的业务方法名,
书写格式必须要按照java的书写规则
*/
public void validateProving(){
if(user != null){
//逻辑验证代码
if(user.getUserName().equals("")|| user.getUserName() == null){
//使用addFieldError方法抛出一个异常
addFieldError("error",getText("userName"));
}elseif(user.getEmail().equals("") || user.getEmail() == null){
addFieldError("error",getText("email"));
}
}
}
B.代码全局验证;
/**
* 全局;
* 重写validate方法,在validate方法中写业务处理验证逻辑代码
*/
@Override
public void validate() {
if(user != null){
//逻辑验证代码
if(user.getUserName().equals("")|| user.getUserName() == null){
//使用addFieldError方法抛出一个异常
addFieldError("error",getText("userName"));
}elseif(user.getEmail().equals("") || user.getEmail() == null){
addFieldError("error",getText("email"));
}
}
}
2.配置文件验证;
A.配置文件局部验证;
步骤;
1.在当前业务处理类下创建文件名为;
★ Action类-<action>访问路径-validation.xml
2.配置业务处理文件
引入dtd约束文件;
位于xwork_jar包中的xwork-validator-1.0.3.dtd约束文件
-->
"-//Apache Struts//XWork Validator1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<!-- 根据约束文件创建对应的根标签-->
filed对需要进行验证的属性进行进行验证
name 是需要进行验证的属性
-->
field-validator 是需要进行验证的规则
在xwork_jar包下的default文件中可以查看
requiredstring 必须要是一个有值的string字符串
regex自己写正则代码
-->
message 验证失败后需要提示的信息
key 是使用国际化文件中的key对应的value显示提示的信息
-->
B.配置文件全局验证;
只是需要在当前业务处理类下创建文件名为;
★ Action类-validation.xml
——————————————————————————————————〓〓〓 Struts2框架具体执行过程 〓〓〓————————————————————————————————————————————————————
具体执行过程;
1.服务器启动
A_ 加载web.xml文件
B_ 加载web.xml文件中配置的Struts2框架的核心过滤器
3.核心过滤器则加载src目录下的struts.xml文件
A_ 会加载Struts2框架下的启动配置文件和类等。。。。。。
B_ 会读取default.properties文件 ---> 默认常量文件
C_ 会读取struts-default文件 ---> 默认配置文件
D_ 会读取struts--plugin.xml文件 ---> 默认插入文件
E_ 加载src目录下的struts.xml文件
i) 会查看当前的src目录下是否有全局的转换器关联配置文件,有则加载
ii) 加载表单验证配置文件
iii) 加载Struts2框架定义的拦截器
iiii) 加载自定义拦截器
iiiii)
4.访问这个业务逻辑处理类,使用这个类中的业务处理方法
A_ 会先查找这个类的包下的类转换器所对应的关联文件
B_ 会创建OgnlValueStack值栈接口的实现类,
并且还会一起创建ObjectStack和ContextMap
C_ 会将当前的业务处理类命名为action存放到ContextMap值栈中
D_ 如果有表单验证则先进入validate的方法无论是局部还是全局的
5.
----------------------------------↓↓↓↓↓↓↓↓↓Struts2框架的铁律↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
铁律;
配置文件中;
1.<param>标签则必须要提供set方法,用于注入
2.多个<package>标签中的name属性值命名则报错
3.多个<action>标签中的name属性值同名则使用后定义的
4.多个<result>标签中的name属性值同名则使用后定义的,并且是就近原则
5.通过struts.xml配置文件给一个业务处理类的成员变量设置值,则必须要提供set()方法,
6.在struts.xml文件中获取到这个成员变量的值则提供get()方法