Appearance
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.