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


分享到:


相關文章: