博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
struts2学习笔记
阅读量:6533 次
发布时间:2019-06-24

本文共 12043 字,大约阅读时间需要 40 分钟。

hot3.png

 

 

1.系统开发流程分层

 

 

231751_rk94_2897732.png

2.struts2属于Mvc层

Struts2的下载地址

目录结构:

234030_RL9j_2897732.png

3.struts2的例子

(1)解压struts2-blank.war包

(2)创建web项目;

(3)导入必要的jar包;

struts2-core-2.3.32.jar             Struts2的核心包

xwork-core-2.3.32.jar             WebWork的核心包

ognl-3.0.19.jar                      对象图导航语言(Object Graph Navigation Language)Struts2                                               通过其读写对象属性

freemarker-2.3.22.jar            Struts2的UI标签的模板使用freeMark编写

commons-logging-1.1.3.jar     日志包

commons-fileupload-1.3.2.jar    文件上传组件

commons-io-2.2.jar               传文件依赖的jar包

commons-lang3-3.2.jar          对java.lang包的增强

javassist-3.11.0.GA.jar            分析,编辑和创建Java字节码的类库

(4)编写jsp页面;

(5)编写action服务器端处理逻辑;

Action就是处理request请求的动作类,类似于servlet

(6)进行框架配置web.xml,struts.xml

struts.xml配置

1)在src文件下创建struts.xml文件,从APP例子中直接复制struts.xml的内容,然后删除<struts>标签里的内容,作为struts.xml的空文件

091236_MmS1_2897732.png

2)配置xml

/success.jsp

web.xml配置

直接拷贝App例子中的web.xml文件,然后<web-app>标签里面只留<filter>和<filter-mapping>标签

struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*

(7)测试;

 

4.struts的运行流程

141646_YX4g_2897732.png

1.启动服务(tomcat),加载web.xml,实例化StrutsPrepareAndExecuteFilter过滤器

2.在实例化StrutsPrepareAndExecuteFilter过滤器时会执行其中的init()方法,加载struts.xml文件

3.浏览器发起请求,会被StrutsPrepareAndExecuteFilter过滤器拦截到,根据请求的url(hello),找到相应的Action类,并且创建Action对象,执行相应的hello方法。

4.返回视图success.jsp  

 

5.struts2的配置文件

配置文件名称 位置 存储的内容 说明
default.properties struts2-core-2.3.32.jar/org/apache/struts2/default.properties 通过属性的形式来配置struts2的参数 不能直接修改
struts-default.xml struts2-core-2.3.32/struts-default.xml struts2的核心配置文件 不能直接修改
struts-plugin.xml ****-plugin.jar 插件相关配置 不能直接修改
struts.xml 放在classpath 应用配置文件 开发人员使用,可以修改
struts.properties 放在classpath 应用配置文件(较少使用,不推荐) 开发人员使用,可以修改

以上配置文件,服务器启动时会被加载,加载次序从上到下加载(启动服务-->过滤器StrutsPrepareAndExecuteFilter-->过滤器的init方法加载配置文件),按着配置文件的加载顺序,后加载的文件会把前面文件相同的配置的值覆盖

(1)default.properties

参数名称 参数默认值 说明
struts.i18n.encoding UTF-8 框架使用的编码
struts.action.extension action,, 请求的后缀名
struts.serve.static.browserCache true 是否开启浏览器的静态缓存
struts.configuration.xml.reload false 每当struts.xml被修改时是否热部署
struts.devMode false 是否是开发者模式(包含上一属性)

通过<constant>标签配置来间接修改default.properties的属性,name和参数名称相同,value设置属性值

例如:172056_ME07_2897732.png

(2)struts-default.xml

该文件是struts的核心文件,里面提供了结果的返回类型和拦截器以及业务bean

结果的返回类型

174508_BPZO_2897732.png

拦截器

174617_jvAb_2897732.png

(3)struts.xml

开发人员编写的文件

包:package根据项目模块来划分的一个单元,一般在项目开发中,一个模块一个package

属性

name:包的名称,必须属性;

extends:包的继承,默认情况下我们必须继承struts-default,否则无法使用struts框架;

abstract:抽象包,不能包含action,其他的都可以有;

namespace:包的命名空间,值必须为“/***”格式,namespace用于请求访问某一个包的指定路径,目的区分不同的包的相同的action

动作:action每次请求所访问的方法

属性

name : 必须要有,访问方法是根据name来访问,http://localhost:8080/struts2_01/hello.action,后缀无需指定

class : 要访问的方法所在类

method : 方法名

结果:result要跳转的视图

属性

name:result的名称,是唯一的,返回哪一个视图是由action的返回值决定的,action返回值和result的name属性做匹配传,从而返回相应的视图

type : 跳转视图的方式,默认跳转方式是请求转发,地址栏没变

 

6.struts2的动作类(Action)

1)动作类的创建方式:

(1)使用普通方式JavaBean作为动作类,不需要继承任何父类,不需要实现任何接口

.方法一定是公用的(public)

.返回值是字符串来决定跳转到哪个视图

.不需要参数

.方法名自定义,如果不自定义,默认访问execute

 

(2)创建动作类,实现action接口

 接口:com.opensymphony.xwork2.Action

提供的一些常量

常量 说明
SUCCESS success 返回成功页面
NONE none 不返回任何页面
ERROR error 返回错误页面
INPUT input 当提交表单发生错误时,就返回提交表单页面
LOGIN login 返回登录页面

(3)*创建动作类,继承父类(推荐使用)

父类:com.opensymphony.xwork2.ActionSupport

2)Action动作类的生命周期

创建:Action动作类每次请求的时候都会创建一个实例对象

销毁:当Action动作类的请求响应完后就消失了

跟JavaWeb中HttpServletRequest的生命周期是一样的,struts2是多例的,线程安全的

3)Action动作类的访问

通配符

原则:约定优于配置

在action中每个方法都要有一定的规则,eg.都以User结尾

223938_C6oo_2897732.png

225330_uHEQ_2897732.png

*是请求是输入的

225910_Pszi_2897732.png

注意:一个包里面只能有一个通配符Action

 

动态方法调用

首先打开动态方法的开关

我们的action动作类无需指定方法的method属性了,而是直接在url上指定

语法:!方法名[.后缀名]

eg.125007_AAH2_2897732.png

4).结果视图的配置

/success.jsp

result : 要返回的视图

属性

name:action动作类要返回的值,如果的action动作类的返回值与result的name值匹配,则进行相应的跳转

type:跳转方式

type的常用值有:

dispatcher : 请求转发,地址栏不发生变化,相当于JavaWeb中的forward,当我们没有指定type的类型时,默认值是dispatcher

redirect:页面重定向,地址栏发生变化

chain:请求转发到一个action动作类,地址栏不发生变化(我测试的时候地址栏发生了变化,暂时不明白为什么)

redirectAction:重定向到一个action动作类,地址栏发生变化

同包的重定向:

132552_AEFE_2897732.png

不同包的重定向:result需要通过param来指定包的namespace和action的name

135029_k7Ra_2897732.png

stream:文件的上传和下载

5).局部结果视图和全局结果视图

在一个action中配置的result是局部结果视图,外部的action是不能使用这个result的

包级别的全局                                                                                                                                     (包内的全局结果视图对包内的每一个action动作类都有效)

/error.jsp
hello2
/success2.jsp

全局的结果视图                                                                                                                           (整个系统的全局结果视图通过继承的方式来实现

/error.jsp
/success2.jsp

 

7.struts动作类获取ServletAPI

(1).使用ServletActionContext获得ServletAPI

public String hello(){        	/*获得page域对象,获取不到(很少使用)*/        	PageContext pageContext=ServletActionContext.getPageContext();        	/*获取request*/        	HttpServletRequest request=ServletActionContext.getRequest();        	/*获取response*/        	HttpServletResponse response=ServletActionContext.getResponse();        	/*获取session*/        	HttpSession session=request.getSession();        	/*获取application(请求)*/        	ServletContext context=ServletActionContext.getServletContext();        	System.out.println(pageContext);        	System.out.println(request);        	System.out.println(response);        	System.out.println(session);        	System.out.println(context);        	return "success";        }

(2).通过实现接口的方式来获取ServletAPI

接口:

org.apache.struts2.interceptor.ServletRequestAware;

org.apache.struts2.interceptor.ServletResponseAware;
org.apache.struts2.util.ServletContextAware;

public class HelloAction2 implements ServletRequestAware,ServletResponseAware,ServletContextAware{	   HttpServletRequest request;	   HttpServletResponse response;	   ServletContext context;	        public String hello(){        	System.out.println(request);        	System.out.println(response);        	System.out.println(request.getSession());        	System.out.println(context);        	return "success";        }		@Override		public void setServletRequest(HttpServletRequest request) {			this.request=request;		}		@Override		public void setServletResponse(HttpServletResponse response) {			this.response=response;		}		@Override		public void setServletContext(ServletContext context) {			this.context=context;		}}

8.参数的封装

(1)静态封装

在运行器不发生变化的数据,或者一些配置相关的数据可以做静态封装

Action动作类                                                                                                                                     (用于接受静态的参数,必须提供set和get方法)

public class HelloAction {	private String name = "zb";	private String nn;	public String hello() {		System.out.println(name);		System.out.println(nn);		return "success";	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public String getNn() {		return nn;	}	public void setNn(String nn) {		this.nn = nn;	}}

struts.xml配置                                                                                                                                   (<param>的name在action中必须有相应的属性,并且必须提供set和get方法,否则无法注入)

dzb
NN
/success.jsp

(2)动态参数的封装

系统运行期间用户提交表单,Ajax请求,url访问。

1)动作类充当模型对象

动作类和模型合为一体,可以在动作类定义要接收的属性的值,对每个属性必须要提供set和get方法,动作类model属性一定要和表单中的name一致,否则无法注入。

jsp页面:

姓名
年龄
性别

动作类model;

public class HelloAction2 {	private String name;	private int age;	private String sex;	public String hello() {		System.out.println(name);		System.out.println(age);		System.out.println(sex);		return "success";	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	public String getSex() {		return sex;	}	public void setSex(String sex) {		this.sex = sex;	}}

 

2)动作类和模型对象分离封装参数(推荐使用)

动作充当模型对象,动作类既是C层又是M层,可读性差,重用性差,很难维护,不推荐使用第一种方式。 这种方式接受参数对提交的表单中的name有要求,name值需要使用Action动作类的Model属性的名字加上点再加上要接收的属性名,如person.name;

jsp页面:

姓名
年龄
性别

model类:

public class Person {	private String name;	private int age;	private String sex;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	public String getSex() {		return sex;	}	public void setSex(String sex) {		this.sex = sex;	}	@Override	public String toString() {		System.out.println(name);		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";	}}

Action动作类:

public class HelloAction3 {	private Person person;	public String hello() {		System.out.println(person);		return "success";	}	public Person getPerson() {		return person;	}	public void setPerson(Person person) {		this.person = person;	}}

 

3)模型驱动方式封装参数(推荐使用)

第二种方式对页面上的文本域name的属性值有要求,必须要用model属性加上点再加上接受属性的名称,这样的话页面和Action动作类有侵入性(耦合性),模型驱动方式解决了这个问题,我们需要实现一个ModelDriven接口,使用接口中的getModel方法指定要接受的Model的类型,并且Action动作类中的model对象必须手动创建,否则无法注入属性

jsp页面:

姓名
年龄
性别

Model类跟上一种方式的一样:

public class Person {	private String name;	private int age;	private String sex;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	public String getSex() {		return sex;	}	public void setSex(String sex) {		this.sex = sex;	}	@Override	public String toString() {		System.out.println(name);		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";	}}

Action动作类:

public class HelloAction4 implements ModelDriven
{ private Person person = new Person(); public String hello() { System.out.println(person); return "success"; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } @Override public Person getModel() { // TODO Auto-generated method stub return person; }}

 

9.类型转换

(1)类型转换认识

页面所提交过来的数据都是字符串类型的数据,而model里面的数据并不都是字符串数据,有各种各样的类型,我们使用servlet接收数据时都是自己手动转换的,而struts2可以为我们自动转换,转换的前提是前端页面提交过来的字符串数据可以和model中相应的数据类型可以转换。

提交表单时:字符串类型 ----> 其他数据类型

展示页面时:其他数据类型 ---> 字符串类型

表单提交数据时,数据的转换虽然struts2做了大多数,但是时间类型往往需要我们根据实际情况手动做相应的转换。

(2)自定义类型转换

             220958_2snu_2897732.png

日期转换:

默认情况下,struts2解析的时间的格式是“yyyy-MM-dd”

第一步:通过自定义类型转换器继承StrutsTypeConverter做日期转换器

public class DateConverter extends StrutsTypeConverter {	@Override	public Object convertFromString(Map context, String[] values, Class toClass) {		Date date = null;		if (values != null && values.length > 0) {			if (toClass == Date.class) {				try {					date = new SimpleDateFormat("yyyy/MM/dd").parse(values[0]);				} catch (ParseException e) {					// TODO Auto-generated catch block					e.printStackTrace();					throw new RuntimeException();				}			}		}		return date;	}	@Override	public String convertToString(Map context, Object o) {		String dateStr = null;		if (o != null && o.getClass() == Date.class) {			dateStr = new SimpleDateFormat("yyyy/MM/dd").format((Date) o);		}		return dateStr;	}}

第二步:注册日期类型转换器

局部注册:

  在要转换的model类的同级包下创建一个属性文件,                                                                           命名要求:model类名-conversion.properties                                                                                 在文件的内部,key是要转换的属性名,value是转换器的全路径

164710_RLtd_2897732.png

 

全局注册:

如果有很多的Model类都有时间类型,那么使用局部注册就需要创建很多注册文件,这样不合理,这种情况就需要全局注册

170245_y1nv_2897732.png

(3)获取页面的错误提示信息:

在jsp页面添加

<%@ taglib uri="/struts-tags" prefix="s"%>

然后用

输出错误

230447_fU0U_2897732.png

230843_baXv_2897732.png

230218_An9B_2897732.png

230941_GIbM_2897732.png

把错误信息转换成中文:

第一步:在Action的同级包下创建一个属性文件,规则:和Action类同名.properties

第二步:Key : invalid.fieldvalue.[要转换的表单中文本域的name],value是中文的提示信息,中文在properties文件中以Unicode编码的形式存在

           232233_FCdL_2897732.png

 

10.struts2数据校验

验证的方式有两种

客服端校验:使用js结合正则表达式来校验,不和服务器打交道,开发简单,安全性差,

服务端校验:请求服务器,开发量比较大,安全性好,需要和数据库交互必须使用服务端校验。

实际开发中,客服端校验较多,最好是客服端和服务端都校验。

strusts2的校验属于服务器端校验。

1.struts2编程式校验

编程式校验,重写父类(ActionSupport)的validate方法,在这个方法中,对每一个字段做校验,如果参数不符合正则表达式,我们可以添加提示信息,由addFieldError方法来向页面输出提示信息。但是校验的前提是提交过来的参数是能互相转换的,如果转换不了的话会由param,modelDriven拦截器来负责。

/**	 * validate在封装参数之前做验证,如果不通过就跳转到表单页面	 */	@Override	public void validate() {		if (!person.getName().matches("[a-zA-Z]{3,8}")) {		/*	添加提示信息,第一个参数是表单中文本域的name,第二个参数是提示信息*/		  addFieldError("name","姓名只能是3到8位大小写字母!");			}		if (!(person.getAge()+"").matches("\\d{1,3}")) {			/*	添加提示信息,第一个参数是表单中文本域的name,第二个参数是提示信息*/			  addFieldError("age","年龄只能是1到3位数字!");			}	}

2.struts2声明式校验

转载于:https://my.oschina.net/ThreeTiger/blog/1457255

你可能感兴趣的文章
【Matplotlib】 标注一些点
查看>>
[AX]乐观并发控制Optimistic Concurrency Control
查看>>
自定义类加载器
查看>>
MySQL数据库事务各隔离级别加锁情况--Repeatable Read && MVCC(转)
查看>>
C++构造函数例程
查看>>
把某一列值转换为逗号分隔字符串
查看>>
DLL,DML,DCL,TCL in Oracle
查看>>
iOS中--NSArray调用方法详解 (李洪强)
查看>>
MySQL在导入的时候遇到的错误
查看>>
LINUX 常用命令整理
查看>>
德国禁止Facebook利用WhatsApp用户信息:没法律基础
查看>>
“灾备全生态”全揭秘
查看>>
CSS盒子模型
查看>>
Zeppelin Prefix not found.
查看>>
ubuntu中eclipse安装svn插件问题
查看>>
linux 的网络设置
查看>>
首届“欧亚杯”象翻棋全国团体邀请赛圆满收评!
查看>>
编译tomcat
查看>>
最简单 iText 的 PDF 生成方案(含中文解决方案)HTML 转为 PDF
查看>>
MySql中is NULL、ISNULL()和IFNULL()运行速度的比较
查看>>