12.25 SpringMVC 使用Restful api,让你的代码变得更优雅




服务器后台设计API接口时,目前最流行的风格(原则/标准/规范)就是RESTful,往往简称为REST。

其中 REST=REpresentational State Transfer

REST直译:表现层状态转移

REST核心含义:无状态的资源 资源的变化(CURD)都是通过操作去实现的 资源可以用 URI 表示 用不同的URI和方法,表示对资源的不同操作

简单的说,就是使用同一个URI,就能实现增删改查的请求。而区别增删改查则需要以下典型的Rest方法:

  • GET:获取资源
  • POST:新建资源
  • PUT:更新资源
  • DELETE:删除资源

1.Spring中对Restful的支持

Spring对Restful有很好的支持,提供了以下注解分别对应上述的方法。

<code>@GetMapping
/<code>
<code>@PostMapping
/<code>
<code>@PutMapping
/<code>
<code>@DeleteMapping
/<code>

2.使用Restful实现增删改查

那么我们走一遍增删改查。通过以下例子可以看出,不管增删改查,URI都是http://localhost:8081/test/companies/。这样对你的程序设计,维护,文档设计,维护都很有帮助。

2.1 @GetMapping 取得数据

前端请求url例子

<code>http://localhost:8081/test/companies/任意公司ID/<code>

后端接收代码。这里要讲解的就是,@GetMapping中的{companyId}代表具体的公司id,配合@PathVariable注解,就能够将URL中的字符串提取成参数变量。

<code>@GetMapping(value="/companies/{companyId}")
public ResponseDto getCompany(@PathVariable("companyId") int companyId) {
\treturn service.getCompany(companyId);
}/<code>

2.2 @PostMapping 插入数据。取到Json的值,做数据校验

前端请求url例子

<code>http://localhost:8081/test/companies//<code>

如果用postman测试,你需要包含一段json,作为你要插入的数据。

SpringMVC 使用Restful api,让你的代码变得更优雅

后端代码。因为你的接收数据在body中,所以实体类前必须添加@RequestBody注解。当然了,你也可以进行数据校验,并把结果放入BindingResult。

<code>@PostMapping(value="/companies")
public ResponseDto regitsCompany(@Valid @RequestBody MCompany dto, BindingResult result) {
return service.registCompany(dto);
}/<code>

2.3 @PutMapping 更新数据。同时取到URL的值跟json的值

前端URL例子。跟2.2中的post一样,body中传递json。这里就不截图了。

<code>http://localhost:8081/test/companies/任意公司ID/<code>

后端代码。这里又有一个变通,就是既需要使用@PathVariable,又要使用@RequestBody,才能把url中的值跟json的值同时取到。

<code>@PutMapping(value="/companies/{companyId}")
@Transactional
public ResponseDto updateCompany(@PathVariable("companyId") int companyId, @Valid @RequestBody MCompany dto,
BindingResult result) {
dto.setCompanyId(companyId);
return service.updateCompany(dto);
}/<code>

2.4 @DeleteMapping 删除数据

前端URL例子

<code>http://localhost:8081/test//companies/任意公司ID/<code>

后端代码。这个就没什么好讲的了。

<code>@Transactional 

@DeleteMapping("/companies/{companyId}")
public ResponseDto deleteCompany(@PathVariable("companyId") int companyId) {
return service.deleteCompany(companyId);
}/<code>

3. 返回数据的格式跟风格

3.1 请求处理正常

上述controller中ResponseDto的代码是这样的。

<code>@Data
@Component
public class ResponseDto {
\t// 状态码
\tprivate String code;
\t
\t// 状态信息
\tprivate String msg;
\t
\t// 响应数据
\tprivate Object data;
}/<code>

这是Restful返回的比较标准的格式。

SpringMVC 使用Restful api,让你的代码变得更优雅

3.2 请求处理异常

发生异常的话,有可能是数据校验出错,那样压根不进入controller方法体。也有可能在其他地方出错,比如进入方法体后的片段中出错,我们应该统一在ExceptionHander中处理。

像下面这样,我们返回ResponseEntity,并与HttpStatus关联,当然可以是400,404,500。ResponseDto中你可以放同样的code,也可以是你自己自定义的错误码。这里我们为了方便就设置成同样的。

SpringMVC 使用Restful api,让你的代码变得更优雅

比如请求中的邮件地址非法,就会进入ValidationException的分支,出现上述图片的错误。

<code>@RestControllerAdvice
public class GlobalExceptionController {
Logger logger = LogManager.getLogger(GlobalExceptionController.class);

@Autowired
ResponseDto res;

private ResponseEntity<responsedto> buildResponse(Exception e, HttpStatus status) {
logger.error(e.getMessage());
res.setCode(String.valueOf(status.value()));
res.setMsg(e.getMessage());
res.setData("");

return new ResponseEntity<responsedto>(res, status);
}

// 数据校验错误
@ExceptionHandler(ValidationException.class)
public ResponseEntity<responsedto> handleError(ValidationException e) {
return buildResponse(e, HttpStatus.BAD_REQUEST);
}

// 文件IO错误
@ExceptionHandler(FileException.class)
public Object handleError(FileException e) {
return buildResponse(e, HttpStatus.INTERNAL_SERVER_ERROR);
}

// 业务逻辑错误
@ExceptionHandler(SiLEDBusinessException.class)
public Object handleError(SiLEDBusinessException e) {
return buildResponse(e, HttpStatus.BAD_REQUEST);
}

// 其他错误
@ExceptionHandler(Exception.class)
public Object handleError(Exception e) {
return buildResponse(e, HttpStatus.INTERNAL_SERVER_ERROR);
}
}/<responsedto>/<responsedto>/<responsedto>/<code>

4. Restful的其他事项

4.1正则表达式

如果你想精准的匹配URL,可以使用正则表达式。

<code>@RequestMapping(value = "/{name:([a-z][0-9a-z-]{3,31}}/mytest",method = {RequestMethod.GET})
public void test(@PathVariable String name){

}/<code>

4.2 put跟patch的区别

上面没有讲到一种patch请求,该请求也是更新请求,但是是局部更新。什么是局部更新?加入有个user类,你更新他的所有属性,就用put。只更新username可以用put,但是显得很大题小作,因为put是全面替换。这时可以使用patch,仅更新username。

4.3 Options请求跟web.xml配置

如果涉及到跨域,在请求Restful之前,浏览器会先发送一个Options请求给后台,询问该接口/端点支持哪些方法。所以需要配置该许可。

<code><servlet>
<servlet-name>appServlet/<servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet/<servlet-class>
<init-param>

<param-name>dispatchOptionsRequest/<param-name>
<param-value>true/<param-value>

<param-name>contextConfigLocation/<param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml/<param-value>
/<init-param>
<load-on-startup>1/<load-on-startup>
/<servlet>/<code>

原文:https://www.tuicool.com/articles/iAbEra3


分享到:


相關文章: