Skip to main content
Jkyo Chen Blog

Struts2.x 权威指南

Struts 2 核心技术 #

Struts 2 的 Action #

Action 访问 Servlet API #

Action 直接访问 Servlet API #

配置 Action #

配置 Action 的默认处理类 #

动态方法调用(DMI) #

// Form 表单
action="action!methodName.action"
struts.enable.DynamicMethodInvocation=true

为 action 元素指定 method 属性 #

使用通配符 #








    /WEB-INF/content/{1}.jsp



配置默认的 Action #

管理处理结果 #

配置结果 #

// 局部结果

    


// 全局结果

    

    /thank_you.jsp
    true


// name 逻辑视图名 默认为 success
// type 结果类型 默认结果类型是 dispatcher
// 还可以通过配置文件来改变默认的结果类型

// param name
// location 实际视图资源
// parse 指定是否允许在实际视图名字中使用 OGNL 表达式,默认值为 true

/thank_you.jsp

Struts2 支持的处理类型 #

chain 结果类型 #


    getBooks

plainText 结果类型 #


    /WEB-INF/content/welcome.jsp
    GBK

redirect 结果类型 #


    /WEB-INF/content/welcome.jsp

// Action 处理用户请求结束后,系统将重新生成一个请求,直接转入 /WEB-INF/content/welcome.jsp

redirectAction 结果类型 #


    
        
            dashboard
            /secure
        
    


    
        dashboard.jsp
        error
    
    
        /WEB-INF/content/error.jsp
    

动态结果 #


    /WEB-INF/content/input.jsp
    /WEB-INF/content/{1}.jsp

请求参数决定结果 #

edit.action?skill=${curSkill.name}
/WEB-INF/content/${target}.jsp

全局结果 #


    /WEB-INF/content/${target}.jsp

属性驱动和模型驱动 #

模型的作用 #

使用模型驱动 #



// 或者

Struts2 的异常机制 #

Struts2 的异常处理哲学 #

声明式异常捕捉 #


   
       /WEB-INF/content/welcome.jsp
       /WEB-INF/content/exception.jsp
       /WEB-INF/content/exception.jsp
   

// 全局异常映射
   
       
       
   

   
    // 局部异常映射
       
       /WEB-INF/content/exception.jsp
       /WEB-INF/content/error.jsp
       /WEB-INF/content/welcome.jsp
   

   
       /WEB-INF/content/{1}.jsp
   


// exception-mapping
//  exception 此属性指定该异常映射所设置的异常类型
//  result 系统转入 result 属性所指向的结果

输出异常信息 #

 // 输出异常本身
 // 输出异常堆栈信息

未知处理器 #

Struts2 的类型转换 #

类型转换的意义 #

表现层数据处理 #

传统的类型转换 #

String strAge = request.getParamter("age");
int age = Integer.parseInt(strAge);

Struts2 内建的类型转换器 #

public class RegisAction extends ActionSupport
{
    private String name;
    private String pass;
    private int age;
    private Date birth;

    public RegisAction()
    {
    }

    public RegisAction(String name, String pass, int age, Date birth)
    {
        this.name = name;
        this.pass = pass;
        this.age = age;
        this.birth = birth;
    }

    //setter and getter
}

// struts.xml 配置一样

基于 OGNL 的类型转换 #

public class RegistAction implemetns Action
{
    private User user;
    private String tip;

    // setter and getter

    public String execute() throws Exception
    {
        setTip("转换成功");
        return SUCCESS;
    }
}




使用 OGNL 转换成 Map 集合 #

public class LoginAction implements Action
{
    private Map users;
    private String tip;

    // setter and getter

    @Override
    public String execute() throws Exception
    {
        if (getUsers().get("one").getName().equals("czqlan") && getUsers().get("one").getPass().equals("123"))
        {
            setTip("success");
            return SUCCESS;
        } else
        {
            setTip("fail");
            return ERROR;
        }
    }
}

   

封装成对象 Map

// 访问 Action 的 Map 类型属性

使用 OGNL 转换成 List 集合 #

// List







自定义类型转换器 #

系统需求 #

实现类型转换器 #

public interface TypeConverter
{
    public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType);
}
public class UserConverter extends DefaultTypeConverter
{
    @Override
    public Object convertValue(Map context, Object value, Class toType)
    {
        if (toType == User.class)
        {
            String[] params = (String[]) value;
            User user = new User();
            String[] userValues = params[0].split(",");
            user.setName(userValues[0]);
            user.setPass(userValues[1]);
            return user;
        } else if (toType == String.class)
        {
            User user = (User) value;
            return "<" + user.getName() + "," + user.getPass() + ">";
        }
        return null;
    }
}

// 双向转换
// context 是类型转换环境的上下文
// value 是需要转换的参数
// toType 是需要转换的目标类型

局部类型转换器 #

// 同目录下 ActionName-conversion.properties
// propertyName=类型转换器

// LoginAction-conversion.properties
user=org.action.UserConverter
// 当浏览者提交请求时,请求中的 user 请求参数将会先被该类型转换器处理

全局类型转换器 #

// xwork-conversion.properties
// 复合类型=对应的类型转换器

org.domain.User=org.action.UserConverter

局部类型转换器和全局类型转换器的说明 #

基于 Struts2 的类型转换器 #

public abstract class StrutsTypeConverter extends DefaultTypeConverter
{
    @Override
    public Object convertValue(Map context, Object o, Class toClass)
    {
        if (toClass.equals(String.class))
        {
            return convertToString(context, o);
        } else if (o instanceof String[])
        {
            return convertFromString(context, (String[]) o, toClass);
        } else if (o instanceof String)
        {
            return performFallbackConversion(context, new String[]{(String) o}, toClass);
        } else
        {
            return performFallbackConversion(context, o, toClass);
        }
    }

    protected Object performFallbackConversion(Map context, Object o, Class toClass) {
        return super.convertValue(context, o, toClass);
    }

    public abstract Object convertFromString(Map content, String[] values, Class toClass);

    public abstract String convertToString(Map context, Object o);
}

// 将两个不同的转换方向替换成不同方法。
public class UserDemoConverter extends StrutsTypeConverter
{
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass)
    {
        User user = new User();
        String[] userValues = values[0].split(",");
        user.setName(userValues[0]);
        user.setPass(userValues[1]);
        return user;
    }

    @Override
    public String convertToString(Map map, Object o)
    {
        User user = (User) o;
        return "<" + user.getName() + "," + user.getPass() + ">";
    }
}

数组属性的类型转换器 #

集合属性的类型转换器 #

集合类型转换的高级特性 #

指定集合元素的类型 #

// Element_xxx=集合元素类型
Element_users=org.domain.User

// Map
// Key_xxx=key元素类型
// Element_xxx=value元素类型

为 Set 集合的元素指定索引属性 #

类型转换中的错误处理 #

类型转换的错误处理流程 #

处理类型转换错误 #

输出类型转换错误 #


// Invalid filed value for fileld "user"
// user ,Action 中的属性名
xwork.default.invalid.fieldvalue={0}字段类型转换失败!

// struts.xml
// ActionName.properties
// invalid.fieldvalue.属性名=提示信息

// LoginAction.properties 与 Action 相同位置
invalid.fieldvalue.birth=生日信息必须满足 yyyy-MM-dd 格式

处理集合属性的转换错误 #

Struts2 的输入校验 #

输入校验概述 #

为什么需要输入校验 #

客户端校验 #

服务器端校验 #

类型转换和输入校验 #

基本输入校验 #

编写校验规则文件 #

// RegistAction-validation.xml




    
        
            true
            
        
        
            
            您输入的用户名只能是字母和数字,且长度必须在 4 到 25 之间
        
    
    
        
            true
            
        
        
            
            您输入的密码只能是字母和数字,且长度必须在 4 到 25 之间
        
    
    
        
            1
            150
            年龄必须在 1 到 150 之间
        
    
    
        
            1900-01-01
            2050-02-21
            生日必须在${min}到${max}之间
        
    
// 国际化 RegistAction.properties
name.required=..
name.regex=...
pass.required=..
pass.regex=...
age.regex=..
birth.range=..

使用客户端校验 #

// registForm.jsp

    
    
    
    
    
// RegistAction-validation.xml

   
       true
       ${getText("name.required")}
   
   
       
       ${getText("name.regex")}
   

校验器的配置风格 #

字段校验器 #

// 在 validators 元素的 field 或 validator 中都可以出现一次或无限次。


// validators 是校验规则文件的根元素,该根元素下可以出现两个元素
// 
// 

// 出现第一种就是 字段优先,就是字段校验器配置风格
// 出现第二种元素,就是校验器优先,就是非字段校验器风格

   
       参数值
       校验失败后的提示信息
   
   ...

...

// 每个 field-validator 都必须有  元素

非字段校验器配置风格 #


    需要被校验的字段
    ...
    参数值
    ...

    校验失败后的提示信息

...

短路校验器 #