Spring MVC入门学习(四)
在SpringMVC框架中需要收集用户请求参数, 并将请求参数传递给应用的控制器组件. 此时存在一个问题, 即所有的请求参数类型只能是字符串数据类型, 但java是强类型语言, 所以Spring MVC框架必须将这些字符串请求参数转换成相应的数据类型.
SpringMVC框架不仅提供了强大的类型转换和格式化机制, 而且开发者还可以方便地开发自己的类型转换器和格式化转换器.
Spring MVC框架的Converter<S, T>是一个可以将一种数据类型转换成另一种数据类型的接口, 这里的S表示源类型, T表示目标类型. 开发者在实际应用中使用框架内置的类型转换器基本上就够了, 但有时需要编写具有特定功能的类型转换器.
类型转换是在视图和控制器相互传递数据时发生的. Spring MVC 框架对于基本类型已经做好了基本类型转换.
web.xml的配置不再赘述
springmvc-servlet.xml, 配置注解
index.jsp
<%--
Created by 年少、.
User: nianshao
Date: 19-11-9
Time: 下午2:05
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="UTF-8">
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/index/buy">
商品名称: <input type="text" name="name"><br>
商品价格: <input type="text" name="price"><br>
商品数量: <input type="text" name="number"><br>
<input type="submit" value=提交""><br>
</form>
</body>
</html>
BuyController
package cn.lacknb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/index")
public class BuyController {
@RequestMapping("/buy")
public String buy(String name, double price, int number){
System.out.println("商品名字:" + name);
System.out.println("商品价格:" + price);
System.out.println("商品数量:" + number);
return "/success.jsp";
}
}
在使用内置类型转换器时, 请求参数输入值与接收参数类型要兼容, 否则会报400错误. 请求参数类型与接收参数类型不兼容问题需要学习输入校验后才可解决.
例如有一个应用希望用户在页面表单中输入信息来创建商品信息, 当输入 "apple, 10.58 ,200"时,表示在程序中会自动创建一个new Goods(商品实体类), 并将apple值自动赋给goodsname属性...
package cn.lacknb.beans;
public class GoodsModel {
private String goodsname;
private double goodsprice;
private int goodsnumber;
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;
}
@Override
public String toString() {
return "GoodsModel{" +
"goodsname='" + goodsname + '\'' +
", goodsprice=" + goodsprice +
", goodsnumber=" + goodsnumber +
'}';
}
}
package cn.lacknb.controller;
import cn.lacknb.beans.GoodsModel;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/index")
public class ConverterController {
@RequestMapping("/buy")
public String buy(@RequestParam("goods") GoodsModel goods, Model model){
model.addAttribute("goods", goods);
return "/showGoods.jsp";
}
}
package cn.lacknb.converter;
/*
* 创建自定义类型转换类
*
* */
import cn.lacknb.beans.GoodsModel;
import org.springframework.core.convert.converter.Converter;
public class GoodsConverter implements Converter<String, GoodsModel> {
@Override
public GoodsModel convert(String s) {
// 创建一个Goods实例
GoodsModel goods = new GoodsModel();
// 以 , 为分割
String stringValues[] = s.split(",");
if (stringValues != null && stringValues.length == 3){
// 为Goods实例赋值
goods.setGoodsname(stringValues[0]);
goods.setGoodsprice(Double.parseDouble(stringValues[1]));
goods.setGoodsnumber(Integer.parseInt(stringValues[2]));
return goods;
}else{
throw new IllegalArgumentException(String.format("类型转换失败, 需要格式 'applce, 10.58, 200', 但格式是[%s]", s));
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="cn.lacknb"/>
<!--注册类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="cn.lacknb.converter.GoodsConverter"/>
</list>
</property>
</bean>
<!--ConversionSerivce的作用是把接收的参数以什么“类型”呈现出来。前端传递什么参数我们后台以什么形势接收它们-->
<mvc:annotation-driven conversion-service="conversionService"/>
</beans>
<%--
Created by 年少、.
User: nianshao
Date: 19-11-9
Time: 下午2:05
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="UTF-8">
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/index/buy">
<%-- 商品名称: <input type="text" name="goodsname"><br>--%>
<%-- 商品价格: <input type="text" name="goodsprice"><br>--%>
<%-- 商品数量: <input type="text" name="goodsnumber"><br>--%>
请输入商品信息:(格式[不能有空格]: apple,10.58,200)
<input type="text" name="goods"/><br>
<input type="submit" value="提交"><br>
</form>
</body>
</html>
<%--
Created by 年少、.
User: nianshao
Date: 19-11-9
Time: 下午2:36
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="UTF-8">
<head>
<title>Title</title>
</head>
<body>
商品名称为: ${goods.goodsname}<br>
商品价格为: ${goods.goodsprice}<br>
商品数量为: ${goods.goodsnumber}
</body>
</html>
Spring NVC框架的Formatter
Formatter
public T parse(String s, java.util.Locale locale);
public String print(T object, java.util.Locale locale);
parse方法的功能是利用指定的Locale讲一个String类型转换成目标类型, print方法与之相反. 用户返回目标对象的字符串表示.
GoodModelb
package cn.lacknb.beans;
import java.util.Date;
public class GoodsModelb {
private String goodsname;
private double goodsprice;
private int goodsnumber;
private Date goodsdate;
public Date getGoodsdate() {
return goodsdate;
}
public void setGoodsdate(Date goodsdate) {
this.goodsdate = goodsdate;
}
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;
}
@Override
public String toString() {
return "GoodsModel{" +
"goodsname='" + goodsname + '\'' +
", goodsprice=" + goodsprice +
", goodsnumber=" + goodsnumber +
'}';
}
}
FormatterController
package cn.lacknb.controller;
import cn.lacknb.beans.GoodsModelb;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/index")
public class FormatterController {
@RequestMapping("/buy")
public String buy(GoodsModelb goodsModelb, Model model){
model.addAttribute("goods", goodsModelb);
return "/showGoods.jsp";
}
}
GoodsFormatter
package cn.lacknb.converter.formatter;
import org.springframework.format.Formatter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class GoodsFormatter implements Formatter<Date> {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
@Override
public Date parse(String s, Locale locale) throws ParseException {
return dateFormat.parse(s); // Formatter只能对字符串进行转换
}
/*
* SimpleDateFormat 中有两个方法parse()个format()
* parse() 是将字符串转换成Date类型
* format() 是将date类型转成字符串类型
*
* */
@Override
public String print(Date date, Locale locale) {
return dateFormat.format(date);
}
}
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<list>
<bean class="cn.lacknb.converter.formatter.GoodsFormatter"/>
</list>
</property>
</bean>
<mvn:annotation-driven conversion-service="conversionService"/>
index.jsp
<%--
Created by 年少、.
User: nianshao
Date: 19-11-9
Time: 下午4:19
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="UTF-8">
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/index/buy" method="post">
商品名称: <input type="text" name="goodsname"/><br>
商品价格: <input type="text" name="goodsprice"/><br>
商品数量: <input type="text" name="goodsnumber"/><br>
商品日期: <input type="text" name="goodsdate"/>(yyyy-mm-dd)<br>
<input type="submit" value="提交"/><br>
</form>
</body>
</html>
showGoods.jsp
<%--
Created by 年少、.
User: nianshao
Date: 19-11-9
Time: 下午2:36
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="UTF-8">
<head>
<title>Title</title>
</head>
<body>
商品名称为: ${goods.goodsname}<br>
商品价格为: ${goods.goodsprice}<br>
商品数量为: ${goods.goodsnumber}<br>
商品日期为: ${goods.goodsdate}
</body>
</html>
有了数据绑定之后就不再需要手动将Http请求中的String类型转换为模型需要的类型. 数据绑定的另一个好处就是当输入验证失败时会重新生成一个HTML表单, 无须重新填写输入字段.
在SpringMVC中框架中数据绑定有这样几层含义: 绑定请求参数输入值到领域模型、模型数据到视图的绑定(输入验证失败时)、模型数据到表单元素的绑定.
一定要导入jstl的jar包
首先必须在jsp页面开头处声明taglib命令
<%@ taglib prefix="form" url="http://www.springframework.org/form" %>
.............................................