Spring 学习小记(十三)

68 篇文章 0 订阅
Spring MVC 类型转换与格式化
 
本小记学习目标
  1. 类型转换和格式化的介绍
  1. Converter的使用介绍
  1. Formatter的使用介绍
 
一、类型转换和格式化的介绍
在Spring MVC框架中需要收集用户的请求参数,并把请求的参数传递给到控制器,这里会存在一个小问题,这种方式中所有的请求参数类型只能是字符串类型,但是Java是强类型语言,所以Spring MVC中相应地提供了把这些字符串请求参数转换成相应的数据类型的功能。
 
Converter
Spring MVC 中的Converter<S,T>是一种可以把一种数据类型转换成另一种数据类型的接口,S表示源类型,T表示目标类型
Spring MVC中内置类型转换器
对于常用的类据类型,开发者不用创建自己的类型转换器,Spring MVC框架提供了如下几种内置类型转换器
1.标量转换器
类型
说明
StringToBooleanConverter
String--->boolean
ObjectToStringConverter
Object--->String,调用的是toString方法转换
StringToNumberConverterFactory
String---->数字(Integer、Long……)
NumberToNumberConverterFactory
基本数字类型--->数字包装类型
StringToCharacterConverter
String--->Character
NumberToCharacterConverter
基本数字类型--->Character
CharacterToNumberFactory
Character--->基本数字类型
StringToEnumConverterFactory
String--->枚举类型,通过Enum.valueOf把字符串转为需要的枚举类型
StringToLocaleConverter
String--->java.util.Locale
PropertiesToStringConverter
Properties--->String,默认通过ISO-8859-1编码
StringToPropertiesConverter
String--->Properties转换,默认使用ISO-8859-1编码
2.集合、数组相关转换器
类型
说明
ArrayToCollectionConverter
任意数组--->任意集合(List、Set)转换
CollectionToArrayConverter
任意集合(List、Set)--->任意数组转换
ArrayToArrayConverter
任意数组--->任意数组
CollectionToCollectionConverter
任意集合--->任意集合
MapToMapConverter
Map--->Map
ArrayToStringConverter
任意数组--->String
StirngToArrayConverter
String--->数组,默认通过“,”进行分隔,去掉字符串两边的空格
ArrayToObjectConverter
任意数组--->Object,如果目标类型与源类型兼容,直接返回源对象,否则返回数组第一个元素进行类型转换
ObjectToArrayConverter
Object--->单元素数组
CollectionToStringConverter
任意集合(List、Set)--->String
StringToCollectionConverter
String--->集合(List、Set),默认通过“,”进行分隔,去掉字符串两边的空格
CollectionToObjectConverter
任意集合--->Object,如果目标类型与源类型兼容,直接返回源对象,否则返回集合第一个元素进行类型转换
ObejctToCollectionConverter
Object--->单元素集合
类型转换发生的时机:在视图与控制器转递数据时发生。
Spring MVC对于基本类型(int,long,float,double,boolean,char……)做好了基本类型转换,但是在类型上要做到兼容。
 
自定义类型转换器
例如:在表单中输入商品信息,“杯具1,128.00,100”--->自动创建一个Goods对象,并且把"杯具1"=》goodsName;"128.00"=》goodsPrice;"100"=>goodsNumber
 
Eclipse中新增一个Maven的war工程
右建工程Build Path..,把web工程的Server Runtime加入进来
pom.xml中添加如下jar包依赖
< dependencies >
       <!-- context -->
       < dependency >
             < groupId >org.springframework </ groupId >
             < artifactId >spring-context </ artifactId >
             < version >5.0.2.RELEASE </ version >
       </ dependency >
    <!-- Spring MVC -->
    < dependency >
       < groupId >org.springframework </ groupId >
       < artifactId >spring- webmvc </ artifactId >
       < version >5.0.2.RELEASE </ version >
    </ dependency >
   
    <!-- Spring web -->
    < dependency >
       < groupId >org.springframework </ groupId >
       < artifactId >spring-web </ artifactId >
       < version >5.0.2.RELEASE </ version >
       </ dependency >
   
    <!-- commons-logging -->
    < dependency >
       < groupId >commons-logging </ groupId >
       < artifactId >commons-logging </ artifactId >
       < version >1.2 </ version >
    </ dependency >
   
    <!-- spring- aop -->
    < dependency >
       < groupId >org.springframework </ groupId >
       < artifactId >spring- aop </ artifactId >
       < version >5.0.2.RELEASE </ version >
    </ dependency >
   
       < dependency >
       < groupId >javax.servlet </ groupId >
       < artifactId > jstl </ artifactId >
       < version >1.2 </ version >
       </ dependency >
</ dependencies >
 
创建实体类:com.xiaoxie.pojo.GoodsModel
package com.xiaoxie.pojo;
/**
 * 类型转换中使用到的实体类
 * @author adven
 *
 */
public class GoodsModel {
       private String goodsName;
       private double goodsPrice;
       private int goodsNumber;
      
       //getter和setter
       public String getGoodsName() {
             return goodsName;
      }
       public void setGoodsName(String goodsName) {
             this. goodsName = goodsName;
      }
       public double getGoodsPrice() {
             return goodsPrice;
      }
       public void setGoodsPrice( double goodsPrice) {
             this. goodsPrice = goodsPrice;
      }
       public int getGoodsNumber() {
             return goodsNumber;
      }
       public void setGoodsNumber( int goodsNumber) {
             this. goodsNumber = goodsNumber;
      }
      
       //toString
       @Override
       public String toString() {
             return "GoodsModel[goodsName=" + goodsName + ",goodsPrice=" + goodsPrice + ",goodsNumber=" + goodsNumber + "]";
      }
      
}
 
创建控制器类com.xiaoxie.controller.ConverterController
package com.xiaoxie.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.xiaoxie.pojo.GoodsModel;
@Controller
@RequestMapping( "/my")
public class ConverterController {
       @RequestMapping( "/converter")
       public String myConverter( @RequestParam( "goods") GoodsModel gm,Model model) {
             model.addAttribute( "goods", gm);
             return "show_goods";
      }
}
 
自定义类型转换器类:com.xiaoxie.converter.GoodsConverter
package com.xiaoxie.converter;
import org.springframework.core.convert.converter.Converter;
import com.xiaoxie.pojo.GoodsModel;
public class GoodsConverter implements Converter<String,GoodsModel> {
       @Override
       public GoodsModel convert(String arg0) {
             //创建一个GoodsModel的实例
            GoodsModel gm = new GoodsModel();
            String stringValue[] = arg0.split( ",");
             //判断StringValue中的值
             if( stringValue != null && stringValue. length == 3) {
                   //为 gm 这个对象进行属性赋值
                   gm.setGoodsName( stringValue[0]);
                   gm.setGoodsPrice(Double. parseDouble( stringValue[1]));
                   gm.setGoodsNumber(Integer. parseInt( stringValue[2]));
                   return gm;
            } else {
                   throw new IllegalArgumentException(String. format( "类型转换失败,需要格式:'商品名,100.00,1',但提供格式为:%s", arg0));
            }
      }
}
 
添加Spring MVC的配置文件springmvc.xml
<? xml version= "1.0" encoding= "UTF-8" ?>
       xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context= "http://www.springframework.org/schema/context"
       xmlns:mvc= "http://www.springframework.org/schema/mvc"
       <!-- 配置spring要自动扫描的包 -->
       < context:component-scan base-package= "com.xiaoxie.controller" />
       <!-- 注册类型转换器GoodsConverter -->
       < bean class= "org.springframework.context.support.ConversionServiceFactoryBean" id= "conversionServiceFactoryBean" >
             < property name= " converters" >
                   < list >
                         < bean class= "com.xiaoxie.converter.GoodsConverter" />
                   </ list >
             </ property >
       </ bean >
      
       < mvc:annotation-driven conversion-service= "conversionServiceFactoryBean" />
       <!-- 配置视图解析器 -->
       < bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver" id= "viewResolver" >
             <!-- 拼接前缀 -->
             < property name= " prefix" value= "/WEB-INF/jsp/" />
             <!-- 拼接后缀 -->
             < property name= " suffix" value= ".jsp" />
       </ bean >
</ beans >
 
配置web.xml文件,主要是配置DispatcherServlet
<? xml version= "1.0" encoding= "UTF-8" ?>
<!-- DispatcherServlet配置 -->
< servlet >
       < servlet-name > springmvc </ servlet-name >
       < servlet-class >org.springframework.web.servlet.DispatcherServlet </ servlet-class >
       <!-- 加载spring mvc 的配置文件 -->
       < init-param >
                   < param-name >contextConfigLocation </ param-name >
                   <!-- 配置SpringMVC配置文件的路径 -->
                   < param-value >classpath:springmvc.xml </ param-value >
       </ init-param >
       <!-- tomcat 容器在启动时加载 servlet -->
       < load-on-startup >1 </ load-on-startup >
</ servlet >
< servlet-mapping >
       < servlet-name > springmvc </ servlet-name >
       <!-- servlet 处理请求地址,这里/表示所有 url -->
       < url-pattern >/ </ url-pattern >
</ servlet-mapping >
       <!-- 配置解决 psot 请求中文乱码问题 -->
       < filter >
             < filter-name >CharacterEncodingFilter </ filter-name >
             < filter-class >org.springframework.web.filter.CharacterEncodingFilter </ filter-class >
             < init-param >
                   < param-name >encoding </ param-name >
                   < param-value > utf-8 </ param-value >
             </ init-param >
             < init-param >
                   < param-name >forceEncoding </ param-name >
                   < param-value >true </ param-value >
             </ init-param >
       </ filter >
       < filter-mapping >
             < filter-name >CharacterEncodingFilter </ filter-name >
             < url-pattern >/* </ url-pattern >
       </ filter-mapping >
</ web-app >
 
新增一个index/input的Controller请求的Controller:com.xiaoxie.controller.IndexController
package com.xiaoxie.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping( "index")
public class IndexController{
       @RequestMapping( "input")
       public String input() {
             return "input";
      }
}
注意:这个controller只做了一个跳转不做任何处理,它经过视图解析器处理后跳转到/WEB-INF/jsp/input.jsp
 
新增index.jsp,在WebContent目录下
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
    pageEncoding= "UTF-8" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title >Insert title here </ title >
</ head >
< body >
      录入商品信息: < a href= "${pageContext.request.contextPath } /index/input" >录入 </ a >< br />
</ body >
</ html >
 
在/WEB-INF/jsp/目录下新增input.jsp
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
    pageEncoding= "UTF-8" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title >Insert title here </ title >
</ head >
< body >
       < form action= "${pageContext.request.contextPath } /my/converter" method= "post" >
            请输入商品信息(格式:商品名1,100.00,1):
             < input type= "text" name= "goods" >< br />
             < input type= "submit" value= "提交" />
       </ form >
</ body >
</ html >
 
在/WEB-INF/jsp/目录下新增show_goods.jsp
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
    pageEncoding= "UTF-8" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title >Insert title here </ title >
</ head >
< body >
      创建商品信息如下: < br />
       <!-- 使用model绑定的对象展示相关信息 -->
      商品名称:${goods.goodsName } < br />
      商品价格:${goods.goodsPrice } < br />
      商品数量:${goods.goodsNumber }
</ body >
</ html >
 
运行项目打开index.jsp,点击对应的链接---->input.jsp---->录入信息---->show_goods.jsp
注意:在类型转换的过程中如报错我们看到Throw了一个异常,这个时候项目会出现400的异常页面
 
Formatter
Spring MVC框架中Formatter<T>与Converter<S,T>一样,也是一个可以把一种数据类型转为另一种数据类型的接口,这里注意它没有S(源类型),只有T(目标类型),这里的源类型必须要是String类型。
现论上Converter就可以覆盖到Formatter那为什么还有一个Formatter呢?
在Web项目中HTTP请求发送的数据到控制器中都是以String类型获取的,因而在Web项目中使用Formatter比Converter更合理。
Spring MVC提供的内置转换器
类型
说明
NumberFormatter
Number与String之间的解析与格式化
CurrencyFormatter
带货币符号的Number与String之间的解析与格式化
PercentFormatter
带百分符号的Number与String之间的解析与格式化
DateFormatter
Date与String之间的解析与格式化
自定义格式转换器
自定义格式转换器需要编写一个实现org.springframework.format.Formatter接口的Java类
这个接口有parse和print两个接口方法,在自定义的实现类中需要覆盖
parse方法:利用指定的Locale把一个String类型转换为目标类型
print方法:用于返回目标对象的字符串表示
在工程中新增一个实体Model:com.xiaoxie.pojo.EmployeeModel
package com.xiaoxie.pojo;
import java.util.Date;
public class EmployeeModel {
       private String workNo;
       private String name;
       private Date joinDate;
       private double salary;
       private String position;
      
       /*getter,setter*/
       public String getWorkNo() {
             return workNo;
      }
       public void setWorkNo(String workNo) {
             this. workNo = workNo;
      }
       public String getName() {
             return name;
      }
       public void setName(String name) {
             this. name = name;
      }
      
       public Date getJoinDate() {
             return joinDate;
      }
       public void setJoinDate(Date joinDate) {
             this. joinDate = joinDate;
      }
       public double getSalary() {
             return salary;
      }
       public void setSalary( double salary) {
             this. salary = salary;
      }
       public String getPosition() {
             return position;
      }
       public void setPosition(String position) {
             this. position = position;
      }
      
       @Override
       public String toString() {
             return "Employee[工号=" + workNo + ",姓名=" + name + ",职位=" + position + ",入职日期=" + joinDate + ",工资=" + salary + "]";
      }
}
 
新增一个自定义的转换器:com.xiaoxie.converter.MyFormatter
package com.xiaoxie.converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.springframework.format.Formatter;
public class MyFormatter implements Formatter<Date> {
       //使用记录日志的对象
       private static final Log logger = LogFactory. getLog(MyFormatter. class);
       //做日期格式化使用SimpleDateFormat
       private SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
       @Override
       public String print(Date object, Locale locale) {
             return sdf.format( object);
      }
       @Override
       public Date parse(String text, Locale locale) throws ParseException {
             logger.info( "把字符串转为Date对象");
             return sdf.parse( text);
      }
}
 
把转换器注册到Spring MVC,在Spring MVC的配置文件中新增如下内容
<!-- 注册Formatter -->
       < bean class= "org.springframework.format.support.FormattingConversionServiceFactoryBean" id= "formattingConversionServiceFactoryBean" >
             < property name= " formatters" >
                   < set >
                         < bean class= "com.xiaoxie.converter.MyFormatter" ></ bean >
                   </ set >
             </ property >
       </ bean >
< mvc:annotation-driven conversion-service= "formattingConversionServiceFactoryBean" />
 
新增EmployeeController,com.xiaoxie.controller.EmployeeController
package com.xiaoxie.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.xiaoxie.pojo.EmployeeModel;
@Controller
@RequestMapping( "/employee")
public class EmployeeController {
       @RequestMapping( "/create")
       public String createEmp(EmployeeModel em,Model model) {
             model.addAttribute( "employee", em);
             return "show_emp";
      }
}
从这里可以看到当请求/employee/create时会转发到视图 show_emp.jsp
 
对IndexController进行修改,提供一个请求,便于转发到员工信息录入界面,其中添加方法如下
@RequestMapping( "/input_emp")
       public String inputEmp() {
             return "input_emp";
      }
 
修改index.jsp(WebContent下)
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
    pageEncoding= "UTF-8" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title >Insert title here </ title >
</ head >
< body >
      录入商品信息: < a href= "${pageContext.request.contextPath } /index/input" >录入 </ a >< br />
       < hr />
      录入员工信息: < a href= "${pageContext.request.contextPath } /index/input_emp" >录入 </ a >< br />
</ body >
</ html >
 
新增input_emp.jsp(根据我们配置在spirngmvc的配置文件的视图解析器可知我们要配置到/WEB-INF/jsp/input_emp.jsp)
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
    pageEncoding= "UTF-8" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title >Insert title here </ title >
</ head >
< body >
       < form action= "${pageContext.request.contextPath } /employee/create" method= "post" >
            工号: < input type= "text" name= "workNo" /> < br />
            姓名: < input type= "text" name= "name" /> < br />
            入职日期: < input type= "text" name= "joinDate" />( yyyy-MM- dd) < br />
            职位: < input type= "text" name= "position" /> < br />
            工资: < input type= "text" name= "salary" /> < br />
             < input type= "submit" value= "录入" />
       </ form >
</ body >
</ html >
 
新增show_emp.jsp(根据我们配置在spirngmvc的配置文件的视图解析器可知我们要配置到/WEB-INF/jsp/show_emp.jsp)
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
    pageEncoding= "UTF-8" %>
<%@ taglib prefix= "fmt" uri= "http://java.sun.com/jsp/jstl/fmt" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title >Insert title here </ title >
</ head >
< body >
      您录入的员工信息如下: < br />
      工号:${employee.workNo } < br />
      姓名:${employee.name } < br />
      入职日期: < fmt:formatDate value= "${employee.joinDate } " pattern= "yyyy-MM-dd" />< br />
      职位:${employee.position } < br />
      工资:${employee.salary } < br />
</ body >
</ html >
程序运行时我们可以看到,在提交员工信息时要转为一个EmployeeModel对象,这个时候会调用自定义的Formatter类进行字符串转Date的动作,且在控制台可以看到打印出来的信息: 信息: 把字符串转为Date对象
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值