• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
在赶路的我
博客园    首页    新随笔    联系   管理    订阅  订阅

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")
      
posted @ 2023-02-26 16:10  在赶路的我  阅读(90)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3