springboot的服务端Restful风格 API接口,在不同场景下,设置不同的请求及传参方式的设计,及其他异常场景解决方案

Posted 阿啄debugIT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot的服务端Restful风格 API接口,在不同场景下,设置不同的请求及传参方式的设计,及其他异常场景解决方案相关的知识,希望对你有一定的参考价值。

Restful风格API设计

 

Restful本身不是一项什么高深的技术,而只是一种编程风格,是通过HTTP的方法get、post、PUT、DELETE、HEAD等CRUD相关的操作。

序号方法描述
1GET发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中。另外get支持快取、缓存
、可保留书签等。幂等
2POST和get一样很常见,向服务器提交资源让服务器处理,比如提交表单、上传文件等,可能导致建立新的资源或者对
原有资源的修改。提交的资源放在请求体中。不支持快取。非幂等
3HEAD本质和get一样,但是响应中没有呈现数据,而是http的头信息,主要用来检查资源或超链接的有效性或是否可以可达、检
查网页是否被串改或更新,获取头信息等,特别适用在有限的速度和带宽下。
5DELETE请求服务器删除某资源。和put都具有破坏性,可能被防火墙拦截。如果是https协议,则无需担心。幂等
6CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。就是把服务器作为跳板,去访问其他网页
然后把数据返回回来,连接成功后,就可以正常的get、post了。
7OPTIONS获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。
8TRACE回显服务器收到的请求,主要用于测试或诊断。一般禁用,防止被恶意攻击或盗取信息。
@RestController
@RequestMapping("/rest")
public class DebugItRestController {
	@RequestMapping(value = "/debugit/{id}", method = DELETE, produces = "application/json")
	public WebResponse<?> deletedebugIt(@PathVariable Long id) {
		DebugIt debugIt = debugItService.getById(id);
		debugIt.setStatus(-1);
		debugItService.updatedebugIt(debugIt);
		WebResponse<Object> response = WebResponse.getSuccessResponse(null);
		return response;
	}
}

 分析一下这段代码,这段@RestController代码和之前@Controller代码的区别在于:
  (1)使用的是@RestController这个注解,而不是@Controller,不过这个注解同样不是Spring boot提供的,而是Spring MVC4中的提供的注解,表示一个支持Restful的控制器
  (2)若在@RestController标识的类中方法有(delete、get、post、update)等上的注解URL映射可以相同,即都是/debugit/{id},但在@Controller标识的类不能出现。这里的在@RestController标识的类,可以通过method来进行区分produces的作用是表示返回结果的类型是JSON。
  (3)@PathVariable这个注解,也是Spring MVC提供的,其作用是,表示该变量的值是从访问路径中获取

0、场景:请求路径传参,若中间参数为空怎么解决

​​​​​​​@RequestMapping(value = "/get/{id}/{userId}", method = RequestMethod.GET)
    public Result getMemberShip(@PathVariable("id") int id,@PathVariable("userId") int userId) {

假如id为非必需参数

//可以指定多个匹配路径
@RequestMapping(value = {"/get/{userId}", "/get/{id}/{userId}"}, method = RequestMethod.GET)

//然后设置参数非必须
@PathVariable(required = false) String id

A、直接把表单的参数,写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交。

url形式:http://localhost/server-servlet-context-path/insertUser1?username=阿啄debugIT&password=111111 提交的参数需要和Controller方法中的入参名称一致。

前段的请求

POST请求方式

<script>
	var xhr = new XMLHttpRequest()
	xhr.open('POST', 'http://localhost:8080/server-servlet-context-path/insertUser1') // 设置请求行
	xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
	xhr.send('username=阿啄debugIT&password=111111') // 以 urlencoded 格式设置请求体
	xhr.onload=function(){
	  if(xhr.readyState!==4) return 
	  console.log(xhr.responseText)
	}
</script>

GET请求方式: 

<script>
   var xhr = new XMLHttpRequest()
   xhr.open('GET', 'http://localhost:8080/server-servlet-context-path/insertUser1?username=阿啄debugIT&password=123') // 设置请求行
   xhr.send() 
   xhr.onload=function(){
     if(xhr.readyState!==4) return 
     console.log(xhr.responseText)
   }
</script>

Controller相应的方法的形参

/**
 * 直接把表单的参数写在Controller相应的方法的形参中
  * @param username
 * @param password
 * @return
 */
@RequestMapping("/insertUser1")
public String insertUser1(String username,String password) {
	System.out.println("username is:"+username);
	System.out.println("password is:"+password);
	return "index";
}

B、通过HttpServletRequest接收,post方式和get方式都可以。

通过HttpServletRequest对象获取请求参数。

/**
 * 通过HttpServletRequest接收
  * @param request
 * @return
 */
@RequestMapping("/insertUser2")
public String insertUser2(HttpServletRequest request) {
    String username=request.getParameter("username");
    String password=request.getParameter("password");
    System.out.println("username is:"+username);
    System.out.println("password is:"+password);
    return "index";
}

C、通过一个bean来接收,post方式和get方式都可以。

建立一个和表单中参数对应的bean

public class UserModel {
    
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
}

用这个bean来封装接收的参数

    /**
     * 通过一个bean来接收
      * @param user
     * @return
     */
    @RequestMapping("/insertUser3")
    public String insertUser3(UserModel user) {
        System.out.println("username is:"+user.getUsername());
        System.out.println("password is:"+user.getPassword());
        return "index";
    }

D、通过@PathVariable获取路径中的参数

例如:访问http://localhost/server-servlet-context-path/insertUser4/lixiaoxi/111111 路径时,

前端请求

<script>
  var xhr = new XMLHttpRequest()
  xhr.open('GET', 'http://localhost:8080/server-servlet-context-path/insertUser4/username=阿啄debugIT/password=111111') // 设置请求行
  xhr.send() 
  xhr.onload=function(){
    if(xhr.readyState!==4) return 
    console.log(xhr.responseText)
  }
</script>

后端controller

/**
 * 通过@PathVariable获取路径中的参数
  * @param username
 * @param password
 * @return
 */
@RequestMapping(value="/insertUser4/{username}/{password}",method=RequestMethod.GET)
public String insertUser4(@PathVariable String username,@PathVariable String password) {
   System.out.println("username is:"+username);
   System.out.println("password is:"+password);
   return "index";
}

自动将URL中模板变量{username}{password},绑定到通过@PathVariable注解同名参数上,即入参后username=阿啄debugIT、password=111111。

E、使用@ModelAttribute注解获取POST请求的FORM表单数据

Jsp表单如下:

<form action ="<%=request.getContextPath()%>/insertUser5" method="post"> 
     用户名:&nbsp;<input type="text" name="username"/><br/>
     密&nbsp;&nbsp;码:&nbsp;<input type="password" name="password"/><br/>
     <input type="submit" value="提交"/> 
     <input type="reset" value="重置"/> 
</form> 

 或者

<script>
  var xhr = new XMLHttpRequest()
  xhr.open('POST', 'http://localhost:8080/server-servlet-context-path/insertUser5') // 设置请求行
  xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
  xhr.send('username=阿啄debugIT&password=111111') 
  xhr.onload=function(){
    if(xhr.readyState!==4) return 
    console.log(xhr.responseText)
  }
/script>

Java Controller如下:

/**
 * 使用@ModelAttribute注解获取POST请求的FORM表单数据
  * @param user
 * @return
 */
@RequestMapping(value="/insertUser5",method=RequestMethod.POST)
public String insertUser5(@ModelAttribute("user") UserModel user) {
    System.out.println("username is:"+user.getUsername());
    System.out.println("password is:"+user.getPassword());
    return "index";
}

F、用注解@RequestParam绑定请求参数方法入参

当请求参数username不存在时,会有异常发生,可以通过设置属性required=false解决,

例如: @RequestParam(value="username", required=false)

/**
 * 用注解@RequestParam绑定请求参数到方法入参
  * @param username
 * @param password
 * @return
 */
@RequestMapping(value="/insertUser6",method=RequestMethod.GET)
public String insertUser6(@RequestParam("username") String username,@RequestParam("password") String password) {
    System.out.println("username is:"+username);
    System.out.println("password is:"+password);
    return "index";
}

G、用注解@RequestBody绑定请求参数到方法入参,用于POST请求

前段请求

<script>
  var xhr = new XMLHttpRequest()
  xhr.open('POST', 'http://localhost:8080/server-servlet-context-path/insertUser7') // 设置请求行
  xhr.setRequestHeader('Content-Type','application/json')
  xhr.send('{"username":"阿啄debugIT","password":"111111"}') 
  xhr.onload=function(){
    if(xhr.readyState!==4) return 
    console.log(xhr.responseText)
  }
</script>

后端处理

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的) 

@RestController
@RequestMapping("/tools")
public class InnerController {

    @RequestMapping(value="/insertUser7",method=RequestMethod.POST)
    public String insertUser7(@RequestBody DemoUser user) {
        System.out.println("username is:"+user.getUsername());
        System.out.println("password is:"+user.getPassword());
        return "success";
    }
}

以上是关于springboot的服务端Restful风格 API接口,在不同场景下,设置不同的请求及传参方式的设计,及其他异常场景解决方案的主要内容,如果未能解决你的问题,请参考以下文章

restful 接口 复杂对象入参

spring boot 快速搭建 基于 Restful 风格的微服务

SpringBoot使用IDEA创建一个SpringBoot服务,并创建三个restful风格的接口

SpringBoot RESTful API 架构风格实践

Springboot-json做前后端分离

基于WinService,开发Restful 风格的Wcf 服务端