Spring Boot 功能整合的实现

前言

如果根据之前做的 Nest.js 后端项目功能为标准的话,那么 Spring Boot 项目需要几种功能进行整合,好在生态丰富,集成也不算困难。所以打算根据之前的项目使用 Spring Boot 重写个新的项目:

  • Restful API CRUD 功能实现
  • 数据库对象关系映射功能持久化支持
  • OpenAPI 文档支持
  • 参数校验判断业务
  • redis 缓存
  • ...

数据库持久化支持

目前数据库持久化主要是 Spring Boot Jpa 和 Spring Boot Mybatis 。如果看过 JPA 的业务过程会发现和 Nodejs 中的 TypeORM 及其相似。Mybatis 主要可以灵活调试动态 Sql 。不管怎么说根据自己项目业务需求选定其中功能吧。

安装 MyBatis 教程可以官方文档查阅:mybatis-spring-boot-autoconfigure

Swagger 文档支持

集成 Swagger UI 文档支持也非常简单,生态中的 springfox 做的不错,添加依赖:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
</dependency>

这里需要指定版本,不指定拉取依赖会报错。

然后在启动方法添加注解:

@EnableOpenApi
public class YasuoApplication {
	public static void main(String[] args) {
    // ...
	}
}

然后在 Controller 类上添加标识:

@Api(value = "global", tags = "全局接口")
@RestController
@RequestMapping("/")
public class AppController {
}

在然后在方法里添加详细信息:

@Api(value = "global", tags = "全局接口")
@RestController
@RequestMapping("/")
public class AppController {
    UserService userService;

    @ApiOperation(value = "用户登录", notes = "系统用户登录")
    @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;
    }
}

启动项目访问:http://localhost:8080/swagger-ui 即可访问。值得注意是如果你在 application 添加 server.servlet.contextPath 选项的时候记得添加对应的字段。

参数校验 JSR303

从 springboot-2.3 开始,校验包被独立成了一个 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: 请求用户登录参数
 * Date: 2021-05-26
 */
@Data
public class UserLoginRequestDTO {
    @NotEmpty(message = "登录名称不得为空!")
    private String username;

    @NotEmpty(message = "登录密码不得为空!")
    private String password;
}

内置的校验注解可以查看官方文档,然后进行参数校验:

@ApiOperation(value = "用户登录", notes = "系统用户登录")
@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("系统管理员");
    userLoginResponseDTO.setToken("test");
    return new RestfulModel<>(0, "登录成功!", userLoginResponseDTO);
}

不过默认返回的异常信息并不是很友好,需要再次简化,所以需要做个全局异常处理。如果需要可以使用 @RestControllerAdvice 注解来表示全局处理类:

/**
 * Author: Jaxson
 * Description: 全局异常处理类
 * Date: 2021-05-26
 */
@ControllerAdvice
public class ExceptionHandlerConfig {

    /**
     * 统一处理参数校验异常
     * @param bindException 捕捉到的异常
     * @return 返回数据
     */
    @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);
    }
}

当然这里面还可以处理一些系统级别的异常,自己抛出即可。

跨域解决

解决跨域问题也很简单,只需要实现接口 WebMvcConfigurer 重写方法即可:

/**
 * Author: Jaxson
 * Description: 运行跨域
 * 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小时内不需要再预检(发OPTIONS请求)
    }
}

整合MongoDB实现文件上传下载删除

引入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
 # 设置文件上传的大小限制
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 50MB

上传下载删除

/**
 * @author Mr.Horse
 * @version 1.0
 * @description: MongoDB的文件上传、下载、删除等基本操作(集合HuTool工具库)
 * @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 {
            // 校验文件信息(文件类型,文件内容)
            String originalFilename = file.getOriginalFilename();
            if (StrUtil.isBlank(originalFilename)) {
                return ResponseEntity.badRequest().body("参数错误");
            }
            String contentType = file.getContentType();
            if (!CONTENT_TYPES.contains(contentType)) {
                return ResponseEntity.badRequest().body("文件类型错误");
            }
            InputStream inputStream = file.getInputStream();
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            if (ObjectUtil.isEmpty(bufferedImage)) {
                return ResponseEntity.badRequest().body("文件内容错误");
            }

            // 文件重命名
            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("文件上传异常");
        }
    }

    /**
     * 根据ObjectId读取文件并写入响应流,页面进行进行相关操作,可以进行文件的下载和展示
     *
     * @param objectId
     */
    @GetMapping("/read")
    public void queryFileByObjectId(@RequestParam("objectId") @NotBlank(message = "ObjectId不能为空") String objectId, HttpServletResponse response) {
        // 根据objectId查询文件
        GridFSFile file = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(objectId)));
        // 创建一个文件桶
        GridFSBucket gridFsBucket = GridFSBuckets.create(mongoTemplate.getDb());
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            if (ObjectUtil.isNotNull(file)) {
                // 打开下载流对象
                GridFSDownloadStream fileStream = gridFsBucket.openDownloadStream(file.getObjectId());
                // 创建girdFsResource,传入下载流对象,获取流对象
                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);
        }
    }

    /**
     * 根据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("删除成功");
    }

}

如果需要实现在浏览器页面下载此资源的功能,可结合js进行操作(文件类型根据具体业务需求而定)。主要实现代码如下所示:

    downloadNotes(noteId) {
      axios({
        url: this.BASE_API + '/admin/mongo/file/query/' + noteId,
        method: 'get',
        responseType: 'arraybuffer',
        params: { type: 'download' }
      }).then(res => {
        // type类型可以设置为文本类型,这里是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 对象
      })
    }

以上就是Spring Boot 功能整合的实现的详细内容,更多关于Spring Boot 功能整合的资料请关注我们其它相关文章!

(0)

相关推荐

  • SpringBoot整合MongoDB实现文件上传下载删除

    本文主要内容 MongoDB基础操作命令示例练习 MongoDB居于GridFSTemplate的文件上传.下载.删除等操作(工作重点使用) 1. 基础命令 创建的数据库名称:horse,创建的集合名称:blog # 创建数据库 use horse # 删除当前数据库[horse] db.dropDatebase() # 查看所有数据库 show dbs # 设置用户的角色和权限 db.createUser({user:"horse",pwd:"mongo123",

  • SpringBoot整合MongoDB的实现代码

    MongoDB官网安装: https://www.mongodb.com/download-center/community MongoDB客户端工具(Mongo Management Studio)安装: http://mms.litixsoft.de/#software_pricing 一.添加Maven依赖 <!--mongodb--> <dependency> <groupId>org.springframework.boot</groupId> &

  • springboot整合RabbitMQ发送短信的实现

    RabbitMQ安装和运行 # 安装 rpm -ivh erlang-21.3.8.9-1.el7.x86_64.rpm rpm -ivh socat-1.7.3.2-1.el6.lux.x86_64.rpm rpm -ivh rabbitmq-server-3.8.1-1.el7.noarch.rpm # 卸载 #rpm -qa | grep rabbitmq # 启用管理插件 rabbitmq-plugins enable rabbitmq_management # 启动RabbitMQ s

  • SpringBoot整合MyBatis超详细教程

    1.整合MyBatis操作 前面一篇提到了SpringBoot整合基础的数据源JDBC.Druid操作,实际项目中更常用的还是MyBatis框架,而SpringBoot整合MyBatis进行CRUD也非常方便. 下面从配置模式.注解模式.混合模式三个方面进行说明MyBatis与SpringBoot的整合. 1.1.配置模式 MyBatis配置模式是指使用mybatis配置文件的方式与SpringBoot进行整合,相对应的就有mybatis-config.xml(用于配置驼峰命名,也可以省略这个文

  • SpringBoot整合EasyExcel实现文件导入导出

    准备工作 注意:点击查看官网Demo 1. 引入pom依赖 <!--easyExcel--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> </dependency> 2. 实现功能 结合Vue前端,实现浏览器页面直接导出日志文件 实现文件的导入 Excel文件下载 3. 日志实体类 实体类里有自定义转换器:用于

  • SpringBoot整合Redisson的步骤(单机版)

    Redisson.Jedis.Lettuce优缺点对比 (1)Redisson 优点: 实现了分布式特性和可扩展的 Java 数据结构,适合分布式开发: API线程安全: 基于Netty框架的事件驱动的通信,可异步调用. 缺点: API更抽象,学习使用成本高. (2)Jedis 优点: 提供了比较全面的Redis操作特性的API API基本与Redis的指令一一对应,使用简单易理解. 缺点: 同步阻塞IO: 不支持异步: 线程不安全. (3)Lettuce 优点: 线程安全; 基于Netty 框

  • SpringBoot整合JDBC、Druid数据源的示例代码

    1.SpringBoot整合JDBCTemplate 1.1.导入jdbc相关依赖包 主要的依赖包: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</gro

  • SpringBoot整合Drools的实现步骤

    Drools有什么用 从我个人所待过的公司,其中做智能酒店这个项目时就用到规则引擎Drools,将它用于处理优惠劵规则. SpringBoot整合Drools初步实战 1.导入Maven依赖 <properties> <drools.version>7.14.0.Final</drools.version> </properties> <!-- drools --> <dependency> <groupId>org.dr

  • springboot cloud使用eureka整合分布式事务组件Seata 的方法

    前言 近期一直在忙项目,我也是打工仔.不多说,我们开始玩一玩seata. 正文 什么都不说,我们按照惯例,先上一个图(图里不规范的使用请忽略): 简单一眼就看出来, 比我们平时用的东西,多了 Seata Server 微服务 . 同样这个 Seata Server 微服务 ,也是需要注册到eureka上面去的. 那么我们首先就搞一搞这个 seata server ,那么剩下的就是一些原本的业务服务整合配置了. 该篇用的 seata server 版本,用的是1.4.1 , 可以去git下载下.当

  • Java基础之SpringBoot整合knife4j

    插件的特点 1.非常简洁清爽的UI设计,接口的快速搜索. 2.支持个性化设置,个性化设置包含: 请求参数缓存 动态请求参数 RequestMapping接口过滤 HOST代理设置 3.全局参数设置,可以很方便的设置Token等权限认证参数. 4.离线API文档下载: Markdown(已支持) Html(已支持) Word(已支持) OpenApi(已支持) 5.对 json 格式的数据有更好的支持,可以折叠展开等. knife4j官方文档地址 : https://doc.xiaominfo.c

  • springboot2.x只需两步快速整合log4j2的方法

    前言 本文详细介绍如何使用spring-boot2.x快速整合log4j2日志框架. spring-boot2.x使用logback作为默认日志处理库,因此我们除了要引用log4j2之外,还要去除logback的依赖 1.依赖库 maven方式: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifac

随机推荐