Skip to content

springCloud使用

springCloud
This page demonstrates some of the built-in markdown extensions provided by VitePress.

父亲项目pom.xml

md
```xml
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
    </parent>
    <groupId>com.concare</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.2</version>
    <packaging>pom</packaging>

    <name>parent</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.8.RELEASE</spring-cloud-alibaba.version>
        <mybatisplus.version>3.5.2</mybatisplus.version>
        <dynamic-datasource.version>3.5.0</dynamic-datasource.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-security-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-spring-boot-starter</artifactId>
                <version>1.5.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
```

##注册中心、配置中心## 使用nacos

普通服务配置

pom.xml

md
```xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>
```

yml

md
```yml
#api默认超时时间
feign:
  client:
    config:
      default: {"connectTimeout":30000,"readTimeout":30000}
      DeliverymanAPi: {"connectTimeout":100000,"readTimeout":100000}
      
spring:
  cloud:
    nacos:
      username: ${demo.username}
      password: ${demo.password}
      config:
        server-addr: ${concare.nacos-addr}
        file-extension: yml
        name: ${spring.application.name}-${spring.profiles.active}
      discovery:
        server-addr: ${demo.nacos-addr}
        service: ${spring.application.name}
        
#seata配置
seata:
  application-id: ${spring.application.name}
  # 这里的配置对应 seataServer.properties 中的 service.vgroupMapping.storage-service-group=default
  enable-auto-data-source-proxy: true
  config:
    type: nacos
    nacos:
      server-addr: ${demo.nacos-addr}
      username: ${demo.username}
      password: ${demo.password}
      # 微服务必须在一个组,否则服务发现不了,但Seata-server 可以在不同的组中
      group: DEFAULT_GROUP
      dataId: "seataServer.properties"
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: ${demo.nacos-addr}
      group: DEFAULT_GROUP
      username: ${demo.username}
      password: ${demo.password}
      # 微服务必须在一个组,否则服务发现不了,但Seata-server 可以在不同的组中
  tx-service-group: default-tx-group
```

启动类

md
```java
@MapperScan(basePackages = {"com.demo.oms.mapper"})
@EnableDiscoveryClient
@EnableCaching
@EnableFeignClients(basePackages = {"com.demo.api"})
@SpringBootApplication(scanBasePackages = {"com.demo"})
public class OrderServiceApplication {
    //springBoot1.4后版本不再默认提供RestTemplate的实例Bean,需要手动创建RestTemplate配置
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    public static void main(String[] args) {
        // mail包1.5.3版本后文件名太长会截断文件名,导致乱码,此设置为控制不截取
        System.getProperties().setProperty("mail.mime.splitlongparameters", "false");
        String workId = System.getProperty("workId");

        IdGeneratorOptions options = new IdGeneratorOptions();
        options.WorkerId = Short.parseShort(workId);//机器编码
        YitIdHelper.setIdGenerator(options);
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}
```

openFeign

md
```java
@FeignClient(name = "cts",contextId = "TrainCourseApi",url = "${cts.api.url:}")
public interface TrainCourseApi {

    @PostMapping(name = "批量根据项目编码获取相关的课程课件信息",path = "api/trainCourse/findTrainCourseByProCodeSet")
    Map<String,List<TrainCourseApiVo>> findTrainCourseByProCodeSet(@RequestBody TrainCourseApiDto trainCourseApiDto);

    @PostMapping(name = "员工入职时推送必学课程",params = "/api/cts/course/pushCourse")
    Map listPushCourse(@RequestBody TrainCourseApiDto trainCourseApiDto);

}
```

配置类

处理全局异常

md
```java
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public void globalException(HttpServletResponse response, Exception ex){
        ServletRequestAttributes requestAttr = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttr.getRequest();
        log.error("请求异常{},{}",request.getRequestURI(),ex);
        if (request.getRequestURI().startsWith("/api")){
            renderString(response,ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value());
            return;
        }
        this.render500(response,ex.getMessage(),HttpStatus.OK.value());
    }

    /**
     * 处理api异常
     * @param response
     * @param msg
     * @param status
     */
    private void renderString(HttpServletResponse response, String msg,int status) {
        try {
            response.setStatus(status);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(msg);
        } catch (IOException e) {
            log.error("响应前端异常",e);
        }
    }

    /**
     * 处理500异常
     */
    private void render500(HttpServletResponse response, String msg,int status) {
        try {
            R fail = R.fail(msg);
            fail.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.setStatus(status);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(new JSONObject(fail));
        } catch (IOException e) {
            log.error("响应前端异常",e);
        }
    }
}
```

处理API异常

md
```java 
@Slf4j
@Component
public class MyFeignExConfig implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response){
        String res = "";
        try {
            RequestTemplate requestTemplate = response.request().requestTemplate();
            String url = requestTemplate.url();
            Response.Body body = response.body();
            byte[] bytes = Util.toByteArray(body.asInputStream());
            res = new String(bytes, StandardCharsets.UTF_8);
            log.error("错误信息:{},{},{}",url,methodKey,res);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new RuntimeException(res);
    }
}
```

Request

md
```java 
@Component
@Slf4j
public class TransmitRequestInterceptor implements RequestInterceptor {


    @Value("${spring.application.name}")
    private String appName;

    @Override
    public void apply(RequestTemplate template) {

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes == null ? ((HttpServletRequest) FeignThreadLocal.get()) : (requestAttributes.getRequest());
        if (request == null){
            log.warn("request is null............");
            return;
        }
        // 获取 RequestContextHolder 中的信息
        Map<String, String> headers = getHeaders(request);

        // 放入 feign 的 RequestTemplate 中
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            if ("content-length".equalsIgnoreCase(entry.getKey())) {
                continue;
            }
            template.header(entry.getKey(), entry.getValue());
        }
        template.header("appName",appName);
    }

    /**
     * 获取原请求头
     */
    private Map<String, String> getHeaders(HttpServletRequest request) {

        Map<String, String> map = new LinkedHashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        if (enumeration != null) {
            while (enumeration.hasMoreElements()) {
                String key = enumeration.nextElement();
                String value = request.getHeader(key);
                map.put(key, value);
            }
        }
        return map;
    }

}
```

More

Check out the documentation for the full list of markdown extensions.