springmvc中的数据绑定
springmvc的数据绑定
简单数据类型的数据绑定
- 对于java默认的数据类型:如String
- 对于pojo的数据绑定
- 对于其他类型的数据绑定(如String->Date):需要自定义类型装换器,实现Converter接口即可
- 对于httpServletRequest等默认的数据类型
package com.chen.controller;
import com.chen.pojo.School;
import com.chen.pojo.User;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Date;
import java.util.List;
@Controller
public class TestController {
/**
* 对于简单类型的数据绑定
* 对于简单数据类型的数据绑定,都要求请求端数据要以key-value的形式
* */
//对于java基本数据类型的绑定(请求端的数据格式必须为key-value的形式才能接收)
@RequestMapping("/base")
public String test(String username, Model model){
model.addAttribute("username",username);
System.out.println(username);
String[] split = username.split(",");
for (String s : split) {
System.out.println(s);
}
return "index";
}
//对于pojo的绑定(请求端的数据格式必须为key-value的形式才能接收)
@RequestMapping("/pojo")
public String test1(User user,Model model){
model.addAttribute("user",user);
return "index";
}
//对于不是java基本类型需要自定义类型转换(请求端的数据格式必须为key-value的形式才能接收)
@RequestMapping("/date")
public String test2(Date date,Model model){
model.addAttribute("date",date);
return "index";
}
//使用@DateTimeFormat来实现String->Date的类型装换
@RequestMapping("/date1")
public String test3(@DateTimeFormat(pattern = "YYYY-MM-dd") Date date, Model model){
model.addAttribute("date",date);
return "index";
}
}
自定义数据类型装换器(日期)
package com.chen.converent;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String, Date> {
String pattern = "YYYY-MM-dd";
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date parseDate = null;
try {
parseDate = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return parseDate;
}
}
<!-- 添加类型转换器-->
<!-- 在ConversionServiceFactoryBean中注入自定义的类型转换器 -->
<!-- 在这里ConversionServiceFactoryBean可以替换成FormattingConversionServiceFactoryBean,效果也是一样的 -->
<bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<array>
<bean class="com.chen.converent.DateConverter"/>
</array>
</property>
</bean>
<!-- 在mvc中注入ConversionServiceFactoryBean -->
<mvc:annotation-driven conversion-service="converterService"/>
-
Converter接口
-
/* * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.core.convert.converter; import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** * A converter converts a source object of type {@code S} to a target of type {@code T}. * * <p>Implementations of this interface are thread-safe and can be shared. * * <p>Implementations may additionally implement {@link ConditionalConverter}. * * @author Keith Donald * @author Josh Cummings * @since 3.0 * @param <S> the source type * @param <T> the target type */ @FunctionalInterface public interface Converter<S, T> { /** * Convert the source object of type {@code S} to target type {@code T}. * @param source the source object to convert, which must be an instance of {@code S} (never {@code null}) * @return the converted object, which must be an instance of {@code T} (potentially {@code null}) * @throws IllegalArgumentException if the source cannot be converted to the desired target type */ @Nullable T convert(S source); /** * Construct a composed {@link Converter} that first applies this {@link Converter} * to its input, and then applies the {@code after} {@link Converter} to the * result. * @param after the {@link Converter} to apply after this {@link Converter} * is applied * @param <U> the type of output of both the {@code after} {@link Converter} * and the composed {@link Converter} * @return a composed {@link Converter} that first applies this {@link Converter} * and then applies the {@code after} {@link Converter} * @since 5.3 */ default <U> Converter<S, U> andThen(Converter<? super T, ? extends U> after) { Assert.notNull(after, "After Converter must not be null"); return (S s) -> { T initialResult = convert(s); return (initialResult != null ? after.convert(initialResult) : null); }; } } -
T泛型指需要装换的目标类型,S泛型指原类型
-
对于复杂类型的数据绑定
- 数组(String[])
- 集合(List<Sting,String>)
- 复杂pojo
- 有pojo
- 有list
- 有map
- json(需要导入jackson的核心包)
package com.chen.controller;
import com.chen.pojo.School;
import com.chen.pojo.User;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Date;
import java.util.List;
@Controller
public class TestController {
/**
* 对于复杂类型的数据绑定
* */
//对于多个同名属性的值得绑定(请求端的数据格式必须为key-value的形式才能接收)
@RequestMapping("/array")
public String test4(String[] usernames,Model model){
model.addAttribute("usernames",usernames);
for (String username : usernames) {
System.out.println(username);
}
return "index";
}
//对于集合的绑定(也要求请求端数据以key-value的形式,且必须要有@RequestParam注解)
@RequestMapping("/list")
public String test5(@RequestParam List<String> usernameList, Model model){
System.out.println(usernameList);
model.addAttribute("usernameList",usernameList);
return "index";
}
//对于复杂的pojo的数据绑定(请求端参数以key-value)
//属性中有其他类
//对于url参数中文不会乱码,但是对于body中的参数会出现中文乱码
@RequestMapping("/fuzapojo")
public String test6(School school,Model model){
System.out.println(school.getAddress());
System.out.println(school.getUser().getPassword());
System.out.println(school.getUser().getUsername());
model.addAttribute("school",school);
return "index";
}
//属性中有List集合
//对于url参数中文不会乱码,但是对于body中的参数会出现中文乱码
@RequestMapping("/fuzapojolist")
public String test7(School school,Model model){
model.addAttribute("fuzapojolist",school);
return "index";
}
//属性中有Map集合
//对于url参数中文不会乱码,但是对于body中的参数会出现中文乱码
@RequestMapping("/fuzapojomap")
public String test8(School school,Model model){
model.addAttribute("fuzapojomap",school);
return "index";
}
//对于接收json,springmvc中要导入jsckson的包,且在参数前面需要加上@RequestBody
//MappingJackson2HttpMessageConverter来解析json并绑定到参数上,也可以将返回值转换成json作为响应
@RequestMapping("/json")
public String test9(@RequestBody User user, Model model){
model.addAttribute("jsonUser",user);
return "index";
}
}
-
jackson的核心包
-
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency>
-
HttpMessageConverter接口:将请求消息中的报文数据转换成指定的对象(常用的有MappingJackson2HttpMessageConverter的json消息转换器)
与前面的类型转换器Converter接口不同
/*
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.converter;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
* Strategy interface for converting from and to HTTP requests and responses.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @since 3.0
* @param <T> the converted object type
*/
public interface HttpMessageConverter<T> {
/**
* Indicates whether the given class can be read by this converter.
* @param clazz the class to test for readability
* @param mediaType the media type to read (can be {@code null} if not specified);
* typically the value of a {@code Content-Type} header.
* @return {@code true} if readable; {@code false} otherwise
*/
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
/**
* Indicates whether the given class can be written by this converter.
* @param clazz the class to test for writability
* @param mediaType the media type to write (can be {@code null} if not specified);
* typically the value of an {@code Accept} header.
* @return {@code true} if writable; {@code false} otherwise
*/
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
/**
* Return the list of media types supported by this converter. The list may
* not apply to every possible target element type and calls to this method
* should typically be guarded via {@link #canWrite(Class, MediaType)
* canWrite(clazz, null}. The list may also exclude MIME types supported
* only for a specific class. Alternatively, use
* {@link #getSupportedMediaTypes(Class)} for a more precise list.
* @return the list of supported media types
*/
List<MediaType> getSupportedMediaTypes();
/**
* Return the list of media types supported by this converter for the given
* class. The list may differ from {@link #getSupportedMediaTypes()} if the
* converter does not support the given Class or if it supports it only for
* a subset of media types.
* @param clazz the type of class to check
* @return the list of media types supported for the given class
* @since 5.3.4
*/
default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
return (canRead(clazz, null) || canWrite(clazz, null) ?
getSupportedMediaTypes() : Collections.emptyList());
}
/**
* Read an object of the given type from the given input message, and returns it.
* @param clazz the type of object to return. This type must have previously been passed to the
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
*/
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/**
* Write an given object to the given output message.
* @param t the object to write to the output message. The type of this object must have previously been
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
* default content type of the converter must be used. If not {@code null}, this media type must have
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
* returned {@code true}.
* @param outputMessage the message to write to
* @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors
*/
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
对于http中的参数类型
- 请求头中的参数
- url参数:key-value形式的
- 请求体中的参数
- 表单形式的(常用于文件上传)(form-data)
- key-value形式的(x-www-form-urlencoded)
- raw
- json
- xml
- javascript
- plain
- html
对于以上的数据绑定,get请求能提交url中的参数,但是body中的参数不会提交,且不会中文乱码;post请求能提交body中的参数,如果url中也有参数,全部可以提交,但是body中的会出现中文乱码,url中的不会。
-
(post请求)对于body中的参数乱码解决:在web.xml中注册spring中的CharacterEncodingFilter类来过滤乱码
-
<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> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
-
(get请求) 对于url中的参数乱码解决:在使用参数之前对参数进行重新编码(ISO8859-1是tomcat的默认编码,需要将tomcat编码后的参数以UTF-8重新编码)
-
String param new String(param.getBytes("ISO8859-1"),"UTF-8")
-
浙公网安备 33010602011771号