项目构建

1. 创建项目

1.1 查询SpringCloud和SpringBoot 对应版本

官网地址  https://spring.io/
1.直达链接:https://spring.io/projects/spring-cloud#overview #查看版本对应关系
2.可以直接访问 https://start.spring.io/actuator/info 会返回对应版本JSON,
使用JSON在线解析就可查看

Alt

1.2 创建对应项目

https://start.spring.io/

Alt

1.3 删除SpringBoot项目无用文件夹

Alt

1).mvn 包含用于 Maven Wrapper(mvnw 和 mvnw.cmd)的配置文件,
Maven Wrapper 是一个用于封装 Maven的工具,在没有安装全局Maven的情况下运行项目 
(如果本地有全局Maven,可以删除)
2).gitignore git版本控制 指定应该被 Git 版本控制系统忽略的文件和目录 
(使用git务必保留)
3)HELP,md 项目帮助文档 (可以删除没有影响)
4)mvnw Maven Wrapper 的可执行脚本在Unix/Linux 系统中使用 
(在没有安装全局Maven情况下运行Maven构建的脚本,可以删除)
5)mvnw.cmd Maven Wrapper 的可执行脚本在Windows 系统中使用
(在没有安装全局Maven情况下运行Maven构建的脚本,可以删除)

1.4 创建子工程

复制父工程到父工程文件夹下
Alt
添加Modules
Alt
将刚刚复制的父工程导入进来即可
Alt

1.5 整理pom.xml

在父工程中添加    <packaging>pom</packaging> 
用来做jar包的版本控制
 <!--    引入子项目的pom-->
    <modules>
        <module>module_tesst</module>
    </modules>
 <!--       引入父项目pom-->
    <parent>
        <artifactId>springcloud_test</artifactId>
        <groupId>com.test</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

2.集成SpringCloud

   <!-- spring cloud begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- spring cloud end -->
          <!-- 健康检查-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
 application.yml文件
 spring:
    cloud:
        consul:
            discovery:
                prefer-ip-address: true
                instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
                heartbeat:
                    enabled: true
application-local.yml文件
spring:
    cloud:
        consul:
            host: 172.17.0.2
            port: 8500

3.配置Spring Boot项目必要配置

3.1 配置全局异常拦截器

/**
 * 全局异常处理
 * @author Administrator
 *
 */
@ControllerAdvice
public class GloableExceptionController extends BaseController{
    
    /**
     * 拦截Exception类型异常
     * 所有的异常都可以用该类来接受
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value = Exception.class)
//    @OperLog(operModul="异常信息",operType="defaultExceptionHandler",operDesc="异常信息")
    public ModelAndView defaultExceptionHandler(HttpServletRequest request,Exception ex){
        ModelAndView mv = new ModelAndView();
        //获取请求路径
        mv.addObject("url",request.getRequestURL());
        //异常对象
        mv.addObject("ex",ex);
        //异常对象信息
        mv.addObject("message",ex.getMessage());
        System.err.println(mv);
        mv.setViewName("/defaultException");
        return mv;
    }
 
    /**
     * 自定义异常
     * @param request
     * @param ex
     * @return
     * BindingException mybatis中参数异常
     * NoHandlerFoundException 404异常
     */
    @ExceptionHandler(value = {NoHandlerFoundException.class,BindingException.class})
    public ModelAndView defaultExceptionHandler2(HttpServletRequest request,Exception ex){
        ModelAndView modelAndView = new ModelAndView("/404");
        //获取请求路径
        modelAndView.addObject("url",request.getRequestURL());
        //异常对象
        modelAndView.addObject("ex",ex);
        //异常对象信息
        modelAndView.addObject("message",ex.getMessage());
        return modelAndView;
    }
    
    /**
     * 权限校验异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value = {UnauthorizedException.class})
    @ResponseBody
    public AjaxResult unauthorizedException(HttpServletRequest request,Exception ex){
        return result(HTTP_ERROR,"暂无权限",ICON_ERROR);
    }
}

3.2 跨域配置

@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        return true;
    }
}
或者使用过滤器
/**
 * 过滤器,需要使用@ServletComponentScan注解来扫描@WebFilter、@WebServlet、@WebListener等注解
 */
@WebFilter
public class MyCorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        //设置访问源地址
        response.setHeader("Access-Control-Allow-Origin", "*");
        //设置访问源请求方法
        response.setHeader("Access-Control-Allow-Methods", "*");
        //跨域请求的有效时间, 这里是1小时
        response.setHeader("Access-Control-Max-Age", "3600");
        //设置访问源请求头
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(req, res);
    }
}
或者使用nginx 

后续会有专题解释后台不必要配置跨域

3.3 配置modelMapper

    <properties>
        <modelmapper.version>3.2.0</modelmapper.version>
    </properties>
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>${modelmapper.version}</version>
            <scope>compile</scope>
        </dependency>
@Configuration
public class ModelMapperConfig {
    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();

        modelMapper.getConfiguration()
            .setFullTypeMatchingRequired(true)
            .setMatchingStrategy(MatchingStrategies.STRICT)
            .setPropertyCondition(Conditions.isNotNull());

        modelMapper.addConverter(new Converter<LocalDateTime, Long>() {
            @Override
            public Long convert(MappingContext<LocalDateTime, Long> context) {
                Timestamp timestamp = Timestamp.valueOf(context.getSource());
                return timestamp.getTime();
            }
        });

        modelMapper.addConverter(new Converter<Long, LocalDateTime>() {
            @Override
            public LocalDateTime convert(MappingContext<Long, LocalDateTime> context) {
                if (context.getSource() == 0L) {
                    return null;
                }
                Timestamp timestamp = new Timestamp(context.getSource());
                return timestamp.toLocalDateTime();
            }
        });

        return modelMapper;
    }
}

3.4 MapStruct配置

   <mybatis.version>3.0.2</mybatis.version>
            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct</artifactId>
                <version>${org.mapstruct.version}</version>
            </dependency>

3.5 Commons-Beanutils包

<commons-beanutils.version>1.9.4</commons-beanutils.version>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>${commons-beanutils.version}</version>
        </dependency>

3.6 swagger 3.0

引入Maven依赖

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>${org.springdoc.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
            <version>${org.springdoc.version}</version>
        </dependency>

配置SwaggerOpenApiConfig(注解)
可选配置类方式

import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.boot.SpringBootConfiguration;

@SpringBootConfiguration
@OpenAPIDefinition(
        // ## API的基本信息,包括标题、版本号、描述、联系人等
        info = @Info(
                title = "Swagger3.0 (Open API) 框架学习示例文档",       // Api接口文档标题(必填)
                description = "学习Swagger框架而用来定义测试的文档",      // Api接口文档描述
                version = "1.2.1",                                   // Api接口版本
                termsOfService = "https://example.com/",             // Api接口的服务条款地址
                contact = @Contact(
                        name = "name",                            // 作者名称
                        email = "emmail@qq.com",                  // 作者邮箱
                        url = "https://www.baidu.com"  // 介绍作者的URL地址
                ),
                license = @License(                                                // 设置联系人信息
                        name = "Apache 2.0",                                       // 授权名称
                        url = "https://www.apache.org/licenses/LICENSE-2.0.html"   // 授权信息
                )
        ),
        // ## 表示服务器地址或者URL模板列表,多个服务地址随时切换(只不过是有多台IP有当前的服务API)
        servers = {
                @Server(url = "http://192.168.100.2/demo/", description = "本地服务器一服务"),
                @Server(url = "http://192.168.100.3/demo/", description = "本地服务器二服务"),
        },
        externalDocs = @ExternalDocumentation(description = "更多内容请查看该链接", url = "xxx"))
public class SwaggerOpenApiConfig {
}

JWT验证配置类

@Configuration
@SecurityScheme(
        name = "Bearer Authentication",
        type = SecuritySchemeType.HTTP,
        bearerFormat = "JWT",
        scheme = "Bearer"
)
public class OpenAPISecurityConfig {
}

4.集成组件(中间件)

4.1 SpringBoot集成Mysql和Mybatis Plus

  1. mysql-connector-java是JAVA程序中真正操作mysql数据库的客户端,spring-boot-starter-jdbc中的JdbcTemplate是对JDBC的封装,底层还是调用mysql-connector-java中的方法操作mysql数据库
  2. 如果你想使用特定的数据库连接器,那么你应该同时引入 spring-boot-starter-jdbc 和 mysql-connector-java
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
       <!--mybatisplus组件-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
            <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.9</version>
    </dependency>
yml配置
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver  #定义配置驱动类
    username: root #mysql登录用户名
    password: 123 #mysql登录密码
    url: jdbc:mysql://localhost:12345/shopDB?characterEncoding=utf8&allowMultiQueries=true 
    type: com.alibaba.druid.pool.DruidDataSource #配置连接池
    druid:
      one:
        max-active: 100 #最大连接数
        min-idle: 20 #最小连接数
        max-wait: 2000 #超时时间(ms)
mybatis-plus:
    mapper-locations: classpath*:/mapper/*Mapper.xml
    configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台输出日志
//配置分页插件
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }

4.2 Springboot整合redis

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

yml配置
spring:
  application:
    name: redis-demo
  redis:
    host: localhost
    database: 1
    jedis:  # 配置jedis线程池,也可以配置Lettuce
      pool:
        max-active: 8 # 最大活动数量()
        max-wait: -1 # 连接池最大阻塞时间 (使用负数表示没有限制)
    port: 6379  # 6379默认端口,不配置就取默认
  # --lettuce 配置
  #  lettuce:
  #   pool:
  #     max-active: 
//RedisConfig配置类
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer(Object.class);
        // 设置键(key)的序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 设置value序列化
        redisTemplate.setValueSerializer(serializer);
        // 设置HashKey序列化 为啥要hashkey
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // 设置HashValue序列化
        redisTemplate.setHashValueSerializer(serializer);
        // 默认序列化
        redisTemplate.setDefaultSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

4.3 Spring Boot集成GRPC

引入依赖,开箱即用

 <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>${net-devh-grpc-spring-boot.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>io.grpc</groupId>
                    <artifactId>grpc-netty-shaded</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-client-spring-boot-starter</artifactId>
            <version>${net-devh-grpc-spring-boot.version}</version>
        </dependency>

4.4 Spring Boot集成Zipkin

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
spring:

  zipkin:
    #zipkin服务所在地址
    base-url: http://127.0.0.1:9411/
#    discovery-client-enabled: false
    sender:
      type: web #使用http的方式传输数据
  #配置采样百分比
  sleuth:
    sampler:
      probability: 1 # 将采样比例设置为 1.0,也就是全部都需要。默认是0.1也就是10%,一般情况下,10%就够用了

配置GRPC Tracing

@Slf4j
@AutoConfiguration(after = BraveAutoConfiguration.class)
@ConditionalOnClass({ Tracer.class, BraveTracer.class })
@EnableConfigurationProperties(TracingProperties.class)
@ConditionalOnEnabledTracing
public class GrpcZipkinConfig {

    @Bean
    public GrpcTracing grpcTracing(Tracing tracing) {
        return GrpcTracing.create(tracing);
    }

    //grpc-spring-boot-starter provides @GrpcGlobalInterceptor to allow server-side interceptors to be registered with all
    //server stubs, we are just taking advantage of that to install the server-side gRPC tracer.
    @Bean
    ServerInterceptor grpcServerSleuthInterceptor(GrpcTracing grpcTracing) {
        return grpcTracing.newServerInterceptor();
    }

    //We also create a client-side interceptor and put that in the context, this interceptor can then be injected into gRPC clien
    //then applied to the managed channel.
    @Bean
    ClientInterceptor grpcClientSleuthInterceptor(GrpcTracing grpcTracing) {
        return grpcTracing.newClientInterceptor();
    }

    @Bean
    public GlobalServerInterceptorConfigurer globalInterceptorConfigurerAdapter(ServerInterceptor grpcServerSleuthInterceptor) {
        return registry -> registry.add(grpcServerSleuthInterceptor);
    }
}

4.5 Spring Boot 集成 Micrometer

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
	<dependency>
		<groupId>io.micrometer</groupId>
		<artifactId>micrometer-registry-prometheus</artifactId>
		<micrometer-tracing.version>1.1.6</micrometer-tracing.version>
	</dependency>

4.6 Spring Boot 集成 gateway

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
spring:
    profiles:
        active: local

    application:
        name: gateway-service
        gateway:
            discovery:
                locator:
                    enabled: true
            routes:
                -   id: system-service # 路由标识必须唯一
                    uri: lb://system-service # 路由的目标服务 lb负载均衡 后面为服务名称
                    predicates: # 路由断言 判断是否符合断言规则
                        - Path=/system/** # 为system 开头则是符合
                    filters:
                        - RewritePath=/system/(?<path>.*), /$\{path} # 路径替换 /system 替换为 /
                        - PreserveHostHeader # 保留原有Host,并转发到下游服务

5.Maven 打包插件

5.1 prptobuf打包插件

   <protobuf-java.version>3.24.0</protobuf-java.version>
   <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
<build>
        <extensions>
            <extension>
            <!-- 识别不同的操作系统 -->
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>${os.plugin.version}</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>${protobuf.plugin.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <!-- 工具版本 -->
                   <protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
                    <!--默认值,proto源文件路径-->
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <!--默认值,proto目标java文件路径-->
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
                    <clearOutputDirectory>false</clearOutputDirectory>
 
                </configuration>
                <executions>
                    <execution>
                        <!--在执行mvn compile的时候会执行以下操作-->
                        <phase>compile</phase>
                        <goals>
                            <!--生成OuterClass-->
                            <goal>compile</goal>
                            <!--生成Grpc-->
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

更多参数参考官网https://www.xolstice.org/protobuf-maven-plugin/compile-mojo.html

5.2 Maven打包插件

        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
    <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.verison}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>io.github.linpeilie</groupId>
                            <artifactId>mapstruct-plus-processor</artifactId>
                            <version>${mapstruct-plus.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>${mapstruct-plus.lombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
<annotationProcessorPaths>:指定了注解处理器的路径。在这个配置中,我们添加了 org.mapstruct:mapstruct-processor 的注解处理器,
${org.mapstruct.version} 是一个变量,表示从项目的属性或外部配置文件中获取的注解处理器版本。

5.3 Spring Boot 打包插件

说明:如果打包成Springboot 可执行的jar,需要添加下面的插件,如果jar用作依赖包使用直接用 maven-compiler-plugin 打包即可

           <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>1.3.2.RELEASE</version>
                <configuration>
                    <mainClass>test.ApplicationMain</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

 <goal>repackage</goal> 这个是默认 goal,在 mvn package 执行之后,
 这个命令再次打包生成可执行的 jar,同时将 mvn package 生成的 jar 重命名为 *.origin

6.项目推送远程仓库

子级工程打包启动没有问题将项目推向远程仓库

git init # 初始化项目
git status # 检查项目更改信息
git add . # 添加所有文件
git commit -am "init" # 将新增文件提交到本地仓库
git remote add oriain "git http 地址" # 添加远程仓库
git push origin init:init  # 推送到远程分支

建议先clone到本地,再搭建项目

7.总结

本文为本人搭建项目笔记
到此Spring Cloud项目搭建完成
下一专题搭建基于Spring Security框架的用户登陆服务

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐