开发者学堂课程【Java Web开发系列课程 - Struts2框架入门:回顾】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/537/detail/7320
一、类型转换
1、在 servlet 中如果表单提交非符数据的时候,需要进行类型转换:如提交 age
代码如下
String strAge =reg-getParameter("age");
int age=0;
if(stnAge!=nu11){
age=Integer.parseInt(strAge);
2、在 struts2中,常见数据类型 struts2已经自动的进行了类型转换。无需程序独进行手动转换。
3、某些情况下,有自定义的类型时,struts2不能完成类型转换,那么需要手动转换,如果该自定义类型使用的领率较高时,手动转换重复代码将会增多使用 struts2提供的类型转换器来进行类型转换。
4、案例:比如坐标点(x.y)
不进行类型转换的处理方式: Jsp 页面:
代码如下
String strAge =reg-getParameter("age");
int age=0;
if(stnAge!=nu11){
age=Integer.parseInt(strAge);
Action 代码:
public class PointAction{
private Point point;
public String execute(){
Systen.out.println(point.getx()+"_----"+point.getY());
return Action.SUCCESS:
}
public Point getPoint(){
return point;
}
public void setPoint(Point point){
this.point = point;}
Struts.xml 配置
代码如下
tpackage name="defoult" namespace="/" extends="struts-default",
/index.jsp x/action>
这种方式不符合数学的表示形式;采用大至诗换的处理
5、使用类型转换的步观:
a编写类型转换器-继承$trutsTypeComverter类
b)编写 xwork-comversion properties 的配置文件,放于 sre 下;内容为要转换的类型-类型转换器
6、使用类型转换来完成上述案例:
类型转换器:
public class PointConverter extends StrutsTypeConverter
/**
*将表单提交的字符串数据 转换为 指定自定义类型
*context是ActionContext
*values 要进行类型转换的字符串数组
*toClass 被转换的类型
**/
@Override
public Object convertFromString(Map context, String[] values,
Class toClass){
String valuemvalues[0]; Point point =new Point();
String xmvalue.substring(1,value.index0f(","));
String
y=value.substring(value.index0f(",")+1,value.length()-1);
System.out.println("x="+x);
System.out.println("y="+y);
point.setx(Integer.parseInt(x)); point.setY(Integer.parseInt(y));
return point;
}
/**
*将定义类型 转换为字符串在前台页面显示----通过ognl表达式将会使用该方法进行转换
*contextactionContext
*o要转换的对象
**/
@Override
public String convertToString(Map context,Object o){
Point point =(Point)o;
return "("+point.getx()+","+point.gety()+")";
}
xwork-conversion.properties 配置文件
cn.sxt.entity.Point=cn.sxt.converter.PointCorverter Action
代码不变,struts.xml 配置 Jsp 页面
action="point.action" method="post">
点:<input type="text" name="point"/><br)
<input typem"submit" valuem"
提
交"/>
</form>
二、struts2的验证机制
1、服务端验证:如果 action 类继承 ActionSupport 类,那么该 action 类将会继承ActionSupport 的相关功能:如:验证功能。
执行流程为
requet
validateXxx方法
T
validate 方法
T
xxx方法
F:imput
Result
reqpsonse
注意:如果执行的是 Action 中的 execute 方法,那么只会执行 validate 方法。
如果执行的是自定义的 action,register 方法,那么将会先执行 validateRegister--validate--register 方法。
2、案例:
Jsp 页面:
一定要加上<s:actionerror>或者是<s:feiderror>
<s:actionerror/>
<form action="register.action" method="post">
用户名:cinout tvpe="text" name="name"/><br>
年龄:<input type="text" name="age"/><br>
生日:<input type="text" name="birthday"/><br>
<input type="submit" value="登
录
"(</form>
Action 代码
public class RegisterAction extends ActionSupport{
private String name private String pwd; private int age;
private Date birthday;
@Override
public String execute() throws Exception{
System.out.println("execute");
return Action.SUCCESS;
public String register(){
System.out.println("register");
return Action.SUCCESS;
}
public void validateRegister(){
System.out.println("validate age");
if(age>100||age<1){
this.addActionError("年龄不合法");
}
}
public void validate(){
System.out.println("validate");
}
public String getName(){
return name,
this.birthday = birthday;
}
Struts.xml 配置文件
<package name="defoult" extends="struts-default" namespace="/"
<action name="register"
class="cn,sxt.action.RegisterAction" method="register">
<result>/index.jspx/result>
<result namem"input">/register.jsp</result>
</action>
</package>
3、struts2的验证框架
使用险证框架的步骤:在对应的 action 的包下添加一个验证框架的配置文件该文件名为:actionName-validation.xml
案例:Jsp 页面
<s:fielderror></s:fielderror)
<form action="register.action" method="post",
用户名:<input type="text" name="name"/><br>
密码:<input typem"password" name="pwd"/><br>
年龄:<input type="text" name="age"/><br>
生日:<input tvpe="text" name="birthday"/><br>
<input type="submit" value="
登录
"/>
</form>
Action类
public class RegisterValidateAction extends ActionSupport{
private String name;
private String pwd; private int age;
private Date birthday;
@Override
public String execute() throws Exception {
System.out.println("execute");
return Action.SUCCESS;
}
public String getName(){
}
return name;
}
public void setName(String name){
this.name = name;
}
public String getPwd(){
return pud;
}
public void setPwd(String pwd){
}
this.pwd = pwd; public int getAge(){
return age;
}
public Date getBirthday(){
return birthday;
}
public void setBirthday(Date birthday){
this.birthday = birthday;
}
}
struts. xmt 配置
<package name="default" extends="struts-default" namespace""/">
<!-- <action namem"renister"
class="cn.sxt.action.RegisterAction" method="register">
<result>/index.jsp</result>
<result name-"input">/register.jsp</result></action>->
<action name-"register"
class-"cn.sxt.action,RegisterValidateAction">
<result>/index.jspx/result>
<result name="input">/register.jsp</result>
</action></package>
RegisterValidateAction-validation xml 验证文
件
<?xm1 version="1.0"encoding="UTF-8"?>
<!DOCTYPE yalidators PUBLIC "-//Apache Struts//XWork Validator
1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名必填</message>
</field-validator>
<field-validator type="stringlength">
<param name="trim">true</param><param name="maxLength->10</param>
<param namem"minLength->4</param>
<message>用户名去掉2端空格后长度为${minLength}到
${maxLength)</message>
</field-validator></field>
<field namem"age">
<field-validator type="int">
<param name="min">1</param><param namem"max">150</peram
<message>年龄范围为1~150</message>
三、拦截器
1、拦截器:拦截器和过滤器很相似。在 action 执行的前后执行。Struts2的核心功能都是通过拦截器来实现。
2、拦截器栈:由多个拦截器组成。
3、作用:对于 action 的一些公共处理代码可以放到拦截器中来实现。如:权限控制,日志等等。
4、多个拦截器之间的执行是采用责任链设计模式来实现。
5、拦器的执行流程
Http ServietRequest
apServeRegone
Struts Filter Dispatcher
Interceptor 1
Interceptor 2
Interceptor N
Action
Result
6、拦截器的实现步骤:
a)编写拦截器(实现 Interceptor 接口或者继承 Abstractinterceptor 类)
b) 在 struts.xml 中配置拦截器
c)在 action 中引用拦截器
7、案例:
定义拦截器
/**
*计算 action 执行时间
*/
public class TimeInterceptor extends AbstractInterceptor(
@Override
public String intercept(ActionInvocation invocation) throws Exception{
long start=System.currentTimeMillis();
//执行下一个拦截器,当拦截器执行完后执行action String result= invocation.invoke(); long end=System.currentTimeNillise);
System.out.println(“执行该 Action 所用时间为:
"+(end-start)+"ms");
return result;
}
在struts.xml中配置拦
截
器,以及引用拦截
器
<struts>
<package name="default" extends="struts-defoult"
namespace="/">
<!-- 配置拦截器 -->
<interceptors>
</field-validator>
</field>
</validators>
<interceptor name="time"
class="cn.sxt.interceptor.TimeInterceptor"/>
</interceptors>
<action name="hello" class="cn.sxt.action.HelloAction">
<result>/index.jsp</result>
<!-- 应用拦截器 -->
<interceptor-ref name="time"/>
</action>
</package>
</struts>
当请求hello.action 时将会执行该拦截器。
8、拦截器的配置详解
a)当引用了自定义拦截器时,默认拦截器将不起作用。
b)默认拦截器:在 struts-default.xml 中,配置了默认拦截器。
c)当配置时认拦截器以后,如果不引用拦截器,那么默认的拦截器将起作用。
<default-interceptor-ref name="defoultStack"/>
当引用自定义拦截器后,又想使用truts2提供的拦截器功能,那么需要手动引用
<action name="hello" class="cn.sxt.action.HelloAction">
<result>/index.jsp</result><!-- 引用拦截器-->
<interceptor-ref name="time">
<!-- 引用默认的拦截器栈;引用拦截器和引用拦截器
栈
的方式一
样-->
<interceptor-ref name="defoultstach"",</action>
d)当 action 应用的拦截器个数比较多时,可以将多个拦截器放入一个拦截器栈中。
<!-- 一个拦截器栈中,可以包含多个拦
截
器的引用
拦
截
器栈的引用和拦截器一致
-->
<interceptor-stack name="myStack",
<!--引用拦
截
器-->
<interceptor-ref namen"time"/>
<!--拦
截
器栈中,可以包含多个拦截器的引用
拦截器栈的引用和拦截器一致 -->
<interceptor-stack name="myStack">
<!-- 引用拦截器 -->
<interceptor-ref name="time"/>
<!引用默认的
拦截
器栈;引用拦
截
器和引用拦截器栈的方
式一样-->
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<action namem"hello" classm"cn.sxt.action.HelloAction">
<result>/index.isp</result>
<interceptor-ref name="myStack">
</action>
e)当自定义拦截器在这个包下的所有 action 都使用的时,可以定义为默认的拦截器栈,或默认的拦截器
<!--定义默认的拦截器/栈-->
<default-interceptor-ref namem"myStock""
<action name="hello" class="cn.sxt.action.HelloAction">
<result>/index.jsp</result>
</action>
9、拦截器的运用案例:
对于登录权限的控制:拦截器的实现:
public class LoginInterceptor extends Abstractinterceptor
@Override
public String intercept(ActionInvocation invocation) throws Exception{
//判断是否是login.action如果是则直接执行下一个拦截器
//如果不是则判断是否登录,如果登录执行下一个拦截器
//如果没有则返回登录页面
//actionName没有扩展名
String actionName-invocationgetProxy()getActionName(); if("login".equals(actionName)){
return invocation.invoke();
}
Object obj =
invocation.getInvocationContext().getSession().get("user");
if(obj==nu11){//没有登录
return Action.LOGIN;
}
return invocation.invoke();
}
}
Struts.xml的配置
<struts>
<package name="defoult
extends=
"struts-default"
namespace="/">
<!-- 配置拦截器 -->
<interceptors>
<interceptor name="time"
class-"cn.sxt.interceptor.TimeInterceptor"/>
<interceptor name="loginInterceptor
class="cn.sxt.interceptor.loginInterceptor"
<-- 一个拦截器栈中,可以包含多个拦截器的引用
拦截器栈的引用和拦截器一致 -->
<interceptor-stack name="myStack">
<interceptor-ref name="loginInterceptor"/>
<!-- 引用拦截器 -->
<interceptor-ref name="time"/>
<!--引用默认的拦截器栈 ;引用拦截器和引用拦
截
器栈的方
式一样-->
<interceptor-ref name="defaultstack""></interceptor-stack></interceptors>
<!-- 定义默认的拦截器/栈 -->
<default-interceptor-ref name="mystack"/>
<global-results>
<result name="login">/login.jsp</result>
</global-results>
<action name="hello" class="cn.sxt.action.HelloAction">
<result>/WEB-INF/index.jsp</result>
</action>
<action name="login" class="cn.sxt.action.loginAction">
<result>/success.jsp</result>
</action>
</package>
</struts>
jsp 页面
<body>
<form action="user/login.action" method="post">
用户名:<input type="text" name="name"/><br>
密码:<input type="password"namem"pwd"/><br>
<input type="submit" value="登
录
"/>
</form>
<body>
Action代码
public class LoginAction {
private String name;
private String pwd;
//处理方法
public String execute(){
System.out.println(name+"---"+pwd);
if("siggy".equals(name)&&"1111".equals(pwd)){
ActionContext.getContext().getSession()-put("user",
name);
return "success";
}else{
return "login";
}
}
public String logout(){
System.out.println("退出");
return "success";
}
public String getName(){
return name;
public void setName(String name){
this.name = nane;
}
public String getPwd(){
return pwd;
}
public void setPwd(String pwd){
this.pwd = pwd;
}
}
10、方法拦截器:方法拦截器时比 Action 拦截器更加细粒度的控制,主体实现和 Action 拦截器一致。但是方法拦截器时继承 MethodFilterinterceptor 类,重写dointercept()方法。
引用方法拦截器配置会发生改变:
<interceptor-ref name="methodInterceptor",
<!-- 配置被拦截的方法 -->
<param name="includeMethods">list,add</param)
<!-- 配置不被拦截的方法 -->
<param name="excludeMethods">login</param)
<interceptor-ref>
四、文件上传
1、struts2的文件上传功能使用的是 apache 下的 commons-fileupload 来实现
2、Js 的表单要求是 post 提交,并且 enctype=multipart/form-datd"
<form action="upload.action" method="post"
enctypem"multipart/form-data">
文件:<input type="file" name="file"/>
<input type="submit" value="上传"/>
</form>
3、action 的代码:在 Action 中需要提供3个属性,一个 File 类型,名称是表单域名,其它两个分别是表单域名+FileName,表单域名+ContentType;并且提供 get/set 方法 public class UploadAction extends ActionSupport{
private File file;
//文件名
private String fileFileName;
//文件的类型
private String fileContentType:
//上传
public String upload() throws IOException{
//写文件的过程
HttpServletRequest request =
ServletActionContext.getRequest();
String path=request.getRealPath("/upload");
InputStream is = new FileInputStream(file);
OutputStream os = new FileOutputStream(new File(path,fileFileName));
byte[] buffer = new byte[200];
int len=0;
while((len=is.read(buffer))!=-1){
os.write(buffer,
len);
}
os.close(); is.close();
return Action.SUCCESS:
}
public File getFile(){
return file;
public void setFile(File file) {
this.file = file;
}
public String getFileFileName(){
return filefileName;
}
public void setFileFileName(String fileFileName){
this.fileFileName = fileFileName;
}
public String getFileContentType() {
return fileContentType;
}
public void setFileContentType(String fileContentType){
this.fileContentType = fileContentType;
}
}
4、struts.xml 配置文件的编写;主要是上传文件大小的控制。需要配置拦截器的 maximumSize 属性和 struts2 的静态属性:struts.multipart.maxsize: maxsize 要大于等于 maximumSize。
<struts>
<!--设置临时自录-->
<constant name="struts.multipart.saveDir" value="c:("/><!-- 设置上传文件的最大大小必须大于等于maximumSize->
<constant name="struts.multipart.maxSize" value="20971520"/>
<package namem"default" extends="struts-default" namespace."/>
<action name="upload" class="cn.sxt.action.UploadAction"
method="upload">
<result>/index.jsp</result>
<interceptor-ref name="fileUpload">
<param namem"maximumSize">20971520</param)
<interceptor-ref>
<interceptor-ref name="defoultstack"/>
</action>
</package>
</struts>