@常用的常量
struts.i18n.encoding :应用中使用的编码
struts.objectFactory.spring.autoWire:和spring框架整合有关
struts.multipart.parser:指定文件上传用的组件
struts.multipart.maxSize:文件上传总文件大小限制2M
struts.enable.DynamicMethodInvocation:是否允许动态方法调用
struts.devMode:是否是开发模式
struts.ui.theme:页面展示用的主题
@xml配置文件的主要元素
1:package元素
1:作用:在struts2的配置文件中引用了面向对象思想,使用了分包管理
易于管理动作类,便于模块式开发动作类
2:属性:name:包的名称,必须唯一
extends:一般情况下需要继承struts-default包,如果不继承的话
将无法使用struts2提供的核心功能
struts-default.xml:中定义着struts-default这个包
abstract:把包声明为抽象包,抽象包就是用来被继承的,只要没有
<action>
元素的包,就可以声明为抽象包
namespace:名称空间 名称空间+动作名称=访问路径2:action元素
1:作用:配置动作用的
2:属性:name:动作名称
class:动作类全名,默认的动作类是:com.opensymphony.xwork2.
ActionSupport,实在struts-default.xml中定义的method:动作类中的方法名称,默认是public String execute(){} 要求是: 1:public的:2:返回值必须是String 3:没有参数
3:动作类
方式1:动作类就是一个POJO(Plain Old Java Object 原始的java对象),
非常简单的Javabean =》public class HelloAction{}
方式二:动作类实现com.opensymphony.xwork2.Action接口
常量:给动作方法返回值用的,用常量可以使你的应用规范和统一
SUCCESS :动作执行成功
ERROR:动作执行失败
INPUT:回显
LOGIN:一般转向登录页面
NONE:不转向任何页面
方式三:动作类继承com.opensymphony.xwork2.ActionSupport
public class HelloAction extends ActionSupport{}4:动作的访问
1,使用通配符
<action name="*" class="com.shikun.action.UserAction" method="{1}>
` <result `name="success">/{1}.jsp` </result> `
` </action>`
升级版
<action name="*_*" class="com.shikun.action.*Action" method="{1}{2}>
<result name="success>/{1}{2}`</result>`
`</action>`
优先级:绝对匹配优先,按照在配置文件中的先后顺序进行匹配的
2:动态方法调用
`<constant`name="struts.enable.DynamicMethodInvocation" value="true">`</constant>`
@结果类型视图
1:result元素
作用:为动作执行结果视图
属性:name:逻辑视图的名称,对应着动作方法的返回值,默认是success
type:结果类型,指的就是用什么方法转到定义的页面,默认是dispatcher2:result元素中type的取值
:type属性的取值在struts-default.xml中定义的
常用的结果类型介绍:
dispatcher:(默认值)使用请求转发,转向一个页面
redirect:使用重定向,转向一个页面
redirectAction:使用的是重定向,
1:重定向到另一个相同名称空间的动作
2:重定向到不同名称空间的工作
<result
name=”success” type=”redirectAction”>
<param
name=”namespace”>/n2</param>
<param
name=”actionName”>action2</param>
</result>
chain:使用的是请求转发
1:转发到另一个相同名称空间的动作
2:请求转发到不同民称空间的动作
<result
name=”success” type=”chain”>
<param
name=”namespace”>/n2</param>
<param
name=”actionName”>action2</param>
</result>
3:result元素中param子元素
在转发或者重定向到不同包下的动作时,都用到了result元素的子元素param
param元素的作用:依赖注入(Dependence Injection)思想,param元素就是将配置
的参数,注入到该类中,调用的是对应类的setter方法进行注入的4:自定义结果类型
结果类型都实现了com.opensymphony.xwork2.Result接口或者继承自该接口的实现
类org.apache.struts2.dispatcher.StrursResultSupport,这些类都有一个
doExecute方法,用于结果视图
CAPTCHA(Completely Automated Public Turing Test to Tell Computers and
Humans Apart 全自动区分计算机和人类的图灵测试)->验证码
public class CaptchaResult extends StrutsResultSupport{
proterted void doExecute(String finalLocation,ActionInvocation invocation ) throws Exception{
//ValidateCode是一个ValidateVode.jar包中的一个类
ValidateCode code = new ValidateCode(200,100,4,10);
//使用ServletActionContext对象获取response对象
HttpServletResponse response = ServletActionContext.getResponse();
//得到getOutputStream()
code.write(response.getOutputStream());
}
}
- 5:全局视图
` <global-results>
<result name="success" type="captcha">
<param name="width">320</param>
<param name="height">240</param>
</result>
</global-results>
@在动作中访问servlet的API
1:使用ServletActionContext类
@封装请求正文到对象中
- 1:静态参数封装
:在struts.xml配置文件中,给动作类注入值,调用的是setter方 法,原因是由一个staticParams的拦截器完成注入的
- 2:动态参数封装
:通过用户的表单封装请求正文参数
1:动作类作为实体模型
实体模型:Entity,对应数据库中表的记录,类对应的是表结构,对象对应 的是一条记录,原因是由params拦截器完成的
2:动作类和实体模型分开
问题:由于没有初始化对象,默认为null,一调用setUser方法,就空指针
执行过程:第一次执行getUser,是框架判断该对象是否为null,如果不为null,就再次调用getuser为该对象中的属性赋值,如果为null,框架通过反射,把对象创建出来,在调用getUser为对象中的属性赋值
3:模型驱动:建立动作类和模型分开的前提下,是由一个modelDriven拦截器 做的,创建动作类时,实现modelDriven
@JNDI
Context initCtx = new InitialContext();
ds = (DataSource)initCtx.lookup();
@注册类型转换器
局部类型转换器:只能指定Javabean中的属性,按照属性来注册,在属性所属的javaBean的包下建立一个.properties文件,文件名称:Javabean名称-conversion.properties
全局类型转换器:按照要转换的数据类型来注册,at the top op classpath,建立
一个固定名称xwork-conversion.properties的属性文件
@数据回显
1:使用struts2的标签库生成表单,原因是由一个叫做conversionError的拦截器完成
的,要想使用类型转换中的错误处理,在定义Action是必须继承ActionSupport
@数据验证
1:验证方式
1:客户端验证:javascript 2:服务器验证:逻辑验证
2:服务端的验证
1:编程式验证:前提是动作类必须继承ActionSupport,在代码中编写验证规则
a:针对动作类中的所有动作方法进行验证:
在动作类中覆盖public void validate()方法
public void valuedate(){
if(StringUtils.isEmpty(user.getUsername())){
addFieldError(“username”,”用户名必须输入”);
}
}
b:针对动作类中的某个动作方法进行验证
针对某些问题1:给不需要验证的动作方法添加一个@SkipValudation注解1:validation方法遵守书写规范:
validate+要验证的动作方法名称,注意要验证的动作方法首字母要大写
2:声明式验证
:通过编写验证规则的xml文件,需要验证时,编写xml文件
a:针对动作类中的所有动作进行验证:在动作类所在的包中,建立一个
ActionClassName-validation.xml的文件
//requiredstring:是内置的验证器,默认会去掉首尾空格
<field-validator
type=”requiredstring”>
//提示信息
<message>
请输入用户名</message>
</field-validator>
3:struts2内置的常用声明式验证器
:参数注入使用param
@固定文本的国际化
1:创建一个消息资源包
一个资源包由多个文件组成,这些文件名都有命名规范:
主要文件名语言代码国家代码.properties,
当文件只有主要文件名.properties时,表明它是默认资源包
message_zh_CN.properties ,message_zh_HK.properties2:读取资源包中的内容
ResourceBundle bundle = ResourceBundle.getBundle(“配置文件名”)
@struts2中使用国际化
1:配置全局资源包
<constant
name=”struts.custom.i18n.resources” value=“配置文件名”></constant>
2:配置包范围的资源包
资源包名称命名规范:package_语言代码_国家代码.properties
3:局部消息资源包(只为动作类来使用的)
资源包名称命名规范:动作类名称语言代码国家代码.properties,优先级最高
4:自由指定读取资源包
,使用struts2的i18n标签
<s:i18n
name=”com.shikun.resources.messaeg”>
<s:text
name=”key”></s:text>
</s:i18n>
@struts2中的拦截器
1. 1:拦截器的重要性:
struts2中的很多功能都是由拦截器完成的,是AOP编程思想的一种应用形式
2. 2:拦截器的执行时机
执行动作之前:正序执行,结果视图之后:倒序执行
3. 3:自定义拦截器
1:编写一个类,继承AbstractInterceptor类或者实现Interceptor接口,重写in tercept方法
2:配置拦截器:注意拦截器必须先声明再使用
`<interceptors>`
` <interceptor` name="demo1" class="拦截器类名">`</interceptor>`
`</interceptors>`
`<action>`
//一旦配置了任何一个拦截器,那么默认的就都失效了
<`interceptor-ref `name="demo1">`</interceptor-ref>`
` </action>`
3:自定义拦截器栈及相关问题解决方法
`<package` name="mydefault" extends="struts-default">
//声明拦截器
`<interceptors>`
`<interceptor` name="checkLoginInterceptor" class="拦截器类名">`</interceptor>`
//声明拦截器栈
`<interceptor-stack` name="myDefaultStack">
`<interceptor-ref` name="defaultStack">`</interceptor-ref>`
<`interceptor-ref` name="checkLoginInterceptor"><interceptor-ref
`</interceptor-stack>`
`</interceptors>`
//定义默认拦截器栈
<default-interceptor-ref name="myDefaultStack>`</default-interceptor-ref>`
`</package>`
4: MethodFilterInterceptor中的方法
excludeMethods注入的方式,配置哪些动作方法不拦截
includeMethods注入的方式,配置哪些动作方法拦截
`<interceptor-ref>`
<param name="excludeMethods>`/param>`
`</interceptor-ref>`
@文件的上传(拦截器)
- 1:文件上传
1:表单method必须是post
2:enctype取值必须是multipart/form-data
3:提供文件选择域
- 2:限制文件上传
<constant name="struts.multipart.maxSize" value="10485760"></constant
- 3:限制文件上传的类型
<interceptor-ref name="defaultStack>
<param name="fileUpload.allowenExtensions">.jpg,.png,.bmp</param>
</interceptor-ref>
- 4:多文件上传
public String upload(){
//执行文件存放的位置
String directory = ServletActionContext.getServletContext().getRealPath("文件位置");
File file = new File(directory);
if(!file.exists()){
file.mkdirs();
}
if(photo != null && photo.length > 0){
for(int i =0; i<photo.length; i++){
photo[i].renameTo(new File(file,photoFileName[i]));
}
}
return null;
}
- 5:文件下载:其实就是一种结果类型(Stream)
public String download() throws FileNotFoundException{
//给输出流赋值
String filePath = ServletActionContext.getServletContext().getRealPath("文件位置");
fileInputStream = new FileInputStream(filePath);
//返回成功
return SUCCESS;
//剩下的交给stream类型的结果去完成
}
配置文件
<action name="download" class="com.shikun.web.action.DownloadAction" method="download">
<result name="success" type="stream">
//配置输入流
<param name="inputName">fileInputStream</param>
//设置响应消息头
<param name="contentDisposition">attachment;filename=${filename}</param>
//设置正文的MIME类型
<param name="contentType">application/octet-stream</param>
</result>
</action>
@OGNL
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目
1:支持普通方法的调用
<s:property
value=“‘OGNL-Expression’.length()”/>2:访问静态成员(静态属性,静态方法)
<s:property
value=”@java.lang.Math@random()”/>
//在struts2中,OGNL默认禁止访问静态方法
<constant
name=”struts.ognl.allowStaticMethodAccess” value=”true”></constant>
3:使用s:property取数据
a:取contextMap中的数据,需使用#
<s:prperty
value=”#contextMap”/>
b:用contextMap里面valueStack中对象的属性:直接写属性名
<s:property
value=”name”/>
特殊说明:当s:property不给定value属性时,默认取栈顶对象4:iterator标签
value:是OGNL表达式
var:是一个字符串,如果指定var属性,以var值为key,放入contextMap
如果不指定var属性,框架会把当前遍历的元素压入值栈中
status:是一个字符串,记录遍历数据的一些属性
<s:iterator
value=”students” status=”vs”>
<tr>
<td>``<s:property
value=”#vs.index”/></td>
<td>``<s:property
value=”name”/>${name}</td>
<td>``<s:property
value=”age”/>${age}</td>
</tr>
</s:iterator>
5:set标签的使用
value:存入map中属性的值,是一个OGNL表达式
var:存入map中属性的key
scope:存入的范围,如果不写,默认值是action,它是在contextMap中
和request范围内各存一份
6:action标签
action:调用action
如果要显示name指定的动作的结果,需要使用executeResult属性
<s:action
name=”action1” executeResult=”true”/>7:if标签
,elseif标签 else标签
<s:if
test=”#level ==’A’”></s:if>
<s:elseif
test=”#level ==’B’”>level B</s:elseif>
<s:else>
level<s:property
value=”#level”/></s:else>
- 8:url和a标签
s:url就是创建一个地址
value属性:输出的就是value的值,注意:value的取值不在是OGNL表达式,而 是字符串
action属性:输入的是action1的请求地址
var属性:会把action的值存到contextMap中
<s:url action="action1" var="url"></s:url>
<s:a action="aciton1">
<s:param name="username" value="test"></s:param>
<s:param name="city" value="北京"></s:param>
</s:a>
@valuestack
1:setValue方法
setValue(“name”,”值”); //就是把根中第一个name属性的值设置为第二个参数
2:set方法是操作根的
,如果栈顶元素是一个Map的话,直接把数据存入map中
如果栈顶元素不是一个Map,就创建一个map,把key和value存入map中,并压入栈顶
- 3:findValue
:寻找对应的值
Object obj = vs.findValue(“s2.name”);
- 4:放到请求域中的属性
,使用EL表达式取出来,但放到应用域中的属性,使用EL表达式 没取出来
@Struts2中$,%符号的使用
1:#:
1:取contextMap中key时使用,例
<s:property
value=”#name”/>
2:OGNL中创建Map对象时使用,例
<s:radio
list=”#{‘male’:’男’,’female’:’女’}”/>2:$
1:在jsp中使用EL表达式时使用,例 name2:在xml配置文件中,编写OGNL表达式时使用,例 {@java.net.URLEncoder.encode(f ilename)}
3:%
1:把普通字符串强制看成是OGNL,就需要使用%{}把字符串套起来
<s:textfield
value=”%{username}”/>
@防止表单重复提交解决办法
1:使用重定向
<result
type=”redirect”>/success.jsp</result>
2:
使用<s:token/>
生成令牌配合token拦截器
<s:token>``</s:token>
<interceptor-ref
name=”token”></interceptor-ref>
- 3:
使用<s:token/>
生成令牌配个tokensession拦截器
<interceptor-ref
name=”tokenSession”></interceptor-ref>