【Java EE 学习第35天】【strus2】【类型转换器】【struts2和Servlet API解耦】【国际化问题】

一、类型转换器

  1.在动作类action中,声明和表单中name属性的值同名的属性,提供get和set方法,struts2就可以通过反射机制,从页面中获取对应的内容

 1 package com.kdyzm.convert;
 2
 3
 4 import com.opensymphony.xwork2.ActionSupport;
 5
 6 public class TypeConvertAction extends ActionSupport{
 7     private static final long serialVersionUID = 5695452524134841455L;
 8     private int id;
 9     private String name;
10     public int getId() {
11         return id;
12     }
13
14     public void setId(int id) {
15         this.id = id;
16     }
17
18     public String getName() {
19         return name;
20     }
21
22     public void setName(String name) {
23         this.name = name;
24     }
25
26     @Override
27     public String execute() throws Exception {
28         System.out.println("访问了默认的execute方法!");
29         System.out.println("id="+id);
30         System.out.println("name="+name);
31         return "success";
32     }
33 }

TypeConvertAction

  2.并非所有类型的值struts2框架都能转化,比如经典的Date类型的数值(标准格式的yyyy-MM-dd可以)。提示错误信息:

九月 08, 2015 9:56:09 上午 com.opensymphony.xwork2.interceptor.ParametersInterceptor error
严重: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting ‘register_date‘ on ‘class com.kdyzm.convert.TypeConvertAction: Error setting expression ‘register_date‘ with value [‘2015/2/1‘, ]
九月 08, 2015 9:56:09 上午 com.opensymphony.xwork2.util.LocalizedTextUtil warn
警告: Missing key [invalid.fieldvalue.register_date] in bundles [[org/apache/struts2/struts-messages, com/opensymphony/xwork2/xwork-messages]]!

  该错误提示信息提示了处理该转换的拦截器是ParametersInterceptor,错误的原因是不能将value值为2015/2/1(非标准格式的日期)类型转换为register_date的数值类型。而且能提示该错误信息是因为开启了开发者模式,具体见上一天内容。

  3.当转换失败的时候,如果想要让页面跳转到指定页面,则应当在配置文件中添加如下内容:

       <result name="input">
                <param name="location">
                    /01_converter/fail.jsp
                </param>
            </result>

  4.struts2框架不能将在页面中得到的字符串进行类型转换时,就需要自定义类型转换器。

    (1)自定义类型转换器必须实现TypeConverter接口或者继承该实现类DefaultTypeConverter,实现或者重写convertValue方法。

       com.opensymphony.xwork2.conversion.TypeConverter

          |--com.opensymphony.xwork.conversion.impl.DefaultTypeConverter

              |--org.apache.strut2.util.StrutsTypeConverter

      注意第一个接口com.opensymphony.xwork2.conversion.TypeConverter和com.opensymphony.xwork.conversion.impl.DefaultTypeConverter在xwork-core核心包,但是org.apache.strut2.util.StrutsTypeConverter在struts-core核心包。

    (2)选择继承DefaultTypeConverter类,这里有三个convertValue方法,需要重写那个方法呢?

        底层代码:

public abstract class DefaultTypeConverter implements TypeConverter {
public Object convertValue(Map<String, Object> context, Object target, Member member,String propertyName, Object value, Class toType) {
        return convertValue(context, value, toType);
    }
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
        return convertValue(value, toType);
    }
public Object convertValue(Object value, Class toType) {
     ......
   }
}

        可见最后调用的方法是public Object convertValue(Object value, Class toType),所以重写该方法就可以了。

        value是一个字符串数组,原因是struts2底层取值的方法都是getParameterValues;toType是将要转换成的数据类型。

    (3)注册转换器:注册转换器的方法有两种,一种是局部的配置文件注册,另外一种是全局的配置文件配置

      局部的配置文件配置方式:

        在动作类的同目录下,创建一个名为"TypeConvertAction-conversion.propterties"的配置文件,在该配置文件中写上:表单中对应项下面的name属性的值=

        定制转换类的全类名。如register_date=com.kdyzm.convert.DateConverter

        *  TypeConvertAction是Action的类名,-conversion是固定写法。

      全局的配置文件方式:

        在class目录下,创建一个全局的配置文件"xwork-conversion.properties",其内容配置为:java.util.Date=com.kdyzm.convert.DateConverter

        这样就将所有表单中字符串类型的日期输入转换成日期对象了,而不仅仅是某个表单中的某个字段而已。

    (4)自定义日期类型转换器,将yyyy年MM月dd日格式的字符串转换为标准格式的日期。

        第一步:在Action类中添加属性register_date,类型是Date,提供标准的get方法和set方法。

 1 package com.kdyzm.convert;
 2
 3
 4 import java.util.Date;
 5
 6 import com.opensymphony.xwork2.ActionSupport;
 7
 8 public class TypeConvertAction extends ActionSupport{
 9     private static final long serialVersionUID = 5695452524134841455L;
10     private int id;
11     private String name;
12     private Date register_date;
13
14     public Date getRegister_date() {
15         return register_date;
16     }
17
18     public void setRegister_date(Date register_date) {
19         this.register_date = register_date;
20     }
21
22     public int getId() {
23         return id;
24     }
25
26     public void setId(int id) {
27         this.id = id;
28     }
29
30     public String getName() {
31         return name;
32     }
33
34     public void setName(String name) {
35         this.name = name;
36     }
37
38     @Override
39     public String execute() throws Exception {
40         System.out.println("访问了默认的execute方法!");
41         System.out.println("id="+id);
42         System.out.println("name="+name);
43         System.out.println("register_date="+register_date);
44         return "success";
45     }
46 }

TypeConvertAction

        第二步:创建转换器,继承DefaultTypeConverter类,并重写convertValue(Object value,Class toType)方法。

package com.kdyzm.convert;

import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;

public class DateConverter extends DefaultTypeConverter{

    @Override
    public Object convertValue(Object value, Class toType) {
        System.out.println(value);
        System.out.println(toType);
        if(value==null||toType==null)
            return null;
        if(!toType.equals(java.util.Date.class))
            return null;
        if(value instanceof java.lang.String[])
        {
            String []str=(String[]) value;
            String temp=str[0];
            try {
                temp=new String(temp.getBytes("iso-8859-1"),"utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日");
            Date date;
            try {
                date = sdf.parse(temp);
                return date;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
        return null;
    }

}

        第三步:注册转换器,这里使用局部的配置方式,新建配置资源文件:TypeConvertAction-conversion.properties,内容如下

register_date=com.kdyzm.convert.DateConverter

        第四步:验证输出

        

        后台打印结果:

        

  5.可以将javaBean对象作为Action类中的成员变量

    但是使用方法需要改变。

    首先Action文件中首先需要改变:

private Edu edu;

    其中Edu是一个JavaBean。

    再者jsp文件也需要改变:

    学历编号:<input type="text" name="edu.eduid"><br>
        学历名称:<input type="text" name="edu.eduname"><br>

  6.可以将Collection对象作为Action类中的成员变量。

    Collection中的成员是javaBean。

private Collection<Emp>coll;

    同时jsp页面中也需要进行相应的修改:

学历编号:<input type="text" name="coll[0].eduid"><br>
学历名称:<input type="text" name="coll[0].eduname"><br>

学历编号:<input type="text" name="coll[1].eduid"><br>
学历名称:<input type="text" name="coll[1].eduname"><br>

  5.配置错误提示信息为中文:乱码未解决。

      怎样在jsp页面中显示中文错误提示信息呢?

      应当引入sruts2中的标签。

<%@ taglib uri="/struts-tags"   prefix="s"%>

      使用的标签时:

<s:fielderror fieldName="createTime"/>

      用法是:在fieldName字段值改为:可能会出现错误的字段的name值。

    (1)当输入的日期类型不合法的时候,会提示如下信息的错误提示

      

      控制台输出的错误信息:

      该错误信息提示在两个资源文件中都都没有对应的key:invalid.fieldvalue.register_date,如果这两个资源文件中有一个存在该key值,这个错误就不会报出来了。

      能不能将英文改成中文呢?

      通过修改配置文件能够达到目的。

    (2)配置文件所在的地方:xwork-core-2.3.24.jar包下的com.opensymphony.xwork2.xwork-messages.properties资源文件,但是jar包中的文件最好不要修改,

       那么怎么做才能达到目的呢?

      上面的提示信息在文件中的位置

       

    (3)修改方法

      * 在动作类Action同目录下,创建一个名为"conerter.properties"的资源文件

      * 该资源文件配置如下

        * 针对所有字段的:

          xwork.default.invalid.field.fieldvalue=类型转换失败"{0}"

        * 针对某个字段的:

          invalid.fieldvalue.register_date=注册日期字符串转换成日期对象的时候失败!(对比(1)中的错误信息提示)

      * 进行以上的配置之后,还应当将配置注册到struts.xml文件中。

<constant name="struts.custom.i18n.resources" value="com.kdyzm.convert.converter_messages"></constant>

        注意,value值在写的时候不要加上后缀,即.properties后缀不要带上,只使用文件名就可以了。

    (4)未解决的问题:struts2中的properties文件中文乱码问题,只要输入中文就会自动编码成乱码,同时,如果将文件的编码方式改成utf-8,那么再次打开的时候如果

      使用myelcipse的工具打开仍然是乱码,如果是使用了properties edit工具打开的话就不会是乱码,但是在jsp文件中显示的时候仍然是乱码。很担心国际化的时候仍

      然会是中文乱码,那时候国际化的时候就会完全失败了。

      解决中文乱码的方法是:使用properties edit插件,但是该插件在myelcipse中并不好用。

      插件里里连接地址:http://java-properties-editor.com/

    



二、Struts2和ServletAPI解耦

  1.使用该方式的目的是什么:为了避免和ServletAPI耦合在一起,方便Action做单元测试。

  2.做了什么样的改进:Struts2对HttpServletRequest、HttpSession、ServletContext进行了封装,构造了三个对象来替代这三个对象。在Struts2中可以直接使用这三个对象所对应的Map对象可以非常方便的实现对数据的增加、查找和删除。

  3.使用方法简介:

    (1)第一种方法:使用ServletActionContext类来获取几个对象。

1 HttpServletRequest request=ServletActionContext.getRequest();
2         HttpServletResponse response=ServletActionContext.getResponse();
3         HttpSession session=request.getSession();
4         ServletContext application=ServletActionContext.getServletContext();

    (2)第二种方法:实现接口以获取几个对象:ServletRequestAware,ServletResponseAware,ServletContextAware,SessionAware

        这四个借口分别只定义了一个接口,实现该接口就能获取到所需要的各个对象的值。



三、国际化(.properties乱码问题没有解决)

  1.软件本地化:一个软件在某个国家或者地区使用的时候采用该国家或者地区的语言、数字、货币、日期等习惯

  2.软件国际化:软件开发的时候让它能够支持多个国家或者地区的本地化应用。

  3.使用struts2实现软件国际化需要定义资源文件,资源文件的定义需要遵循一定的规则

    资源文件会包含用默认语言编写的会在程序中出现的所有消息。这些消息会以键值对的形式存储。

    当对一个应用程序进行国际化处理的时候,所要用的各种语言版本的信息应当存放在不同的资源文件中,每一个这样的文件对应着一种语言版本。所有这样的文件合在一起称为资源包(Resource Bundle)

  4.属性文件的命名格式分为以下两种:

    (1)文件名前缀.properties

    (2)文件名前缀_语言种类.properties

    文件名前缀可以自由书写,语言种类字段必须是合法的ISO语言代码。改代码可以在浏览器上查看(IE)。

    文件名前缀.properties是默认的形式,当其他属性文件找不到的时候,会默认的寻找该属性文件。

  5.定义不同的资源文件

    (1)定义文件名:基名_国家代码_语言代码.properties,如果找不到该文件,则使用默认的文件名:基名.properties

    (2)定义不同的资源文件示例:

      中文的资源文件:

        文件名:resource_ch_CN.properties

        文件内容:item.username=张三

      英文的资源文件:

        文件名:resource_en_US.properties

        文件内容:item.username=zhangsan

      默认的资源文件:

        文件名:resource.properties

        文件内容:item.uername=username

  6.在struts.xml文件中注册

    使用的是struts.custom.i18n.resources,常量定义如下所示:

<constant name="struts.custom.i18n.resources" value="com.kdyzm.i18n.resource"></constant>

    其中value值中com.kdyzm.i18n.resource中的resource是基名,并不带国家代码和语言代码,也不带后缀名。

    这样一个注册语句就能够注册很多资源文件了。

  7.案例:国际化小练习。

 1 <?xml version="1.0" encoding="UTF-8"?>
 2  <!DOCTYPE struts PUBLIC
 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 4     "http://struts.apache.org/dtds/struts-2.3.dtd">
 5 <struts>
 6     <!-- 注意在注册国际化资源文件的时候使用的value值是资源文件的基名,而不是全名,而且不使用后缀名.properties -->
 7     <constant name="struts.custom.i18n.resources" value="com.kdyzm.i18n.resource"></constant>
 8     <package name="i18npackage" namespace="/i18n_space" extends="struts-default">
 9         <action name="i18n_test" class="com.kdyzm.i18n.I18nAction">
10             <result name="success">
11                 /02_i18n/success.jsp
12             </result>
13         </action>
14     </package>
15 </struts>

i18n_struts.xml

1 name=zhangsan

com.kdyzm.i18n.resource_zh_CN.properties

1 name=Danny

com.kdyzm.i18n.resource_en_US.properties

 1 package com.kdyzm.i18n;
 2
 3 import com.opensymphony.xwork2.ActionSupport;
 4
 5 public class I18nAction extends ActionSupport{
 6     private static final long serialVersionUID = -7378612320977074589L;
 7
 8     @Override
 9     public String execute() throws Exception {
10         System.out.println("访问了默认的测试方法!");
11         return "success";
12     }
13 }

com.kdyzm.i18n.I18nAction.java

 1 <%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8"
 2     contentType="text/html; charset=utf-8" %>
 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 5 <html>
 6   <head>
 7     <title>Insert title here !</title>
 8     <meta http-equiv="content-type" content="text/html;charset=utf-8">
 9   </head>
10
11   <body>
12     <a href="<c:url value=‘/i18n_space/i18n_test.action‘/>">测试</a>
13   </body>
14 </html>

/i18n/query.jsp

 1 <%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8"
 2     contentType="text/html; charset=utf-8" %>
 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 4 <%@ taglib uri="/struts-tags" prefix="s" %>
 5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 6 <html>
 7   <head>
 8     <title>Insert title here !</title>
 9     <meta http-equiv="content-type" content="text/html;charset=utf-8">
10   </head>
11
12   <body>
13     i18n测试成功!<br/>
14     姓名是:<s:text name="name"></s:text>
15   </body>
16 </html>

/i18n/success.jsp

  运行结果:使用IE浏览器进行测试,首先调整语言选项为:中文(zh_CN)

    

    

  然后调整为美国英文(en_US)

    

  由此可以得到国际化小案例已经成功了!

  8.配置文件中存在占位符的情况

1 name=zhangsan
2 password=zhangsan_mima
3 items={0},huan ying lai dao shandong!{1}

resource_zh_CN.properties

1 name=Danny
2 password=Danny_password
3 items={0},welcome to shandong!{1}

resouce_en_US.properties

  jsp核心代码测试区域:最关键的是<s:text>的使用方法。

  <s:text name="items">
        <s:param>
            <s:text name="name"></s:text>
        </s:param>
        <s:param>
            <s:text name="password"></s:text>
        </s:param>
    </s:text>

  运行结果:zh_CN:

    

    en_US:

    

  9.TextProvider接口

    (1)功能:提供对各种资源包和它们的底层文本消息的访问机制

    (2)当调用该接口的getText()方法的时候,它将按照一下顺序搜索相关的属性文件。

      * Action类的属性文件,该文件的名字和相关的动作类的名字相同,并且和那个动作类存放在同一个目录下。

      * 动作类所实现的各个接口的属性文件

      * 动作类的各个父类的属性文件

      * 动作类的各个父类所实现的各个接口的属性文件

      * 如果动作类实现了ModelDriven接口,Struts将会调用getModel()方法,并从模型对象的类开始沿着类的继承关系进行一次上溯搜索。

      * 默认的包的属性文件

      * 继承关系中的下个父包里的资源包

    (3)测试在Action中的方法中调用getText方法访问资源文件中的内容

      * 测试不带有占位符的getText方法

      String name=this.getText("name");
          System.out.println(name);

      * 测试带有占位符的getText方法

        String arr[]=new String[]{"张三","李四"};
        String temp=this.getText("items",arr);
        System.out.println(temp);

      运行结果:

      



四、解决.properties资源文件乱码问题

  1.JDK自带的工具:native2ascii

      使用方法:native2ascii -encoding gb2312 源文件 目标文件.properties

      使用这种方法能够解决中文乱码问题,但是非常麻烦,有什么好办法能比较简单的解决这个问题吗。

时间: 2024-10-07 18:44:52

【Java EE 学习第35天】【strus2】【类型转换器】【struts2和Servlet API解耦】【国际化问题】的相关文章

【Java EE 学习第16天】【dbcp数据库连接池】【c3p0数据库连接池】

零.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: 1 package day16.utils; 2 3 import java.io.IOException; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.sql.Connection; 8 import java.sql.D

Java EE学习--Quartz基本用法

新浪博客完全不适合写技术类文章.本来是想找一个技术性的博客发发自己最近学的东西,发现博客园起源于咱江苏,一个非常质朴的网站,行,咱要养成好习惯,以后没事多总结总结经验吧.很多时候都在网上搜索别人的总结,我自己也总结些东西,或许多多少少能帮得上别人. 首先提到的是Quartz,一个开源的定期执行计划任务的框架.其实我内心好奇这个框架很久了,像那些能定时修改数据库数据,定时分配任务的功能一直觉得很神奇.心动不如行动,今天我就小小的学习了一下用法,力求言简意赅,大家都懂的我就不说了. 第一步:下载Qu

Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库

参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Java EE 学习(6):IDEA + maven + spring 搭建 web(2) 5 数据库配置 下面,就要通过一个简单的例子,来介绍 SpringMVC 如何集成 Spring Data JPA(由 Hibernate JPA 提供),来进行强大的数据库访问,并通过本章节

JAVA EE 学习笔记[V1 jsp编程]

在三月初学校开设了javaee的课程,也就此展开了对javaee基础的学习.然后老师也对这次的课程有一定要求.前面的基础就为最终的作业做准备啦~ 在上学期我们学习了java相关知识,也对java se 的安装使用有了一定的认知,而java ee则是构建于java se 平台之上的一套多层的,可扩展的的网络应用. 学习java ee我们首先进行环境的搭建.无非就是使用 tomcat进行服务器的搭建和jdk环境变量配置.而IDE这方面我们选择myeclipse 2016 CI(这个编译器自带tomc

Java EE 学习(5):IDEA + maven + spring 搭建 web(1)

参考:http://www.cnblogs.com/lonelyxmas/p/5397422.html http://www.ctolib.com/docs-IntelliJ-IDEA-c--159047.html 孔老师的<SpringMVC视频教程> 记录: 本节主要完成 使用 maven 管理 spring + 项目 包,搭建 maven+spring 的 web 项目平台. 前提: 已安装并配置好 - Intellij IDEA 16.3.5 Ultimate - JDK 1.8.0_

Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理

转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库 记录: 通过对用户表的管理,更加深入地讲解SpringMVC的操作. 6 用户管理 既然我们

Java基础学习1-Java标识符及基本类型

暑假闲来无事,重新学习Java,希望能够加深自己对Java的理解与深入. 第一天,从Java标识符开始. Java标识符的命名规则 - 标识符必须以字母.下划线.美元符$开头. - 标识符其它部分可以是字母.下划线.美元符$和数字的任意组合. - Java标识符的大小写敏感,无长度限制(但是也不要太长,会变成裹脚布的(/ □ \)). - 不可以是Java的关键字(这点只要是有点基础的都会知道啦,Java的关键字还挺多的哦,小心踩到地雷呀). 下面是一个小栗子. /* *测试标识符的写法 */

Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理

转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Java EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库 Java EE 学习(8):IDEA + maven + spring 搭建 web(

Java EE学习之旅1——HeadFirstJavaEE

因为找到的实习是用Java开发的公司,所以来学习一下Java EE的知识. 首先找来了书<轻量级Java EE企业应用实战>. 啊不得不说学了Java之后直接看这个还是完全不行呢,好多名词看都没有看过啊哈哈. 首先来看看都些啥看不懂的词... 1.JSP.Servlet和JavaBean JSP和Servlet都是用在表现层的东西,而实质上JSP编译成Servlet才运行. 但Servlet开发成本太大,所以用JSP. JavaBean用来通信交换表现层和底层数据. 2.MVC和Struts