springboot+mybaits-plus+shiro微服务接口搭建改造(JAVA11版本)

springboot微服务接口完整搭建(JAVA11)

这两天业余时间把MarkerHub的一个微服务开源项目亲手搭建了一遍,顺手把千年的Java8换成了Java11,springboot版本换成了2.3.0,没办法我用的最新版的Vscode开发工具强迫我改JAVA11…代码不亲手实践一遍,等于白学,只要一动手,绝对会发现一堆坑,知行合一,果然古人诚不欺我,该项目是一个经典的前后端分离的博客项目,后端采用SpringBoot,mybatis plus,shiro,数据库是用的mysql,在这里写一下亲测改造后的总结汇总。

文章目录

  • springboot微服务接口完整搭建(JAVA11)
    • 1. VsCode配置
    • 2. 数据库创建
    • 3. 整合mybaits-plus
      • 3.1 依赖配置
      • 3.2 mysql配置文件
      • 3.3 代码生成器
      • 3.4 添加配置类
      • 3.5 官方指导文档
    • 4. 配置shiro与jwt
      • 4.1 依赖包
      • 4.2 具体实现链接
    • 5. 结果与异常的统一处理与封装
      • 5.1 封装返回结果
      • 5.2 封装全局异常
    • 6. 实体检验
    • 7. 跨域处理
    • 8. 项目结构
    • 9. 原项目文档及链接

1. VsCode配置

因为比较喜欢用VsCode的轻量,所以本次搭建项目的IDE选择Vscode,具体过程如下:
Ctrl+Shift+P 调出命令行,选择输入Spring,选择SpringBoot扩展插件生成项目,如果配置过程中出现卡顿,则换用国内的阿里云的脚手架url,具体配置如下:JDK11,Spring boot 2.3.0…

.......
"spring.initializr.serviceUrl": [
    "https://start.aliyun.com/"
],
"spring.initializr.defaultGroupId": "xxxxx.xxxxx"
-------

之后一次填入包名和项目名称后,选择初始的依赖包 Spring Boot DevTools,Spring Web,MySQL Driver

2. 数据库创建

就用人家已经创建好的博客数据库当做实例。

CREATE TABLE `tbuser` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(64) DEFAULT NULL,
  `avatar` varchar(255) DEFAULT NULL,
  `email` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL,
  `status` int(5) NOT NULL,
  `created` datetime DEFAULT NULL,
  `last_login` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `UK_USERNAME` (`username`) USING BTREE
);

CREATE TABLE `tbblog` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL,
  `title` varchar(255) NOT NULL,
  `description` varchar(255) NOT NULL,
  `content` longtext,
  `created` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  `status` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

3. 整合mybaits-plus

3.1 依赖配置


<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-boot-starterartifactId>
    <version>3.2.0version>
dependency>

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-freemarkerartifactId>
dependency>

<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-generatorartifactId>
    <version>3.2.0version>
dependency>

3.2 mysql配置文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/springblogdb?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: xxxxxx
mybatis-plus:
  mapper-locations: classpath*:/mapper/**Mapper.xml
server:
  port: 8081

3.3 代码生成器

在入口函数文件同级目录下新建CodeGenerator.java代码生成器源码文件,输入如下代码,之后编译执行该源码生成项目结构。


// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {

    /**
     * 

* 读取控制台内容 *

*/
public static String scanner(String tip) { Scanner scanner = new Scanner(System.in); StringBuilder help = new StringBuilder(); help.append("请输入" + tip + ":"); System.out.println(help.toString()); if (scanner.hasNext()) { String ipt = scanner.next(); if (StringUtils.isNotEmpty(ipt)) { return ipt; } } throw new MybatisPlusException("请输入正确的" + tip + "!"); } public static void main(String[] args) { // 代码生成器 AutoGenerator mpg = new AutoGenerator(); // 全局配置 GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); gc.setOutputDir(projectPath + "/src/main/java"); // gc.setOutputDir("D:\\test"); gc.setAuthor("dahlin"); gc.setOpen(false); // gc.setSwagger2(true); 实体属性 Swagger2 注解 gc.setServiceName("%sService"); mpg.setGlobalConfig(gc); // 数据源配置 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://127.0.0.1:3306/springblogdb?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC"); // dsc.setSchemaName("public"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("xxxxxx"); mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig(); pc.setModuleName(null); pc.setParent("cn.zhousonglin.blogspring"); mpg.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; // 如果模板引擎是 freemarker String templatePath = "/templates/mapper.xml.ftl"; // 如果模板引擎是 velocity // String templatePath = "/templates/mapper.xml.vm"; // 自定义输出配置 List<FileOutConfig> focList = new ArrayList<>(); // 自定义配置会被优先输出 focList.add(new FileOutConfig(templatePath) { @Override public String outputFile(TableInfo tableInfo) { // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!! return projectPath + "/src/main/resources/mapper/" + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); // 配置模板 TemplateConfig templateConfig = new TemplateConfig(); templateConfig.setXml(null); mpg.setTemplate(templateConfig); // 策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); strategy.setRestControllerStyle(true); strategy.setInclude(scanner("表名,多个英文逗号分割").split(",")); strategy.setControllerMappingHyphenStyle(true); strategy.setTablePrefix("tb"); mpg.setStrategy(strategy); mpg.setTemplateEngine(new FreemarkerTemplateEngine()); mpg.execute(); } }

3.4 添加配置类

新建同级目录config,之后再config下新建MybatisPlusConfig.java分页插件

@Configuration
@EnableTransactionManagement
@MapperScan("cn.zhousonglin.mapper")
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }
}

3.5 官方指导文档

https://mp.baomidou.com/guide/install.html

4. 配置shiro与jwt

4.1 依赖包

此处坑比较多,在编写Jwt生成generateToken的方法时,会报一个java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter错误, 大概原因由于JAXB API是java EE 的API,因此在java SE 9.0 中不再包含这个 Jar 包。java 9 中引入了模块的概念,默认情况下,Java SE中将不再包含java EE 的Jar包,而在 java 6/7 / 8 时关于这个API 都是捆绑在一起的,所以改造方法就是手动添加缺失的依赖

<dependency>
        <groupId>javax.xml.bindgroupId>
        <artifactId>jaxb-apiartifactId>
        <version>2.3.0version>
    dependency>
    <dependency>
        <groupId>com.sun.xml.bindgroupId>
        <artifactId>jaxb-implartifactId>
        <version>2.3.0version>
    dependency>
    <dependency>
        <groupId>com.sun.xml.bindgroupId>
        <artifactId>jaxb-coreartifactId>
        <version>2.3.0version>
    dependency>
    <dependency>
        <groupId>javax.activationgroupId>
        <artifactId>activationartifactId>
        <version>1.1.1version>
    dependency>

之后就简单了,加入shiro与jwt的相关依赖如下。



<dependency>
    <groupId>org.crazycakegroupId>
    <artifactId>shiro-redis-spring-boot-starterartifactId>
    <version>3.2.1version>
dependency>

<dependency>
    <groupId>cn.hutoolgroupId>
    <artifactId>hutool-allartifactId>
    <version>5.3.3version>
dependency>

<dependency>
    <groupId>io.jsonwebtokengroupId>
    <artifactId>jjwtartifactId>
    <version>0.9.1version>
dependency>

4.2 具体实现链接

由于代码实在太多了,就把人家原版的文档和代码链接都贴出来了,如下:
《超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!》
https://juejin.im/post/5ecfca676fb9a04793456fb8

5. 结果与异常的统一处理与封装

5.1 封装返回结果

这里需要注意一下,由于JAVA11中lombok会出现失效的问题,所以建议都把@Data,自己写set和get方法,其实也不用自己写,用插件生成就行。

public class Result implements Serializable {

    private static final long serialVersionUID = 1L;
    private int code; // 200是正常,非200表示异常
    private String msg;
    private Object data;
    
    // get,set自己生成出来.....

    public static Result success(Object data) {
        return success(200, "操作成功", data);
    }

    public static Result success(int code, String msg, Object data) {
        Result r = new Result();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

    public static Result fail(String msg) {
        return fail(400, msg, null);
    }

    public static Result fail(String msg, Object data) {
        return fail(400, msg, data);
    }

    public static Result fail(int code, String msg, Object data) {
        Result r = new Result();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

}

postman测试样例截图:
springboot+mybaits-plus+shiro微服务接口搭建改造(JAVA11版本)_第1张图片

5.2 封装全局异常

通过使用@ControllerAdvice来进行统一异常处理,@ExceptionHandler(value = RuntimeException.class)来指定捕获的Exception各个类型异常 ,这个异常的处理,是全局的。

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    
    // shiro抛出的异常,比如没有权限,用户登录异常
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(value = ShiroException.class)
    public Result handler(ShiroException e) {
        log.error("运行时异常:----------------{}", e);
        return Result.fail(401, e.getMessage(), null);
    }

    // 处理实体校验的异常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handler(MethodArgumentNotValidException e) {
        log.error("实体校验异常:----------------{}", e);
        BindingResult bindingResult = e.getBindingResult();
        ObjectError objectError = bindingResult.getAllErrors().stream().findFirst().get();

        return Result.fail(objectError.getDefaultMessage());
    }

    // 处理Assert的异常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result handler(IllegalArgumentException e) {
        log.error("Assert异常:----------------{}", e);
        return Result.fail(e.getMessage());
    }

    // 捕捉其他异常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = RuntimeException.class)
    public Result handler(RuntimeException e) {
        log.error("运行时异常:----------------{}", e);
        return Result.fail(e.getMessage());
    }
}

postman测试截图
springboot+mybaits-plus+shiro微服务接口搭建改造(JAVA11版本)_第2张图片

6. 实体检验

实体校验没啥可说的,代码照着人家的文档来就行,但是在JAVA11中必须添加一个依赖才行


<dependency>
    <groupId>javax.validationgroupId>
    <artifactId>validation-apiartifactId>
    <version>2.0.1.Finalversion>
dependency>

还有涉及到时间校验必须加入如下注解:


@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime created;

7. 跨域处理

因为是前后端分离的,所以涉及到跨域问题,代码如下

/**
 * 解决跨域问题
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

8. 项目结构

跟原来人家的代码结构略微不同,但大同小异,根据自己的习惯来就好
springboot+mybaits-plus+shiro微服务接口搭建改造(JAVA11版本)_第3张图片

9. 原项目文档及链接

《超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!》

你可能感兴趣的:(Java,java,spring,boot,shiro,jwt,java11)