SpringMVC

处理提交过来的数据

提交的域名称与方法中的参数名一致

  • 没啥说的,自动封装
http://localhost:8081/springmvc_2/sout?name=APP&phone=1008611
@RequestMapping("sout")
public String test(String name,String phone){
    System.out.println(name);
    System.out.println(phone);
    //不进行任何操作
    return null;
}
//输出APP	 1008611

提交的域名称与方法中的参数名不一致

  • 如果取请求过来的name与方法中的参数名不一致,就不能封装上,为NULL

  • 使用@RequestParam注解,将域名称与方法参数进行绑定

http://localhost:8081/springmvc_2/sout?uuu=PPP&ppp=121212
@RequestMapping("sout")
public String test(@RequestParam("uuu") String name, @RequestParam("ppp") String phone){
    System.out.println(name);
    System.out.println(phone);
    //不进行任何操作
    return null;
}

提交一个对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String pwd;
}
http://localhost:8081/springmvc_2/login?id=123&name=Poer&pwd=123
@RequestMapping("login")
public String login(User user){
    System.out.println(user);
    return null;
}

提交的域名城要与封装的实体类属性名一致,不然为null

自定义工具类实现对象自动封装

  • 工具类
package com.mlyr.d;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
 * @Author 陌路邑人
 * @Date
 * @Project
 */
public class MapUtils {
    public static Object MapToObject(Map<String, String[]> parameterMap, Class clazz) {
        Set<String> keySet = parameterMap.keySet();//先获取map集合的所有key
        Iterator<String> iterator = keySet.iterator();//迭代这个key
        Object o = null;
        try {
            o = clazz.newInstance();
            while (iterator.hasNext()){
                String key = iterator.next();//获取map的key
                Field field = clazz.getDeclaredField(key);//根据key值找到要封装的类对应的属性
                field.setAccessible(true);//打破封装
                String[] values = parameterMap.get(key);//根据key获取value
                Class<?> type = field.getType();//获取属性的数据类型
                //根据属性的数据类型不同,转换与之对应的数据类型进行封装
                if (type==Integer.class){
                    field.set(o,Integer.parseInt(values[0]));
                }else{
                    field.set(o,values[0]);
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return o;
    }
}
  • controller
@RequestMapping("login")
public String login(HttpServletRequest request, HttpServletResponse response){
    //获取请求参数map
    Map<String, String[]> parameterMap = request.getParameterMap();
    //自定义对象封装
    User user = (User)MapUtils.MapToObject(parameterMap,User.class);
    System.out.println(user);
    return null;
}

处理请求中的时间类型数据

  • 首先会报错,Field error in object 'user' on field 'date': rejected value [2021-03-03]; codes [typeMismatch.user.date,typeMismatch.date,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.date,date]; arguments []; default message [date]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'date'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2021-03-03'; nested exception is java.lang.IllegalArgumentException]]

第一种解决方案

  • 需要自定义一个类来处理全局的日期转换,把页面请求过来的字符串转换为Date类型的数据
package com.mlyr.f;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * @Author 陌路邑人
 * @Date
 * @Project  日期转换
 */
public class DateConvert implements Converter<String, Date> {
    String format1 = "yyyy-MM-dd";
    String format2 = "yyyy/MM/dd";
    SimpleDateFormat format = null;
    @Override
    public Date convert(String source) {
        format = new SimpleDateFormat(format1);
        Date date = null;
        try {
            date = format.parse(source);
        } catch (ParseException e) {
            format = new SimpleDateFormat(format2);
            try {
                date = format.parse(source);
            } catch (ParseException parseException) {
                parseException.printStackTrace();
            }
        }
        return date;
    }
}
  • 还要在mvc配置文件中配置
<?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">
    <!--扫描指定包下加有注解的放入spring容器中-->
    <context:component-scan base-package="com.mlyr.f"/>
    <!--指向自定义的日期转换Bean-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    <mvc:default-servlet-handler/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!--配置日期转换器-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!--注入自定义的日期转换器-->
                <bean class="com.mlyr.f.DateConvert"></bean>
            </set>
        </property>
    </bean>
</beans>

第二种解决方案

  • 在实体类上加@DateTimeFormat(pattern = "yyyy-MM-dd")
  • 只能解决局部的类中的日期类型映射
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String pwd;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date date;
}

@RequestBody

  • @RequestBody 注解可以接收json格式的数据,并将其转换成对应的数据类型

  • 在使用之前一定要导入一个依赖,不然会报415错误

  • <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.12.1</version>
    </dependency>
    
  • 还有要设置传过去的是json数据,请求类型为contentType : "application/json;charset=UTF-8"

  • 还有要在mvc配置文件中配置<mvc:annotation-driven/>

@RequestMapping("app")
public String app(@RequestBody User user){
    System.out.println("APP+"+user);
    return null;
}
<button type="button" id="btn">按钮</button>
<script>
    $("#btn").click(function (){
        $.ajax({
            url: "app",
            type: "post",
            dataType:"json",
            //headers contentType 选其一设置去请求类型
            // headers: {'Content-type': 'application/json;charset=UTF-8'},
            contentType : "application/json;charset=UTF-8",
            data: JSON.stringify({"name": "ADD", "pwd": "1234"}),
            success: function (data) {
                alert(data)
            }
        })
    })
</script>

还有一种是自定义一个消息转换器

  • 自定义消息转换器
public class UserHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }
    @Override
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        System.out.println("=========");
        //获取到从页面传递过来的字符串
        InputStream body = inputMessage.getBody();
        byte[] bytes = new byte[1024];
        body.read(bytes);//将输入流中的数据读到byte数组中去
        String str = new String(bytes).trim();//将数组转换为字符串,并去除掉多余的空格   name=AAA&pwd=123
        String[] strings = str.split("&");//将传过来的字符串先按照&进行分割 {name=AAA,pwd=123}
        Object obj = null;
        try {
             obj = clazz.newInstance();
            for (String string : strings) {

                String[] ss = string.split("=");//再将分割后的字符串数组再以=进行分割  此时ss[0]=name,ss[1]=AAA
                Field declaredField = clazz.getDeclaredField(ss[0]);//反射获取对应的属性
                declaredField.setAccessible(true);//打破封装
                declaredField.set(obj,ss[1]);//赋值
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return obj;
    }
    @Override
    protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    }
}
  • 在mvc中配置
<?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">
    <!--扫描指定包下加有注解的放入spring容器中-->
    <context:component-scan base-package="com.mlyr.j"/>
    <mvc:annotation-driven>
        <!--配置消息转换器-->
        <mvc:message-converters register-defaults="true">
            <!--自定义的信息转换器-->
            <bean class="com.mlyr.j.UserHttpMessageConverter">
                <property name="supportedMediaTypes" >
                    <!--配置转换的数据格式-->
                    <list>
                        <value>application/x-www-form-urlencoded</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    <mvc:default-servlet-handler/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>
  • 发送的请求
<button type="button" id="btn">按钮</button>
<script>
    $("#btn").click(function (){
        $.ajax({
            url: "app",
            type: "post",
            dataType:"json",
            //headers contentType 选其一设置去请求类型
            // headers: {'Content-type': 'application/json;charset=UTF-8'},
            // contentType : "application/json;charset=UTF-8",
            // data: JSON.stringify({"name": "ADD", "pwd": "1234"}),
            data:{"name": "ADD", "pwd": "1234"},
            success: function (data) {
                alert(data)
            }
        })
    })
</script>

注意:

  • 这个自定义的消息转换器只能转换传过来的key=value这种形式的数据,json格式的转换不了
  • 当然他与SpringMVC默认的json格式转换可以共同使用,不影响,传过来的如果是 contentType : "application/json;charset=UTF-8",
    data: JSON.stringify({"name": "ADD", "pwd": "1234"}), 的他就会不走自定义的转换器
  • data:{"name": "ADD", "pwd": "1234"} 会走自定义的消息转换器

不经风雨,怎见彩虹?
原文地址:https://www.cnblogs.com/MLYR/p/14487014.html