Springboot:前后端分离——提交url返回json

参考

SpringBoot实现前后端数据交互、json数据交互、Controller接收参数的几种常用方式 - edda_huang - 爱码网

Spring Boot返回JSON数据(三种方式)_Eternal_Summer-的博客-CSDN博客

SpringBoot 返回 Json 数据格式_跑起来要带风!的博客-CSDN博客

Springboot之返回json数据格式的两种方式-yellowcong_drnrrwfs的博客-CSDN博客

Springboot-json做前后端分离 - 梦却了无影踪 - 博客园

1、前言

现在大多数互联网项目都是采用前后端分离的开发方式:

  • 前端负责页面展示数据获取;
  • 后端负责业务逻辑接口封装

后端在与前端交互的过程中,常用Json数据与前端进行交互。

如果想获取前端送来的Json,需要用@RequestBody注解

该注解用于获取http request的内容(字符串),通过SpringMVC提供的HttpMessageConverter接口将读取到的内容转换为Json、xml等格式的数据,并将其绑定到Controller方法的参数上,

提交方式为POST时

  • 前端以application/x-www-form-urlencoded上传JSON对象,后端@RequestParamServlet获取参数;
  • 前端以application/json上传Json字符串后端@RequestBodyHttpServletRequest获取参数。

1.1、依赖

spring-boot-starter-web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
    <version>2.0.3.RELEASE</version>
    <scope>compile</scope>
</dependency>

 

2、注解 

  • @RestController:写在Controller类之前,添加该注解即可返回JSON格式的数据;@RestController = @Controller + @ResponseBody,@ResponseBody注解是将return的数据结构转换为JSON格式。
  • @RequestMapping("/url"):写在Controller类前或类方法前,表示该类或该方法映射的URL,当我们访问该URL时,就会自动调用相应的处理方法;
  • @PostMapping:相当于@RequestMapping(method = ReuqestMethod.POST )
  • @GetMapping:相当于@RequestMapping(method = ReuqestMethod.GET )
  • @PathVariable(GET专用):通常我们用URL Template样式映射,即url/{param}这种形式,我们可以获取到URL后的参数
  • @RequestParam(POST、GET均可):用于获取多个参数,以及application/x-www-form-urlencoded传来的JSON对象,在()传入需要获取参数的参数名
    @RequestParam(
                        required = false , 
                        defaultValue = "0" , 
                        value = "username"
                        )

    参数

    说明

    required

    表明该参数是否必须;

    如果为true且没有传入,会报404错误;

    如果是false且没有传入,会默认为null;

    value

    请求中传入的参数名称;

    如果不设置后台接口的value值,则会默认为该变量名。

    defaultValue

    参数的默认值;

    如果request中没有同名参数,则变量默认为该值

     

     

  • @RequestBody(POST专用)用的最多的注解,该注解与@RequestParam作用类似,区别在于将①传来的多个参数用Map或Entity统一接收,而不用对每个参数分别写注解;②application/json传来的Json字符串的处理;
  • @RequestHeader:获取Header信息;
  • @CookieValue:获取Cookie值。

后端JSON发给前端的过程中,注解的作用

当后端接收完前端JSON,响应也是返回JSON给前端,此时只需要在后台Controller类加上@ResponseBody注解即可。该注解用于将Controller方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据,如JSON、xml等,通过Response响应前端

更常用的是@RestController,它相当于@Controller + @ResponseBody。

3、请求路径参数:GET

注解:@RequestParam@PathVariable

一般用于查询数据,采用明文传输,用于获取用户无关的信息。

可以用@GetMapping注解,它其实是@RequestMapping( method = ReuqestMethod.GET  )的缩写。

3.1、GET请求,URL路径传参:用 url?param=value的形式

如:http://localhost:4001/api/unit?code=111

后端如果要获取这样的URL,可以用@RequestParam注解

@RestController
public class HelloController{
    @RequestMapping(value="/hello",method=RequestMethod.GET)
    public String sayHello(@RequestParam Integer id){
        return "id:"+id;
    }
}

对上段代码的解释,对于URLhttps://IP:端口/hello?Param=Value这种URL,使用@RequestParam 类型 Param的形式来获取,Value作为Param的值被传入,在方法中可以直接用变量Param来访问。

 

3.2、GET请求,URL路径参数:用url/value1/value2/...的形式

与3.1相比,省略了参数名

如:http://localhost:4001/api/unit/1

后端如果要获取路径参数,可以用@PathVariable

@RestController
public class HelloController{
    @RequestMapping(value="/hello/{id}/{name}",method=ReuqestMethod.GET)
    public String sayHello(@PathVariable("id") Integer id,@PathVariable("name") String name){
        return "id:"+id+" name:"+name;
    }
}

上文中,对于URLhttps://IP:端口/hello/Value1/Value2这种URL,Value1作为@RequestParam变量id的值,Value2作为@RequestParam变量name的值被传入。

3.3、GET请求,只有路径没有参数无注解,直接return

假设请求的URL为localhost/book,要返回一个JSON的做法为:

①先创建一个Book实体类(Entity)

package com.itlearn.springboot06json.beans;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

import java.util.Date;

@Data
public class Book {
    private String name;
    private String author;
    @JsonIgnore
    private Double price;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date cationDate;
}
  • @JsonIgnore:转换为JSON时忽略该属性;
  • @JsonFormat(pattern = "yyyy-MM-dd"):对该属性的值进行格式化。

②创建Controller,return book

@RestController
public class BookController {

    @GetMapping("/book")
    public Book book(){
        Book book = new Book();
        book.setName("三国演义");
        book.setAuthor("罗贯中");
        book.setPrice(30D);
        book.setCationDate(new Date());
        return book;
    }

这样在页面中显示的就是:

{"name":"三国演义","author":"罗贯中","cationDate":"2021-05-03"}

3.4、小结

路径传参:URL为URL?Param=Value,用@RequestMapping(value=URL) + @RequestParam 类型 变量名提取参数值;

路径参数:URL为URL/value1/value2/...,用@RequestMapping(value="url/{param1}/{param2}/...") + @PathVariable("param") 类型 变量名提取参数值。

3.5、SpringBoot如何将Entity自动转换为JSON?

SpringBoot之所以能自动将一个return的Entity转换为JSON,是因为引入的 spring-boot-starter-web依赖默认加入了Jackson作为JSON处理器,使我们不需添加额外的JSON处理器就可以直接返回一段JSON了。

 

4、POST请求

注解:

  • @RequestBody:用于application/json类型的POST;

  • @RequestParam:用于application/x-www-form-urlencoded类型的POST;

  • 以上两个注解不能互相混用!

4.1、POST请求,Body传值(application/jsonJSON字符串

使用JSON格式传值,在postman中设置如下

@RequestBody注解(可以用MapEntity类):

//map接收
@PostMapping(path = "/demo1")
public void demo1(@RequestBody Map<String,String> person){
     System.out.println(person.get("name"));
System.out.println(person.get("code")); }
//或者用Entity类对象接收 @PostMapping(path = "/demo1") public void demo1(@RequestBody Person person){ System.out.println(person.toString()) }

注意

  • 使用@RequestBody注解接收参数时,要读取的数据放在Request Body中,Content-Type必须为application/json,否则会类型不支持的异常错误“org.springframework.web.HttpMediaTypeNotSupportedException”
  • 当Ajax用application/x-www-form-urlencoded格式上传数据时,会使用JSON对象,后台只能用@RequestParamServlet获取参数(见4.2节)
  • 当Ajax用application/json格式上传数据时,会使用JSON字符串,后台可以用@RequestBodyrequest获取参数。

 

如何定义后台接收参数,使之可以与前台发来的JSON数据对应呢?

前端JSON的KeyEntity类中必须找到对应的Field,就会自动映射;即前端传来的JSON的Key必须在Entity中存在,且同名,不然就会报错。

 

4.2、POST请求,Body传值(application/x-www-from-urlencoded与JSON对象)

参考

【转载】springboot如何接收application/x-www-form-urlencoded类型的请求_weixin_41734192的博客

数据

编码类型application/x-www-form-urlencoded,这种格式的特点是name/value为一组,每组间用&连接,这种形式不能用复杂Json组织成Key-Value的形式。

要传输的数据,在postman中设置如下,格式为x-www-form-urlencoded,请求的URL为localhost/register:

 

 

注意,千万不能用@RequestBody来接收,否则会报错415:“Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported Http status 415 Unsupported Media Type”,只能用@RequestParam或者HttpServletRequest

4.1.1、@RequestParam(参数前注解)

可以用独立参数分别接收,也可以用Map一次性全部接收

1)独立参数分别接收

@PostMapping("/register")
public void register(@RequestParam(value="username") String username,
                     @RequestParam(value="password") String password,
                     @RequestParam(value="identity") String identity)){
        System.out.println("username="+username");
        System.out.println("password="+password");
        System.out.println("identity="+identity");
}

2)Map一次性接收

@PostMapping("/register")
public void register(@RequestParam Map<String,String> person){
        System.out.println("username="+person.get("username"));
        System.out.println("password="+person.get("password"));
        System.out.println("identity="+person.get("identity"));
}

 

4.2.2、HttpServletRequest(参数前不需要注解)

@Controller
public class LoginController {
  @PostMapping("/login")
  public void login(HttpServletRequest request){
      System.err.println(request.getParameter("identity"));
      System.err.println(request.getParameter("username"));
      System.err.println(request.getParameter("password"));
}

 

4.3、POST请求,Headers、Cookie传值

这里我们把Content-Type设置为JSON格式。

我们还可以在Headers中加入别的参数,比如Token

后端可以通过HttpServletRequest获取请求头的内容,如:

//三个方法
request.getHeader(string name)方法:String 
request.getHeaders(String name)方法:Enumeration 
request.getHeaderNames()方法
 
@GetMapping("/demo3")
public void demo3(HttpServletRequest request) {
    System.out.println(request.getHeader("myHeader"));
    for (Cookie cookie : request.getCookies()) {
        if ("myCookie".equals(cookie.getName())) {
            System.out.println(cookie.getValue());
        }
    }
}

 

后端用@RequestBody + Map接收,前端200,后端就能接收参数::

@Controller
public class LoginController {
  @PostMapping("/login")
  public void login(@RequestBody Map<String,Object> map){
      System.err.println(map.get("username"));
      System.err.println(map.get("password"));
      System.err.println(map.get("openid"));
}
}

后端用@RequestBody + Entity对象来接收时。前端报200,后端也是OK:

public class LoginController {
  @PostMapping("/login")
  public void login(@RequestBody Form form){
      System.err.println(form);
}
}
public class Form {
  private String openid;
  private String username;
  private String password;
 
  // get set
 
  @Override
  public String toString() {
      return "Form{" +
              "openid='" + openid + '\'' +
              ", username='" + username + '\'' +
              ", password='" + password + '\'' +
              '}';
  }
}

5、参数校验 @Valid + 字段前注解

后端接收到前端数据,如果要对前端数据进行校验,可以加入SpringBootValidate依赖

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
</dependency>

使用时,只需要在接收数据的Entity前@Valid注解,用BindingResult接收错误、不合法的提示信息

public R hh(@RequestBody @Valid Users user , BindingResult result){
    ...
}

接收参数的Entity类的对应Field前还要加校验注解,比如@NotEmpty(message="密码不能为空")

 

还可以用正则表达式的方式来对属性进行校验,只需要加上如下注解:

@Pattern(
        regexp =  正则表达式,
        message = "输入格式不合法"
)

字段前注解(配合@Valid完成校验)

下图为返回的JSON数据的前缀注解(写在Entity类相关Field前):

注意:

  • 接收到的参数默认类型是String
  • 有的注解只能用在String类型参数上
  • 可以用@JsonProperty实现前端属性名后端Entity类的Field不一致的问题;
  • 使用@RequestBody@ValidJSON参数进行获取与校验

7、最终选择交互方式

7.1、POST请求

最常用的交互方法为:

  • 前端application/jsonPOST请求,上传JSON字符串
  • 后端@RequestBody使用EntityMap接收参数

后端代码1,Entity

@Controller
public class LoginController {
  @PostMapping("/login")
  public void login(@RequestBody Form form){
      System.err.println(form);
}
}

后端代码2,Map

@Controller
public class LoginController {
  @PostMapping("/login")
  public void login(@RequestBody Map<String,Object> map){
      System.err.println(map.get("username"));
      System.err.println(map.get("password"));
      System.err.println(map.get("openid"));
}
}

7.2、GET请求

路径参数:用@RequestParam@PathVariable获取路径参数

header传值:用HttpServletRequest获取

 

posted @ 2022-07-07 21:51  ShineLe  阅读(3788)  评论(5编辑  收藏  举报