Struts2 学习 (三)Struts2基本配置和核心业务

1. 通配符

用于配置action:

<package name="registerAction" extends="struts-default">
    <action name="user_*" class="com.cityu.b_action.RegisterAction" method="{1}">
        <result name = "success">/{1}.jsp</result>
        <result name = "fail">/index.jsp</result>
    </action>
</package>

因此,JSP页面的下列表单项将会提交到user_register.action(也就是RegisterAction)中的register方法,如果result返回”success”,则会转发到register.jsp页面:

<form action="${pageContext.request.contextPath}/user_register.action" method = "post">

2. Struts中常量配置/国际化举例

在org.apache.struts2包default.properties文件中配置

可以在用户自定义的struts.xml文件中通过常量配置完成一些全局配置

例如国际化:

步骤:

写资源文件–>struts常量加载–>struts标签引入

首先,写资源文件com/cityu/b_action/msg.properties,其中是国际化的name-value对:形如login=\u767B\u9646

  • Msg.properties: 默认语言环境
  • Msg_en_US.properties:英语

然后,通过常量加载资源文件:

<constant name = "struts.custom.i18n.resources" value = "com/cityu/b_action/msg"></constant>

最后,在JSP页面中引入:

<%@taglib uri = "/struts-tags" prefix = "s"%>
<s:text name = "login"></s:text>

注意:国际化资源文件也可以在JSP用struts的i18n标签引入,但是这种方法不推荐!

1)修改访问后缀

<constant name = "struts.action.extension" value = "action,,"></constant>

2)动态方法调用

action name=”user”

/user!login—>访问user对应的action类中的login()方法

3. 全局配置

1)全局跳转视图

<struts>
    <package name="helloaction" extends="struts-default">
        <global-results>
            <result name = "success">/data_test.jsp</result>
        </global-results>
        <action name="data" class="com.cityu.action.HelloActioin" method="execute">
        </action>
    </package>
</struts>

注意需要配置在action节点前面

  • “+”一个或者多个;
  • “?”没有或者一个;
  • “*”没有或者一个或者多个

2)配置各项默认值

如果没有指定类:

<action name = "test"></action>

那么会执行默认的类com.opensymphony.xwork2.ActionSupport中的execute方法,并且返回值是”success”,会去跳转全局视图中找success对应的页面,这种方法,常用与用于页面转发:默认转发,可以跳转到WEB-INF目录下的资源(重定向redirect,不能访问WEB-INF下的资源—处于安全性考虑!)

4. 核心业务

4.1 请求数据自动封装

过程是由参数拦截器实现的,用户访问时,创建Action类对象,此时已经获得了Action中的属性,方法;提交表单数据后,会经过params拦截器

<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

对表单提交的数据进行封装(封装过程会使用到Action中的属性、方法),然后将封装后的结果返回给Action中的数据对象。

4.2 类型转换

jsp提交的数据(一般都是String类型),struts会自动转换为Action中对应的属性类型;对于基本类型,字符串类型会自动封装,而其他类型需要使用自定义类型转换器封装。

1) 自定义类型转换类,继承StrutsTypeConverter类
public class MyConverter extends StrutsTypeConverter{
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        try {
            return sdf.parse(values[0]);
        } catch (ParseException e) {
            throw new RuntimeException("converter failed!!");
        }
    }
    @Override
    public String convertToString(Map context, Object o) {
        return null;
    }
}
2) 配置转换器类

在需要类型转换的Action类同一个包路径下新建配置文件,命名为:

RegisterAction-conversion.properties
在其中配置需要转换的数据类型:提交的字符串—>封装类型

user.birthday=com.cityu.b_action.MyConverter
虽然转换器类是全局通用的,但是由于这个配置文件的原因,只能给RegisterAction提供转换,这被称为局部类型转换器

3)全局类型转换器

类型转换器类是不用修改的!

配置,在src/下:xwork-conversion.properties
java.util.Date=com.cityu.b_action.MyConverter

4) 优化转换器类:
public class MyConverter extends StrutsTypeConverter{

    SimpleDateFormat[] df = {
        new SimpleDateFormat("yyyyMMdd"),   
        new SimpleDateFormat("yyyy-MM-dd"), 
        new SimpleDateFormat("yyyy年MM月dd日") 
    };
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
        if(values == null || values.length==0){
            return null;
        }
        if (toClass!=java.util.Date.class) {
            return null;
        }
        //可以处理三种输入格式的转换
        for (SimpleDateFormat sdf : df) {
            try {
                return sdf.parse(values[0]);
            } catch (ParseException e) {
                continue;
            }
        }
        return null;
    }

    @Override
    public String convertToString(Map context, Object o) {
        return null;
    }
}

4.3 数据处理的几种方式

1)拿到ServletApi执行操作
<struts>
    <package name="helloaction" extends="struts-default">
        <global-results>
            <result name = "success">/data_test.jsp</result>
        </global-results>
        <action name="data" class="com.cityu.action.HelloActioin" method="execute">
        </action>
    </package>
</struts>

public class HelloActioin implements Action{
    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        ServletContext application = ServletActionContext.getServletContext();
        request.setAttribute("request_data", "hello_request");
        session.setAttribute("session_data", "hello_session");
        application.setAttribute("application_data", "hello_application");
        return SUCCESS;
    }
}
2) 使用ActionContext类
public class HelloActioin implements Action{
    @Override
    public String execute() throws Exception {
        ActionContext ac = ActionContext.getContext();
        Map<String, Object> request = ac.getContextMap();
        Map<String, Object> session = ac.getSession();
        Map<String, Object> application = ac.getApplication();
        request.put("request_data", "hello_request2");
        session.put("session_data", "hello_session2");
        application.put("application_data", "hello_application2");
        return SUCCESS;
    }
}

这种方式,没有必要使用Servlet的API,是一种解耦的方式,推荐!

但是,在必须使用Servlet的API时(例如通过request拿到当前的项目路径等等),没有办法去使用封装的map形式。

3) 通过实现接口来注入map对象
public class HelloActioin extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
    private Map<String, Object> request;
    private Map<String, Object> session;
    private Map<String, Object> application;
    @Override
    public void setRequest(Map<String, Object> request) {
        this.request = request;
    }

    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
    }

    @Override
    public void setApplication(Map<String, Object> application) {
        this.application = application;
    }

    @Override
    public String execute() throws Exception {
        request.put("request_data", "hello1");
        session.put("session_data", "hello2");
        application.put("application_data", "hello3");
        return SUCCESS;
    }
}

这种方式,也有解耦的效果。并且在action的业务方法比较多的时候,不需要每次都从ActionContext容器中去取域对象。这种方式已经通过接口在全局注入了域对象,可以在多个业务方法中使用。这种获取域对象的方式,通常在写BaseAction,做优化处理时使用。

4.4 文件上传

传统JSP/Servlet模型实现方式:

前台
  1. 提交方式POST
  2. 表单类型 multipart/form-data
  3. input type = file
后台

Apache提供的FileUpload组件
核心API:
FileItemFactory
ServletFileUpload
FileItem
总之,文件上传在servlet中实现时比较麻烦的!

Struts框架可以简化:前台无法简化(JSP规范),后台如何简化?

4.5 Struts文件下载

1) 通过response对象向浏览器写入字节流数据,设置响应头;
2) struts方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值