Spring Boot 功能整合的實(shí)現(xiàn)
前言
如果根據(jù)之前做的 Nest.js 后端項(xiàng)目功能為標(biāo)準(zhǔn)的話,那么 Spring Boot 項(xiàng)目需要幾種功能進(jìn)行整合,好在生態(tài)豐富,集成也不算困難。所以打算根據(jù)之前的項(xiàng)目使用 Spring Boot 重寫個(gè)新的項(xiàng)目:
- Restful API CRUD 功能實(shí)現(xiàn)
- 數(shù)據(jù)庫(kù)對(duì)象關(guān)系映射功能持久化支持
- OpenAPI 文檔支持
- 參數(shù)校驗(yàn)判斷業(yè)務(wù)
- redis 緩存
- ...
數(shù)據(jù)庫(kù)持久化支持
目前數(shù)據(jù)庫(kù)持久化主要是 Spring Boot Jpa 和 Spring Boot Mybatis 。如果看過(guò) JPA 的業(yè)務(wù)過(guò)程會(huì)發(fā)現(xiàn)和 Nodejs 中的 TypeORM 及其相似。Mybatis 主要可以靈活調(diào)試動(dòng)態(tài) Sql 。不管怎么說(shuō)根據(jù)自己項(xiàng)目業(yè)務(wù)需求選定其中功能吧。
安裝 MyBatis 教程可以官方文檔查閱:mybatis-spring-boot-autoconfigure
Swagger 文檔支持
集成 Swagger UI 文檔支持也非常簡(jiǎn)單,生態(tài)中的 springfox 做的不錯(cuò),添加依賴:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
這里需要指定版本,不指定拉取依賴會(huì)報(bào)錯(cuò)。
然后在啟動(dòng)方法添加注解:
@EnableOpenApi public class YasuoApplication { public static void main(String[] args) { // ... } }
然后在 Controller 類上添加標(biāo)識(shí):
@Api(value = "global", tags = "全局接口") @RestController @RequestMapping("/") public class AppController { }
在然后在方法里添加詳細(xì)信息:
@Api(value = "global", tags = "全局接口") @RestController @RequestMapping("/") public class AppController { UserService userService; @ApiOperation(value = "用戶登錄", notes = "系統(tǒng)用戶登錄") @PostMapping("login") public JSONObject login(@RequestParam("username") String username, @RequestParam("password") String password) { System.out.println(username); System.out.println(password); JSONObject info = new JSONObject(); return info; } }
啟動(dòng)項(xiàng)目訪問(wèn):http://localhost:8080/swagger-ui 即可訪問(wèn)。值得注意是如果你在 application 添加 server.servlet.contextPath 選項(xiàng)的時(shí)候記得添加對(duì)應(yīng)的字段。
參數(shù)校驗(yàn) JSR303
從 springboot-2.3 開始,校驗(yàn)包被獨(dú)立成了一個(gè) starter 組件:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
比如在 DTO 類里:
package com.iiong.yasuo.dto; import lombok.Data; import javax.validation.constraints.NotEmpty; /** * Author: Jaxson * Description: 請(qǐng)求用戶登錄參數(shù) * Date: 2021-05-26 */ @Data public class UserLoginRequestDTO { @NotEmpty(message = "登錄名稱不得為空!") private String username; @NotEmpty(message = "登錄密碼不得為空!") private String password; }
內(nèi)置的校驗(yàn)注解可以查看官方文檔,然后進(jìn)行參數(shù)校驗(yàn):
@ApiOperation(value = "用戶登錄", notes = "系統(tǒng)用戶登錄") @PostMapping("login") public RestfulModel<UserLoginResponseDTO> login(@RequestBody @Validated UserLoginRequestDTO userLoginRequestDTO) { System.out.println(userLoginRequestDTO); UserLoginResponseDTO userLoginResponseDTO = new UserLoginResponseDTO(); userLoginResponseDTO.setId(1013401346173L); userLoginResponseDTO.setLoginName("112233"); userLoginResponseDTO.setName("系統(tǒng)管理員"); userLoginResponseDTO.setToken("test"); return new RestfulModel<>(0, "登錄成功!", userLoginResponseDTO); }
不過(guò)默認(rèn)返回的異常信息并不是很友好,需要再次簡(jiǎn)化,所以需要做個(gè)全局異常處理。如果需要可以使用 @RestControllerAdvice 注解來(lái)表示全局處理類:
/** * Author: Jaxson * Description: 全局異常處理類 * Date: 2021-05-26 */ @ControllerAdvice public class ExceptionHandlerConfig { /** * 統(tǒng)一處理參數(shù)校驗(yàn)異常 * @param bindException 捕捉到的異常 * @return 返回?cái)?shù)據(jù) */ @ExceptionHandler(value = BindException.class) @ResponseBody public RestfulModel<Object> validExceptionHandler(BindException bindException) { String exceptionMsg = bindException.getBindingResult().getAllErrors().get(0).getDefaultMessage(); return new RestfulModel<>(1000, exceptionMsg, null); } }
當(dāng)然這里面還可以處理一些系統(tǒng)級(jí)別的異常,自己拋出即可。
跨域解決
解決跨域問(wèn)題也很簡(jiǎn)單,只需要實(shí)現(xiàn)接口 WebMvcConfigurer 重寫方法即可:
/** * Author: Jaxson * Description: 運(yùn)行跨域 * Date: 2021-05-26 */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry corsRegistry) { corsRegistry.addMapping("/**") .allowedOriginPatterns("*") .allowedHeaders(CorsConfiguration.ALL) .allowedMethods(CorsConfiguration.ALL) .allowCredentials(true) .maxAge(3600); // 1小時(shí)內(nèi)不需要再預(yù)檢(發(fā)OPTIONS請(qǐng)求) } }
整合MongoDB實(shí)現(xiàn)文件上傳下載刪除
引入pom依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
配置yml
spring: data: mongodb: host: *.*.*.* username: *** password: *** database: *** port: 27017 # 設(shè)置文件上傳的大小限制 servlet: multipart: max-file-size: 10MB max-request-size: 50MB
上傳下載刪除
/** * @author Mr.Horse * @version 1.0 * @description: MongoDB的文件上傳、下載、刪除等基本操作(集合HuTool工具庫(kù)) * @date 2021/4/29 9:53 */ @Validated @Controller @RequestMapping("/mongo") public class MongoUploadController { private static Logger logger = LoggerFactory.getLogger(MongoUploadController.class); @Autowired private GridFsTemplate gridFsTemplate; @Autowired private MongoTemplate mongoTemplate; private static final List<String> CONTENT_TYPES = Arrays.asList("image/gif", "image/jpeg", "image/jpg", "image/png"); /** * MongoDB文件上傳(圖片上傳) * * @param file * @return */ @PostMapping("/upload") public ResponseEntity<String> fileUpload(@RequestParam("file") MultipartFile file) { try { // 校驗(yàn)文件信息(文件類型,文件內(nèi)容) String originalFilename = file.getOriginalFilename(); if (StrUtil.isBlank(originalFilename)) { return ResponseEntity.badRequest().body("參數(shù)錯(cuò)誤"); } String contentType = file.getContentType(); if (!CONTENT_TYPES.contains(contentType)) { return ResponseEntity.badRequest().body("文件類型錯(cuò)誤"); } InputStream inputStream = file.getInputStream(); BufferedImage bufferedImage = ImageIO.read(inputStream); if (ObjectUtil.isEmpty(bufferedImage)) { return ResponseEntity.badRequest().body("文件內(nèi)容錯(cuò)誤"); } // 文件重命名 String suffix = FileNameUtil.getSuffix(originalFilename); String fileName = IdUtil.simpleUUID().concat(".").concat(suffix); // 文件上傳,返回ObjectId ObjectId objectId = gridFsTemplate.store(inputStream, fileName, contentType); return StrUtil.isBlank(String.valueOf(objectId)) ? ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上傳失敗") : ResponseEntity.ok(String.valueOf(objectId)); } catch (IOException e) { return ResponseEntity.badRequest().body("文件上傳異常"); } } /** * 根據(jù)ObjectId讀取文件并寫入響應(yīng)流,頁(yè)面進(jìn)行進(jìn)行相關(guān)操作,可以進(jìn)行文件的下載和展示 * * @param objectId */ @GetMapping("/read") public void queryFileByObjectId(@RequestParam("objectId") @NotBlank(message = "ObjectId不能為空") String objectId, HttpServletResponse response) { // 根據(jù)objectId查詢文件 GridFSFile file = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(objectId))); // 創(chuàng)建一個(gè)文件桶 GridFSBucket gridFsBucket = GridFSBuckets.create(mongoTemplate.getDb()); InputStream inputStream = null; OutputStream outputStream = null; try { if (ObjectUtil.isNotNull(file)) { // 打開下載流對(duì)象 GridFSDownloadStream fileStream = gridFsBucket.openDownloadStream(file.getObjectId()); // 創(chuàng)建girdFsResource,傳入下載流對(duì)象,獲取流對(duì)象 GridFsResource gridFsResource = new GridFsResource(file, fileStream); // 寫入輸出流 inputStream = gridFsResource.getInputStream(); outputStream = response.getOutputStream(); byte[] bytes = new byte[1024]; if (inputStream.read(bytes) != -1) { outputStream.write(bytes); } } } catch (IOException e) { logger.error("文件讀取異常: {}", e.getMessage()); } finally { IoUtil.close(outputStream); IoUtil.close(inputStream); } } /** * 根據(jù)ObjectId刪除文件 * * @param objectId * @return */ @DeleteMapping("/remove") public ResponseEntity<String> removeFileByObjectId(@RequestParam("objectId") @NotBlank(message = "ObjectId不能為空") String objectId) { gridFsTemplate.delete(new Query(Criteria.where("_id").is(objectId))); return ResponseEntity.ok("刪除成功"); } }
如果需要實(shí)現(xiàn)在瀏覽器頁(yè)面下載此資源的功能,可結(jié)合js進(jìn)行操作(文件類型根據(jù)具體業(yè)務(wù)需求而定)。主要實(shí)現(xiàn)代碼如下所示:
downloadNotes(noteId) { axios({ url: this.BASE_API + '/admin/mongo/file/query/' + noteId, method: 'get', responseType: 'arraybuffer', params: { type: 'download' } }).then(res => { // type類型可以設(shè)置為文本類型,這里是pdf類型 const pdfUrl = window.URL.createObjectURL(new Blob([res.data], { type: `application/pdf` })) const fname = noteId // 下載文件的名字 const link = document.createElement('a') link.href = pdfUrl link.setAttribute('download', fname) document.body.appendChild(link) link.click() URL.revokeObjectURL(pdfUrl) // 釋放URL 對(duì)象 }) }
以上就是Spring Boot 功能整合的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot 功能整合的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot整合Drools的實(shí)現(xiàn)步驟
- SpringBoot整合MongoDB的實(shí)現(xiàn)代碼
- SpringBoot整合Redisson的步驟(單機(jī)版)
- springboot整合RabbitMQ發(fā)送短信的實(shí)現(xiàn)
- Java基礎(chǔ)之SpringBoot整合knife4j
- SpringBoot整合MyBatis超詳細(xì)教程
- SpringBoot整合JDBC、Druid數(shù)據(jù)源的示例代碼
- SpringBoot整合EasyExcel實(shí)現(xiàn)文件導(dǎo)入導(dǎo)出
- SpringBoot整合MongoDB實(shí)現(xiàn)文件上傳下載刪除
- springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法
- springboot2.x只需兩步快速整合log4j2的方法
相關(guān)文章
idea一鍵部署SpringBoot項(xiàng)目jar包到服務(wù)器的實(shí)現(xiàn)
我們?cè)陂_發(fā)環(huán)境部署項(xiàng)目一般通過(guò)idea將項(xiàng)目打包成jar包,然后連接linux服務(wù)器,將jar手動(dòng)上傳到服務(wù)中,本文就來(lái)詳細(xì)的介紹一下步驟,感興趣的可以了解一下2023-12-12SpringBoot打包成Docker鏡像的幾種實(shí)現(xiàn)方式
Spring Boot是一個(gè)用于構(gòu)建獨(dú)立的、可執(zhí)行的Spring應(yīng)用程序的框架,結(jié)合使用Spring Boot和Docker,可以方便地將應(yīng)用程序部署到不同的環(huán)境中本文,主要介紹了SpringBoot打包成Docker鏡像的幾種實(shí)現(xiàn)方式,感興趣的可以了解一下2024-01-01Mybatis Plus ActiveRecord模式的具體使用
ActiveRecord 是一種設(shè)計(jì)模式,它是一種在軟件開發(fā)中用于管理關(guān)系數(shù)據(jù)庫(kù)的模式,本文主要介紹了Mybatis Plus ActiveRecord模式的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07java抓取12306信息實(shí)現(xiàn)火車余票查詢示例
這篇文章主要介紹了java抓取12306信息實(shí)現(xiàn)火車余票查詢示例,需要的朋友可以參考下2014-04-04SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置的實(shí)例詳解
這篇文章主要介紹了SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置的實(shí)例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11spring-boot 如何實(shí)現(xiàn)單次執(zhí)行程序
這篇文章主要介紹了spring-boot 實(shí)現(xiàn)單次執(zhí)行程序方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09