浅析SpringMvc中参数的解耦

44 篇文章 0 订阅
13 篇文章 0 订阅

springmvc中请求参数的耦合

这里所说的是请求时的参数耦合
在javaweb我们常常用request对象来获得请求中的参数
如果request获得的参数名称不匹配,那么获得的参数就为null

比如下面的代码---->>

package com.gavin.test;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
public class testController {
    @RequestMapping("/tolog.do")
    public String toLogin(HttpServletRequest request, HttpServletResponse resp) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
//        连接数据库查询
        System.out.println(username + "--" + password);
        return "success";
    }
}

在这里插入图片描述
假如请求时参数不匹配,即我们的请求参数只能是username和password
在这里插入图片描述

这时候如果改变就会得不到想要的参数;

所以需要一种方式来实现低耦合,不用request对象获得参数并能获得请求时的参数

    @RequestMapping("/tologg.do")
    public String toLogin(String username, String password) {
     
//        连接数据库查询
        System.out.println(username + "--" + password);
        return "success";
    }

在这里插入图片描述

这里也是要求请求时的参数要和方法中的参数名一致,如果不一致---->>
在这里插入图片描述

那怎么实现解耦合?

我们可以指定请求时的参数别名

    @RequestMapping("/tologgg.do")
    public String toLog(@RequestParam("name") String username,@RequestParam("pwd") String password) {
//        连接数据库查询
        System.out.println(username + "--" + password);
        return "success";
    }

在这里插入图片描述

使用这种方式还可以自动实现类型的转换
在这里插入图片描述
有时候接收前端的参数太多像这样

在这里插入图片描述后端接收
在这里插入图片描述
这时候就要将参数封装为一个类来实现

POJO类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TPerson {
    String name;
    Integer age;
    String gender;
    String[] hobby;
    String birth;
}

在这里插入图片描述

这样如果参数发生了变化,我们需要修改TPerson类中的属性而不是方法

有时候在pojo解耦时会出现no getter 的错误,此时在参数pojo上添加注解@Param("pojo实例名") 即可

springmvc底层是通过getset方法来实现参数的解析—即反射的方式,所以类中必须要有无参构造方法;

在这里插入图片描述
这里会涉及到一个问题就是对于一些基本类型的转换是可以的,如果是日期类型的,那会提示转换失败
其实原因很简单,关于日期的转换格式不知道,所以,无法进行解析

日期类型转换

在这里插入图片描述

那如果放在实体类中

在这里插入图片描述
我们看到既然注解放在参数上时时可以识别日期,那同样我们将注解放到TPerson类中的属性上
在这里插入图片描述

除了上述的注解转换方式,spring还提供了转换接口
在这里插入图片描述

import lombok.SneakyThrows;
import org.springframework.core.convert.converter.Converter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class StringToDate implements Converter<String, Date> {
    SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
    @SneakyThrows//偷偷默默的抛出异常的注解
    @Override
    public Date convert(String source) {
        Date date = dateFormat.parse(source);
        return date;
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TPerson {
    String name;
    Integer age;
    String gender;
    String[] hobby;
//    @DateTimeFormat(pattern = "yyyy-MM-dd")
    Date birth;
    @Override
    public String toString() {
        return "TPerson{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                ", birth='" + birth + '\'' +
                '}';
    }
}

请求后-----
在这里插入图片描述
害,没有配置转换类,
在配置文件中配置转换类
先看一下要使用的接口

在这里插入图片描述
再次请求后得到结果,
在这里插入图片描述

可以看到明明通过一个注解的方式解决,却要费尽心思用一个转换类加配置
类解决,显然不是一个方便的方式;

List参数的解耦

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form method="post" action="dodo.do">
    名称:<input name="fruitList[0].fruitName"></br>
    种类:<input name="fruitList[0].fruitType"></br>

    名称:<input name="fruitList[1].fruitName"></br>
    种类:<input name="fruitList[1].fruitType"></br>
    <input type="submit" value="提交">
</form>

</body>
</html>

后端—>

package com.gavin.pojo;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * t_user
 * @author 
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TUser implements Serializable {
    private Integer userId;

    private String userName;

    private String loginName;

    private String password;

    private Integer roleId;

    private String tel;

    private Date registerTime;

    private String status;

    /**
     * 一个用户对应一个角色
     */
    private TRole tRole;
    private static final long serialVersionUID = 1L;


    private List<Fruit> fruitList;
}
    @RequestMapping("/dodo.do")
    public String dododo(TUser tUser){

        System.out.println(tUser.getFruitList());
        return "success";
    }

在这里插入图片描述

这里相当于遍历集合中的元素,按照下标的形式进行装配

map类型参数

跟list一样,

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form method="post" action="dodo.do">
    名称:<input name="fruitCount['fruit'].fruitName"></br>
    种类:<input name="fruitCount['fruit'].fruitType"></br>

    名称:<input name="fruitCount['1'].fruitName"></br>
    种类:<input name="fruitCount['1'].fruitType"></br>
    <input type="submit" value="提交">
</form>

</body>
</html>

后端

    @RequestMapping("/dodo.do")
    public String dododo(TUser tUser){

        System.out.println(tUser.getFruitCount());
        return "success";
    }

只要满足键值对关系就可以了

restful风格的参数

说到这个restful风格,说起来也和常见,比如
链接一下baidu.com
在这里插入图片描述
这个就是一种restful风格的解析

在springmvc中怎么用着种风格呢?
我记得之前在某一篇帖子种写了这种方式, 看链接

请求转发与响应重定向

基础知识请看这个链接
后端—>

    @RequestMapping("testForward.do")
    public String testForward() {
        System.out.println("testForward");

        return "1234.jsp";
    }
    @RequestMapping("testForward1.do")
    public String testForward1() {
        System.out.println("testForward1");
        return "/1234.jsp";
    }
    @RequestMapping("testRedirect.do")
    public String testRedirect() {
        System.out.println("testForward1");
        return "redirect:1234.jsp";
    }
<form method="get" action="testForward.do">

    <input type="submit" value="testForward"/>

</form>

<form method="get" action="testForward1.do" >

    <input type="submit" value="testForward1" />

</form>
<form method="get" action="testRedirect.do" >

    <input type="submit" value="testRedirect" />

</form>

通过view来完成请求转发与重定向

    @RequestMapping("/viewForward1.do")
    public View viewForward1(HttpServletRequest request){
        View view=null;
        System.out.println("viewForward1");
//        请求转发
//     view= new InternalResourceView("/1234.jsp");
//     重定向
     view=new RedirectView(request.getContextPath()+"/1234.jsp");
      return view;
    }
}

<form method="get" action="viewForward1.do" >

    <input type="submit" value="viewForward1" />

</form>

通过ModelAndView 来完成请求转发与重定向;

    @RequestMapping("/viewForward.do")
    public Object viewForward(HttpServletRequest request) {
        System.out.println("viewForward");
        ModelAndView model = new ModelAndView();
//      model.setViewName("1234.jsp");
//        model.setViewName("redirect:1234.jsp");

       // model.setView(new InternalResourceView("/1234.jsp"));
       model.setView(new RedirectView(request.getContextPath()+"/1234.jsp"));
        return model;
    }


小结:
可以通过 返回值来直接完成请求转发或者重定向,
可以通过View接口/ModelAndView接口来实现

实际上一般是通过Model model/ModelAndView来在请求转发时添加一些数据;可以看到ModelAndView 可以通过setview方法传入view参数实现请求转发与响应重定向;

Json数据的发送与接收

   @RequestMapping("/searchUser.do")
    @ResponseBody
    public User searchUser() {
     User user= new User(88,"gavin","123");
        return user;
    }

在这里插入图片描述

json数据的传递来龙去脉

为便于理解,做以下逐级递进

//普通格式
    @RequestMapping("/searchUser.do")
    @ResponseBody
    public User searchUser(@RequestParam("name") String name,@RequestParam("pwd") String pwd) {
        System.out.println(name+pwd);
     User user= new User(88,"gavin","pwd");
        return user;
    }
   // pojo对象格式
    @RequestMapping("/searchUserd.do")
    @ResponseBody
    public User searchUserd(User users) {
        System.out.println(users);
     User user= new User(88,"gavin","pwd");
        return user;
    }

前端测试---->>

<%--
  Created by IntelliJ IDEA.
  User: Gavin
  Date: 2021/12/20
  Time: 19:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" %>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>


<body>
<form method="get" action="toInfo.do/10">
    id号<input type="text" name="id" placeholder="请输入账号"/><br>
    <input type="submit" value="toget"/>

</form>
<form method="post" action="toInfo.do/10">
    id号<input type="text" name="id" placeholder="请输入账号"/><br>
    <input type="submit" value="topost"/>

</form>
<form method="post" action="toInfo.do/10">
    id号<input type="text" name="id" placeholder="请输入账号"/><br>
    <input type="hidden" name="_method" value="PUT"/>
    <input type="submit" value="toput"/>

</form>
<form method="get" action="toInfo.do/10">
    id号<input type="text" name="id" placeholder="请输入账号"/><br>
    <input type="hidden" name="_method" value="DELETE"/>
    <input type="submit" value="todel"/>

</form>


<form method="get" action="testVoid.do">

    <input type="submit" value="testVoid"/>

</form>
<form method="get" action="testForward.do">

    <input type="submit" value="testForward"/>

</form>

<form method="get" action="testForward1.do">

    <input type="submit" value="testForward1"/>

</form>
<form method="get" action="testRedirect.do">

    <input type="submit" value="testRedirect"/>

</form>

<form method="get" action="viewForward.do">

    <input type="submit" value="viewForward"/>

</form>

<form method="get" action="viewForward1.do">

    <input type="submit" value="viewForward1"/>

</form>

<form method="get" action="ModelAndViewForward1.do">

    <input type="submit" value="ModelAndViewForward1"/>

</form>

<form>
    姓名:<input name="name" id="name" type="text">
    密码:<input name="pwd" id="pwd" type="text">
    <input type="button" value="searchUser" onclick="search()"/>

</form>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.5.1.min.js" type="text/javascript">

</script>
<script type="text/javascript">
    function search() {
     var str=$("#name").val();
       var str1=  $("#pwd").val();
        $.ajax({
            url: "${pageContext.request.contextPath}/searchUserd.do?name="+str+"&pwd="+str1,
            type:"get",
            // data: JSON.stringify({'name':'123','pwd':'123'}),
            // dataType: "json",
            contentType: "application/json;charset=UTF-8",
            success: function (data) {
                alert(data.name + data.pwd);
            }
        });
    }
</script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述

@RestController
//@Controller
public class testController {  
    @RequestMapping("/searchUser.do")
    @ResponseBody
    public User searchUser(@RequestParam("name") String name,@RequestParam("pwd") String pwd) {
        System.out.println(name+pwd);
     User user= new User(88,"gavin","pwd");
        return user;
    }
    @RequestMapping("/searchUserDemo.do")
    public User searchUser() {
     User user= new User(88,"gavin","pwd");
        return user;
    }
    @RequestMapping("/searchUserd.do")
    @ResponseBody
    public User searchUserd(User users) {
        System.out.println(users);
     User user= new User(88,"gavin","pwd");
        return users;
    }

}

如果返回的数据都是json格式的.可以直接在类上加注解 @RestController来简化每个方法上的@RequesponseBody注解

逐渐将数据替换为json格式


<form>
    id:<input name="id" id="id" type="text"/>
    姓名:<input name="name" id="name" type="text"/>
    密码:<input name="pwd" id="pwd" type="text"/>
    <input type="button" value="searchUser" onclick="search()"/>

</form>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.5.1.min.js" type="text/javascript">

</script>
<script type="text/javascript">
    function search() {
        var str0=$("#id").val();
     var str=$("#name").val();
       var str1=$("#pwd").val();
        $.ajax({
            url: "${pageContext.request.contextPath}/searchUserd.do",
            type:"post",
            data: JSON.stringify({id:$("#id").val(),name:$("#name").val(),"pwd":$("#pwd").val()}),
            dataType: "json",
            contentType: "application/json;charset=UTF-8",
            success: function (data) {
                alert(data.id+data.name + data.pwd);
            }
        });
    }
</script>
</body>
</html>

后端—>>

    @RequestMapping("/searchUserd.do")
    @ResponseBody
    public User searchUserd(@RequestBody User users) {
        System.out.println(users);
     User user= new User(88,"gavin","pwd");
        return users;
    }

在这里插入图片描述

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

RequestBody 与RequestParam的区别

可以这么理解,RequestBody是接收前端json字符串的,{key:value}
RequestParam是接收前端参数的 key=value

DateTimeFormat与 JsonFormat的区别

DateTimeFormat----参数格式

JsonFormat—响应数据格式
先看案例—>>
一个实体类

package com.gavin.pojo;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Repository;

import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository(value = "player")
public class Player {
    private  String name;
    private int age;
    @DateTimeFormat(pattern = "yyyy-MM-dd")//声明一个字段或方法参数应该被格式化为日期或时间。
    //处理响应json 数据的处理, pattern :指定响应时间日期的格式 , Timezone:指定响应的时区,否则会有8个小时的时间差
    @JsonFormat(pattern = "yyyy-MM-dd" ,timezone = "UTC-8")
    private Date birth;
    private static final long serialVersionUID = 1L;
}

controller层

package com.gavin.dateFormat;

import com.gavin.pojo.Player;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class DateFormatController {
    @RequestMapping("/toLogin.do")
    @ResponseBody
    public Player showInfo(@RequestBody Player player){

        System.out.println("success");
        return player;
    }
}

前端

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.5.1.min.js"></script>
</head>
<body>


<script type="text/javascript">
    function happy() {
        $.ajax({
            url:"${pageContext.request.contextPath}/toLogin.do",
            type:"post",
            data:JSON.stringify({name:"张胜男",age:18,birth:"1998-10-19"}),
            dataType:"json",
            contentType:"application/json;charset=UTF-8",
            success:function(data){
                $("#name").val(data.name);
                $("#age").val(data.age);
                $("#birth").val(data.birth);
            }
        });
    }
</script>
<form >

    <button type="button" onclick="happy()">注册</button>
    <input name="name" id="name" type="text"/>
    <input name="age" id="age" type="text"/>
    <input name="birth" id="birth" type="text"/>
</form>
</body>
</html>

前端点击按钮,然后异步显示数据
在这里插入图片描述
要想知道区别,别然讲一万遍不如自己时间一遍;
在这里插入图片描述
请求结果—>>

在这里插入图片描述
具体的原因是这样的---->
在这里插入图片描述

当前端传过来的数据是一堆字符串时,这个时候可以用JSON.stringify(str)来将字符串转换为json对象;

required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值 为 false,get
请求得到是null。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMartain

祝:生活蒸蒸日上!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值