基于Annotation的输入校验
虽然这些Annotation实质上也属于Struts2的零配置特性,但是这些并不是Convention插件提供的,而是由XWork提供的,因此不需要Convention插件
使用Annotation修饰Action里各属性对应的setter方法
public class RegistAction extends ActionSupport {
private String name;
//省略其他属性
@RequiredStringValidator(key="name.required", message="")
@RegexFieldValidator(expression="\\w{4,25}", key="name.regex",
message="")
public void setName(String name) {
this.name = name
}
public void getName() {
return name;
}
}
手动完成输入校验
1.重写validate()方法:会校验所有的处理逻辑
public class RegistAction extends ActionSupport {
private String name;
...
public void validate() {
...
}
}
2.重写validateXxx方法
如果想输入校验只针对某个逻辑,仅仅校验某个处理方法,重写validate方法显然不够,validate无法准确知道需要校验某个处理方法
public class RegistAction extends ActionSupport {
private String name;
...
public String regist() {
return SUCCESS;
}
public void validateRegist() {
if(!name.contains("1")) {
addFieldError("user", "错误信息");
}
}
}
无论用户向Action的哪个方法发送请求,Action内的validate方法都会被调用;如果该Action内还有该方法对应的validateXxx方法,则会在validate方法前调用。
Struts2的输入校验步骤
1.类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值
2.在执行类型转换过程中可能出现异常,如果出现,则将异常信息保存到A ctionContext中,conversionError拦截器负责将其封装到FieldError里,然后执行下一步;如果没有异常,则直接下一步
3.使用Struts2应用中所配置的校验器进行输入校验
4.通过反射调用validateXxx()方法,即处理用户请求的处理逻辑所对应的方法
5.调用Action类里的validate()方法
6.如果上述步骤都未出现FieldError,则调用Action里处理用户请求的处理方法;如果出现,则转入input逻辑视图所指定的视图资源
使用Struts2控制文件上传
为了能上传文件,我们必须将表单的method设置为post;将enctype设置为multipart/form-data,只有这种情况下,浏览器才会把用户选择文件的二进制数据发送给服务器
Struts2的文件上传还没来得及使用Servlet 3.0 API,因此还需要Common-FileLoad和COS等文件上传组件
Struts2不会自己去处理multipart/form-data的请求,它需要调用其他上传框架来解析二进制请求数据。
在struts.properties配置文件:
struts.multipart.parser=cos //指定使用COS的文件上传解析器
struts.multipart.parser=pell //使用pell的文件上传解析器
struts.multipart.parser-jakarta //默认使用jakarta的Common-fileload~
<s:form action="uploadPro" enctype="multipart/form-data">
<s:file name="upload" label="选择文件" /><br />
<s:submit value="上传" />
</s:form>
public class UploadAction extends ActionSupport {
private String title; //请求参数属性
private File upload; //上传文件域的属性
private String uploadContentType; //上传文件类型的属性
private String uploadFileName; //上传文件名称
... //省略get和set
private String savePath; //struts.xml配置的属性
public void setSavePath(String value) {
this.savePath = value;
}
public String getSavePath() throws Exception {
return ServletActionContext.getServletContext()
.getRealPath("/WEB-INF/" + savePath);
}
@Override
public String execute() throws Exception {
FileOutputStream fos = new FileOutputStream(
getSavePath() + "\\" + getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] buffer = new byte[1024];
int len = 0;
while((len == fis.read(buffer) > 0)) {
fos.write(buffer, 0, len)
};
return SUCCESS;
}
}
手动实现文件过滤
大部分时候,WEB应用不允许浏览者自由上传,尤其是不能上传可执行文件,防止病毒;通常可以上传图片、压缩文件等;除此之外,还需要限制文件的大小,因此必须在上传中进行文件过滤;
1.在Action中定义一个专用于文件过滤的方法,方法命名任意,该方法的逻辑就是判断上传文件的类型是否为允许类型
过滤文件类型
public String filterType(String[] types) {
//获取希望上传的文件类型
String fileType = getUploadContentType();
for(String type : types) {
if(type.equals(fileType)){
return null;
}
}
return ERROR;
}
2.为了程序可以动态配置允许上传的文件列表,为该Action增加了一个allowTypes属性,该属性列出所有允许上传的文件类型。
private String allowTypes;
//省略get和set
3.利用输入校验判断用户输入的文件是否符合要求;如果不符合,则加入FieldError中
public void validate() {
String filterResult = filterType(getAllowTypes().split(","));
if(filterResult != null) {
addFieldError("upload", "错误信息");
}
}
validate方法添加了FieldError,这样将自动返回input逻辑视图名;只有当文件类型是允许上传时,才会调用真正的上传逻辑;
配置文件
<action name="uploadPro" class="com.action.UploadAction">
<param name="allowTypes">image/png, image/gif, image/jpg</param>
</action>
<s:fielderror />
拦截器实现文件过滤
Struts2提供了一个文件上传的拦截器,通过配置该拦截器可以实现文件过滤;
配置fileUpload拦截器,需指定两个参数:
allowedTypes //允许上传的文件类型,多个类型之间以英文逗号隔开
maximumsize //允许上传文件的大小,单位是字节
<action name="uploadPro" class="com.action.UploadAction">
<interceptor-ref name="fileUpload">
<param name="allowedTypes">image/png,image/gif</param>
<param name="maximumSize">2000</param>
</interceptor-ref>
<interceptor-ref name="defaultStack">
</action>
interceptor-ref的配置问题:
defaultStack是系统默认使用的defaultStack;引入自己配置的拦截器后,会覆盖掉系统默认的default;如果需要继续起作用,需要手动引入;
<interceptors>
<interceptor name="myInterceptor"class="com.interceptor.
MyInterceptor" />
<interceptor-stack name="myInterceptorStack">
<interceptor-ref name="myInterceptor" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
注意两个interceptor-ref的顺序, 顺序不同, 执行效果也不同:
先配置的先执行/后配置的先退出(先进后出)
使用Struts2控制文件下载
使用超链接下载时,如果文件名为中文,则会导致下载失败;所以应用程序需要在用户下载之前进行进一步检查,比如判断是否有权限等,就需要Struts2控制下载;
public class FileDownloadAction extends ActionSupport {
private String inputPath;
..
public InputStream getTargetFile() throws Exception {
return ServletActionContext.getServletContext().
getResourceAsStream(inputPath);
}
}