• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

做个俗人

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

(二)Springboot + vue + 达梦数据库构建RBAC权限模型前后端分离脚手架保姆级教程(后端项目)

XX后台管理系统

开源地址:git clone https://gitee.com/mrlumin/x-dm-server.git

Springboot + vue + dm8 的前后端分离项目,后端项目

https://spring.io
https://start.aliyun.com

1. 创建项目

初始化项目,导入坐标

web、lombok、devtools
<!-- web start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- web end -->

<!-- devtools start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>
<!-- devtools end -->

<!-- lombok start -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<!-- lombok end -->

2.整合Swagger3

2.1 导入swagger3坐标

<swagger3.version>3.0.0</swagger3.version>
<!-- swagger3 start  -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>${swagger3.version}</version>
</dependency>
<!-- swagger3 end -->

2.2 编写swagger3配置类

package org.cn.common.config;

import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Configuration
@EnableOpenApi
@EnableWebMvc
public class Swagger3Config {

    /**
     * 创建API
     * http:localhost:9999/swagger-ui/index.html 原生地址
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.OAS_30).pathMapping("/")
                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
                /*.enable(enable)*/
                .apiInfo(apiInfo())
                // 设置哪些接口暴露给Swagger展示
                .select()
                // 扫描所有有注解的api,用这种方式更灵活
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                // 扫描指定包中的swagger注解
                //.apis(RequestHandlerSelectors.basePackage("com.cn"))
                // 扫描所有 .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.regex("(?!/ApiError.*).*"))
                .paths(PathSelectors.any())
                .build()
                // 支持的通讯协议集合
                .protocols(newHashSet("https", "http"))
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());

    }

    /**
     * 支持的通讯协议集合
     *
     * @param type1
     * @param type2
     * @return
     */
    private Set<String> newHashSet(String type1, String type2) {
        Set<String> set = new HashSet<>();
        set.add(type1);
        set.add(type2);
        return set;
    }

    /**
     * 认证的安全上下文
     */
    private List<SecurityScheme> securitySchemes() {
        List<SecurityScheme> securitySchemes = new ArrayList<>();
        securitySchemes.add(new ApiKey("Authorization", "Authorization", "header"));
        return securitySchemes;
    }

    /**
     * 授权信息全局应用
     */
    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.any()).build());
        return securityContexts;
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }


    /**
     * 添加摘要信息
     * @return 返回ApiInfo对象
     */
    private ApiInfo apiInfo() {
        // 用ApiInfoBuilder进行定制
        return new ApiInfoBuilder()
                // 设置标题
                .title("接口文档")
                // 服务条款
                .termsOfServiceUrl("NO terms of service")
                // 描述
                .description("权限模型管理系统-接口文档")
                // 作者信息
                .contact(new Contact("LM", "https://www.cnblogs.com/longronglang/", "lumin@gmail.com"))
                // 版本
                .version("版本号:V1.0")
                //协议
                .license("The Apache License")
                // 协议url
                .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html")
                .build();
    }
}

2.3 swagger3注解测试

新增测试类、测试方法等,加上Swagger3注解进行测试

http:localhost:9999/swagger-ui/index.html

@Api(tags = "用户管理")
@ApiOperation("用户登录")
http://localhost:9999/swagger-ui/index.html

3. 代码自动生成

3.1 引入MP&DB坐标

mybatis-plus-boot-starter、mybatis-plus-generator、freemarker、dameng

注意:mybatis-plus 坐标引入的是mybatis-plus启动坐标和代码生成坐标

<dm.version>8.1.2.192</dm.version>
<mybatis-plus-boot.version>3.5.3.1</mybatis-plus-boot.version>
<mybatis-plus-generator.version>3.5.3.1</mybatis-plus-generator.version>
<!-- mybatis-plus-boot start -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus-boot.version}</version>
</dependency>
<!-- mybatis-plus-boot end -->

<!-- mybatis-plus-generator start -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>${mybatis-plus-generator.version}</version>
</dependency>
<!-- mybatis-plus-generator end -->

<!-- freemarker start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- freemarker end -->

<!-- dameng start -->
<dependency>
    <groupId>com.dameng</groupId>
    <artifactId>DmJdbcDriver18</artifactId>
    <version>${dm.version}</version>
</dependency>
<!-- dameng end -->

3.2 代码生成工具类编写

3.2.1 代码生成工具类
package generator;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Collections;

public class CodeGenerator {
    static String url ="jdbc:dm://LOCALHOST:5236";
    static String username ="SYSDBA";
    static String password ="SYSDBA001";
    static String moduleName ="system";
    static String javaLocation ="F:\\install\\workspace\\sty\\x-dm-server\\src\\main\\java";
    static String mapperLocation ="F:\\install\\workspace\\sty\\x-dm-server\\src\\main\\resources\\mapper\\";
    static String tables = "x_user,x_role,x_menu,x_user_role,x_role_menu";

    public static void main(String[] args) {

        FastAutoGenerator.create(url,username,password)
                .globalConfig(builder -> builder
                        .author("LuMin")
                        .enableSwagger() // 开启 swagger 模式
                        .fileOverride() // 覆盖已生成文件
                        .outputDir(javaLocation)
                        .commentDate("yyyy-MM-dd")
                )
                .packageConfig(builder -> builder
                        .parent("org.cn") // 设置父包名
                        .moduleName(moduleName) // 设置父包模块名
                        .entity("entity")
                        .mapper("mapper")
                        .service("service")
                        .serviceImpl("service.impl")
                        .pathInfo(Collections.singletonMap(OutputFile.xml, mapperLocation))
                )
                .strategyConfig(builder -> builder
                        .addInclude(tables) // 设置需要生成的表名
                        .addTablePrefix("x_") // 设置过滤表前缀
                        .entityBuilder()
                        .enableLombok()
                )
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }

    public static class Test {
        static Connection con = null;
        static String cname = "dm.jdbc.driver.DmDriver";
        static String url = "jdbc:dm://192.168.106.137:30236";
        static String userid = "SYSDBA";
        static String pwd = "SYSDBA001";
        public static void main(String[] args) {
            try {
                Class.forName(cname);
                con = DriverManager.getConnection(url, userid, pwd);
                con.setAutoCommit(true);
                System.out.println("[SUCCESS]conn database");
            } catch (Exception e){
                System.out.println("[FAIL]conn database:" + e.getMessage());
            }
        }

        public void disConn(Connection con) throws SQLException {
            if (con != null) {
                con.close();
            }
        }
    }
}
3.2.2 启动异常解决

注意生成代码之后,直接启动项目会报错,需要对项目信息进行修改

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'menuServiceImpl': Unsatisfied dependency expressed through field 'baseMapper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.cn.system.mapper.MenuMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
# ①修改启动类扫描的包
@SpringBootApplication(scanBasePackages = {"org.cn"})
@MapperScan(value = {"org.cn.*.mapper"})
# ②在Mapper接口上增加@Mapper类注解,启动还是会报错
initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'menuServiceImpl': Unsatisfied dependency expressed through field 'baseMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'menuMapper' defined in file
# ③删除创建项目默认生成的demos包,重新启动

3.3 application.yml配置

# server
server:
  port: 9999

# datasource
spring:
  datasource:
    url: jdbc:dm://LOCALHOST:5236/XGIS
    username: SYSDBA
    password: SYSDBA001
    driver-class-name: dm.jdbc.driver.DmDriver
  jpa:
    database-platform: org.hibernate.dialect.DMDialect
    hibernate:
      ddl-auto: update # 或者 create, create-drop, validate, none
    show-sql: true # 显示执行的 SQL 语句,便于调试
    properties:
      hibernate:
        format_sql: true # 格式化 SQL 语句输出
  redis:
    port: 6379
    password: Admin@123
    host: localhost

# mybatis-plus
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-not-delete-value: 0
      logic-delete-value: 1
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: org.cn

# logging
logging:
  charset:
    console: utf-8
  level:
    org.cn: debug

3.4 测试生成代码生成可用性

利用SpringBootJunit测试工具进行测试,在XDmServerApplicationTests类中新建testUserMapper()方法

package org.cn;

import org.cn.system.entity.User;
import org.cn.system.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;


@SpringBootTest
class XDmServerApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
    }

    @Test
    void testUserMapper () {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

foreach循环时没有打印出预期的内容(例如用户对象的某些属性),而是打印出了类似org.cn.system.entity.User@1ad1c363这样的内容,这通常意味着你没有正确覆写User类的toString方法。

org.cn.system.entity.User@76d0ecd7
org.cn.system.entity.User@57c69937
org.cn.system.entity.User@1ad1c363
org.cn.system.entity.User@446b64b3
org.cn.system.entity.User@35ac9ebd
org.cn.system.entity.User@56c0a61e

一是在User实体类中增加 toString()方法

二是在实体类上添加@Data/@NoArgsConstructor/@AllArgsConstructor注解

@Override
public String toString() {
    return "User{" +
            "id=" + id +
            ", username='" + username + '\'' +
            ", password='" + password + '\'' +
            ", email='" + email + '\'' +
            ", status='" + status + '\'' +
            ", phone=" + phone +
            ", avatar='" + avatar + '\'' +
            ", deleted=" + deleted +
            '}';
}

4. 统一结果返回封装

4.1 封装公共响应类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
/**
* 返回编码
/
private Integer code;
/
*
* 返回信息
/
private String message;
/
*
* 返回数据
*/
private T data;

/**
* 返回成功
* @return
* @param
*/
public static Result success(){
return new Result<>(20000, "success",null);
}

public static Result success(T data){
return new Result<>(20000, "success",data);
}
public static Result success(T data,String message){
return new Result<>(20000, message,data);
}

public static Result success(String message){
return new Result<>(20000, message,null);
}

/**
* 返回失败
* @return
* @param
*/
public static Result fail(){
return new Result<>(20001, "fail",null);
}
public static Result fail(Integer code){
return new Result<>(20001, "fail",null);
}
public static Result fail(Integer code,String message){
return new Result<>(20001, message,null);
}
public static Result fail(String message){
return new Result<>(20001, message,null);
}

}

4.2 测试公共响应类

修改控制器,测试公共响应类是否返回自定义数据

4.2.1 修改注解

修改UserController控制器的@Controller为@RestController

4.2.2 新增方法测试

在控制类中注入IUserService接口服务类,新增getUserList()测试方法进行测试

@Resource
private IUserService userService;

@GetMapping("/getUserList")
public Result<List<User>> getUserList() {
    List<User> userList = userService.list();
    return Result.success(userList, "查询成功");
}

5.实体类Lombok改造

5.1 删除注解

@Getter/@Setter是mybatis-plus-generator生成实体时自动添加的注解

@Getter
@Setter

5.2 新增注解

@Data/@NoArgsConstructor/@AllArgsConstructor是lombok中的注解

@Data
@NoArgsConstructor
@AllArgsConstructor

6.JWT登录实现

6.1 JWT 整合

6.1.1 导入Jwt坐标
spring-security-core、jjwt
<jjwt.version>0.9.1</jjwt.version>
<!-- spring-security-core start -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
</dependency>
<!-- spring-security-core end -->

<!-- jjwt  start -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>${jjwt.version}</version>
</dependency>
<!-- jjwt end -->
6.1.2 编写Jwt工具类

①在application.yml配置JWT令牌和有效期

# JWT 配置
jwt:
  secret-key: 123456
  token-validity-in-seconds: 86400000

②JwtUtil工具类

6.1.3 Jwt验证拦截器
6.1.3.1 定义Jwt拦截器

@Component
@Slf4j
public class JwtValidateInterceptor implements HandlerInterceptor {

@Resource
private JwtUtil jwtUtil;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// String token = request.getHeader("Authorization");
/request.getHeader()方法与集成Swagger中ApiKey并无多大关系
private List securitySchemes() {
List securitySchemes = new ArrayList<>();
securitySchemes.add(new ApiKey("Authorization", "Authorization", "header"));
return securitySchemes;
}
/
String token = request.getHeader("X-Token");
log.debug(request.getRequestURI()+"需要验证"+token);
if (token != null) {
try {
jwtUtil.parseToken(token);
log.debug(request.getRequestURI()+"验证通过");
return true;
} catch (Exception e) {
throw new Exception(e);
}
}
log.debug(request.getRequestURI()+"验证失败,禁止访问");
response.setContentType("application/json;charset=utf-8");
Result

本文来自博客园,作者:screws,转载请注明原文链接:https://www.cnblogs.com/mrlumin/p/18602826

posted on 2024-12-12 16:03  screws  阅读(285)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3