Springboot:前后端分离——提交url返回json
作者:互联网
学习自:SpringBoot实现前后端、json数据交互以及Controller接收参数的几种常用方式_java_脚本之家
1、前言
现在大多数互联网项目都是采用前后端分离的开发方式:
- 前端负责页面展示和数据获取;
- 后端负责业务逻辑和接口封装。
在与前端交互的过程中,常用Json数据与前端进行交互。
如果想获取前端送来的Json,需要用@RequestBody注解。
该注解用于获取http request的内容(字符串),通过SpringMVC提供的HttpMessageConverter接口将读取到的内容转换为Json、xml等格式的数据,并将其绑定到Controller方法的参数上,
提交方式为POST时
- Ajax以application/x-www-form-urlencoded上传JSON对象,后端用@RequestParam或Servlet获取参数;
- Ajax以application/json上传Json对象,后端用@RequestBody获取参数。
2、注解
- @PathVariable:通常我们用URL Template样式映射,即url/{param}这种形式,我们可以获取到URL后的参数;
- @RequestParam:用于获取多个参数,在()中传入需要获取参数的参数名;
- @RequestBody:该注解与@RequestParam作用类似,我们使用该注解将参数转换,在代码部分将参数一个个提取出来,用的最多的注解。
- @RequestHeader:获取Header信息;
- @CookieValue:获取Cookie值。
3、请求路径参数:GET
一般用于查询数据,采用明文传输,用于获取用户无关的信息。
可以用@GetMapping注解,它其实是@RequestMapping( method = ReuqestMethod.GET )的缩写。
3.1、GET请求,URL路径传参:用 url?param=value的形式
GET请求通过URL传参,如:
http://localhost:4001/api/unit?code=111
对上文的解释,如果识别到类似URL?Param=Value这种URL,那么Param及其值会被传入@RequestParam标注的各项参数。
后端如果要获取这样的URL,可以用@RequestParam注解:
@RestController public class HelloController{ @RequestMapping(value="/hello",method=RequestMethod.GET) public String sayHello(@RequestParam Integer id){ return "id:"+id; } }
上文中,对于URL为https://IP:端口/hello?Param=Value这种URL,Value作为@RequestParam变量id的值被传入
3.2、GET请求,URL路径参数:用url/value1/value2/...的形式
与3.1相比,省略了参数名。
如:http://localhost:4001/api/unit/1
后端如果要获取路径参数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; } }
上文中,对于URL为https://IP:端口/hello/Value1/Value2这种URL,Value1作为@RequestParam变量id的值,Value2作为@RequestParam变量name的值被传入。
3.3、小结
路径传参:URL为URL?Param=Value,用@RequestMapping(value=URL) + @RequestParam 类型 变量名提取参数值
路径参数:URL为url/value1/value2/...,用@RequestMapping(value="url/{param1}/{param2}/...") + @PathVariable("param") 类型 变量名提取参数值
4、Body参数与POST请求
4.1、POST请求,Body传值
推荐使用JSON格式传值,在postman中设置如下
后端接收这种数据要用@RequestBody或@RequestParam注解:
//用map接收 @PostMapping(path = "/demo1") public void demo1(@RequestBody Map<String,String> person){ System.out.println(person.get("name")); } //或者用Entity类对象接收 @PostMapping(path = "/demo1") public void demo1(@RequestBody Person person){ System.out.println(person.toString()) }
注意
@RequestBody是用来处理前台发来的数据Content-Type,而非application/x-www-form-urlencoded编码的内容,例如application/json、application/xml等;
使用@RequestBody注解接收参数时,从名称上来看也就是说要读取的数据放在请求体中,前台请求的JSON数据的Content-Type必须为application/json,否则会类型不支持的异常错误“org.springframework.web.HttpMediaTypeNotSupportedException”。
当Ajax用application/x-www-form-urlencoded格式上传数据时,会使用JSON对象,后台只能用@RequestParam或Servlet获取参数。
当Ajax用application/json格式上传数据时,会使用JSON字符串,后台可以用@RequestBody或@RequestParam获取参数。
如何定义后台接收参数,使之可以与前台发来的JSON数据对应呢?
若是JSON中的Key在Entity类中可以找到对应的Field,就会自动映射,即前台传来的JSON的Key必须在Entity中存在,且同名,不然就会报错。
4.2、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()); } } }
5、HttpServletRequest
前端JS发送Ajax请求,Content-Type发送信息至服务器内部的编码类型,默认为application/x-www-form-urlencoded,这种格式的特点是name/value为一组,每组间用&连接,这种形式是没有办法将复杂Json组织成Key-Value的形式。
data_type设置为收到的服务器数据的格式,不指定时自动判断:
var jsonObj = {"openid":"xxx","username":"Ed sheeran","password":"123"}; /* Jquery默认Content-Type为application/x-www-form-urlencoded类型 */ $.ajax({ type: 'POST', url: "/login", dataType: "json", data: JSON.stringify(jsonObj), success: function(data) { console.log(data) }, error: function() { console.log("fucking error") } });
后端Servlet接收参数。如果前端报200,后端也是200,返回null。
@Controller public class LoginController { @PostMapping("/login") public void login(HttpServletRequest request){ System.err.println(request.getParameter("openid")); System.err.println(request.getParameter("username")); System.err.println(request.getParameter("password")); }
后端用@RequestBody接收参数,前端报415,后端报Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported Http status 415 Unsupported Media Type
@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")); }
如果在前端加Content-Type:“application/json”。
var jsonObj = {"openid":"xxx","username":"Ed sheeran","password":"123"}; $.ajax({ type: 'POST', url: "/login", dataType: "json", data: JSON.stringify(jsonObj), contentType : "application/json", success: function(data) { console.log(data) }, error: function() { console.log("fucking error") } });
后端用@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 + '\'' + '}'; } }
6、参数校验
后端接收到前端数据,如果要对前端数据进行校验,可以加入SpringBoot的Validate依赖:
<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 = "输入格式不合法" )
2、当后端接收完前端JSON,响应也是返回JSON给前端,此时只需要在后台Controller类加上@ResponseBody注解即可。
该注解用于将Controller方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据,如JSON、xml等,通过Response响应给前端。
@Controller + @ResponseBody返回JSON数据给前端,还可以用@RestController来替换,使代码更简洁。
下图为返回的JSON数据的前缀注解:
注意:
- 接收到的参数默认类型是String;
- 有的注解只能用在String类型的参数上;
- 可以用@JsonProperty实现前端属性名与后端Entity类的Field不一致的问题;
- 使用@RequestBody和@Valid对JSON参数进行获取与校验。
7、最终选择交互方式
7.1、POST请求
最常用的交互方法为:
- 前端用application/json,POST请求,上传JSON字符串
- 后端用@RequestBody使用Entity或Map接收参数
前端代码:
var jsonObj = {"openid":"xxx","username":"Ed sheeran","password":"123"}; /* Jquery默认Content-Type为application/x-www-form-urlencoded类型 */ $.ajax({ type: 'POST', url: "/login", dataType: "json", data: JSON.stringify(jsonObj), contentType : "application/json", success: function(data) { console.log(data) }, error: function() { console.log("fucking error") } });
后端代码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获取
POST请求Body传参:如果参数较多,可以用@RequestBody+Map或Entity接收;如果参数不多,可以用@RequestParam单个映射接收。
标签:Springboot,url,JSON,System,RequestBody,json,参数,println,public 来源: https://www.cnblogs.com/ShineLeBlog/p/16453976.html