2024-08-29

Spring Boot 整合 SkyWalking 主要涉及到对日志的收集,以下是一个基本的整合步骤:

  1. pom.xml 中添加 SkyWalking 日志收集器的依赖:



<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>[1.x版本号]</version>
</dependency>

请将 [1.x版本号] 替换为实际的版本号,该版本需要与你使用的 SkyWalking OAP 服务器版本兼容。

  1. src/main/resources 目录下创建或修改 logback-spring.xml 文件,配置 SkyWalking 的日志收集器:



<configuration>
    <appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.logback.TraceIdAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <root level="INFO">
        <appender-ref ref="SKYWALKING" />
    </root>
</configuration>
  1. 确保 application.propertiesapplication.yml 中包含正确的 SkyWalking 配置,例如:



# application.properties
spring.application.name=your-application-name
skywalking.agent.service_name=your-application-name
skywalking.agent.namespace=your-application-namespace
skywalking.collector.backend_service=localhost:11800

确保 skywalking.collector.backend_service 指向了你的 SkyWalking OAP 服务器地址。

  1. 在启动 Spring Boot 应用时,确保设置了 -javaagent 参数指向 skywalking-agent 目录。例如:



java -javaagent:/path/to/skywalking-agent/skywalking-agent.jar -jar your-application.jar

替换 /path/to/skywalking-agent 为你的 skywalking-agent 实际路径。

完成以上步骤后,你的 Spring Boot 应用就会将日志数据通过 SkyWalking 发送到 OAP 服务器,并在 SkyWalking UI 中进行展示。

2024-08-29

在Spring Boot中,控制器的路径匹配机制是通过@RequestMapping及其衍生注解来实现的,比如@GetMapping@PostMapping等。

以下是一个简单的例子,展示了如何使用@RequestMapping进行路径匹配:




import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class PathMatchingController {
 
    @RequestMapping("/hello")
    public String hello() {
        return "Hello World!";
    }
 
    @RequestMapping("/greet/{name}")
    public String greetings(@PathVariable("name") String name) {
        return "Hello, " + name + "!";
    }
}

在这个例子中,/hello路径被hello()方法处理,而/greet/{name}路径被greetings()方法处理,其中{name}是一个路径变量,可以用来传递参数。

注意,@RequestMapping可以应用在类级别和方法级别,可以定义不同的HTTP请求方式(如GET、POST等),并且可以使用正则表达式定义更复杂的路径模式。

2024-08-29

在Spring中,你可以使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()来在try-catch块中手动实现事务回滚。这里有一个简单的例子:




import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
@Transactional
public void someMethod() {
    try {
        // 业务逻辑执行
        // ...
 
        // 如果发生错误,则回滚事务
        if (发生错误条件) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return;
        }
 
        // 如果没有发生错误,则正常提交事务
        // ...
 
    } catch (Exception e) {
        // 异常处理
        // 可以在这里记录日志,或者进行其他的异常处理操作
        // 但是不需要手动调用setRollbackOnly(),因为Spring会在捕获到未处理的异常时自动回滚事务
        // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        // 可以抛出异常让Spring处理,或者直接返回
        return;
    }
}

在这个例子中,如果满足某个条件,方法内部会手动触发事务回滚。这通常用于在业务逻辑中需要基于某些条件回滚事务的场景。需要注意的是,在catch块中,不需要手动调用setRollbackOnly(),因为Spring会自动处理未处理的异常并回滚事务。

2024-08-29



import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.filter.factory.rewrite.CorsConfig;
import org.springframework.cloud.gateway.filter.factory.rewrite.CorsFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class GatewayConfig {
 
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/api/**")
                        .uri("http://backend:8080")
                        .filters(f -> f.stripPrefix(1))
                )
                .build();
    }
 
    @Bean
    public CorsFilter corsFilter() {
        CorsConfig config = new CorsConfig();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        return new CorsFilter(config);
    }
}

这段代码定义了一个GatewayConfig配置类,其中包含了自定义路由的配置和跨域资源共享的配置。它使用Spring Cloud Gateway来转发所有/api/**路径的请求到http://backend:8080,并使用CorsFilter来允许跨域请求。这是一个安全的实践,确保前端应用可以跨域调用后端服务。

2024-08-29



import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
    private String url;
    private String username;
    private String password;
    private String driverClassName;
    // 省略getter和setter方法
}

这个代码示例展示了如何在Spring Boot应用程序中使用@ConfigurationProperties注解来简化数据库连接池配置的过程。通过定义一个带有@Component注解的类,并将其与@ConfigurationProperties注解结合使用,可以将配置文件(如application.propertiesapplication.yml)中的属性映射到类的字段中。这样,你就可以在代码中直接使用这些属性,而无需手动获取和设置它们。

2024-08-29

Spring Cloud Eureka是Spring Cloud Netflix项目下的服务发现模块。Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册中心;Eureka客户端是一个java客户端,用来简化与服务器的交互、服务注册与发现。

以下是一个基本的Eureka服务端配置示例:




@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

application.properties配置文件:




spring.application.name=eureka-server
server.port=8761
eureka.instance.hostname=localhost
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

以下是一个Eureka客户端的配置示例:




@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

application.properties配置文件:




spring.application.name=eureka-client
server.port=8080
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/

以上代码展示了如何配置和启动一个Eureka服务端和一个Eureka客户端。服务端用于服务注册中心,客户端用于将自身服务注册到Eureka服务器并从Eureka服务器获取服务列表。

2024-08-29



import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
 
@Component
public class ErrorFilter extends ZuulFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(ErrorFilter.class);
 
    @Override
    public String filterType() {
        return "error";
    }
 
    @Override
    public int filterOrder() {
        return 10;
    }
 
    @Override
    public boolean shouldFilter() {
        return true;
    }
 
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        Throwable throwable = ctx.getThrowable();
        HttpServletResponse response = ctx.getResponse();
 
        try {
            if (throwable != null) {
                LOGGER.error("Error during filtering", throwable);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                throwable.printStackTrace(new PrintStream(baos));
                String exceptionStackTrace = new String(baos.toByteArray());
                response.getWriter().write("Unexpected error occurred. Please try again later. StackTrace: " + exceptionStackTrace);
            }
        } catch (IOException e) {
            LOGGER.error("Error while writing the response", e);
        }
 
        return null;
    }
}

这段代码定义了一个Zuul过滤器,用于处理Zuul中出现的异常。它捕获异常信息,记录错误日志,并向客户端返回一个错误信息。这种异常处理方式有利于保持服务的健壮性,并向用户传递一个更为友好的错误信息。

2024-08-29

为了制作一个包含Tomcat的Docker镜像,你需要创建一个Dockerfile,然后使用Docker命令构建镜像。以下是一个基本的Dockerfile示例,用于制作包含Tomcat的镜像:




# 使用官方的Java镜像作为基础镜像
FROM openjdk:8-jdk-alpine
 
# 定义Tomcat版本环境变量
ENV CATALINA_HOME /usr/local/tomcat
ENV CATALINA_BASE /usr/local/tomcat
ENV CATALINA_TMPDIR /tmp
ENV JRE_HOME /usr/local/openjdk-8
 
# 添加Tomcat用户权限
RUN addgroup -S tomcat && adduser -S -g tomcat -D tomcat
 
# 安装Tomcat并清理不需要的文件
RUN mkdir /usr/local/tomcat \
  && curl -fsSL https://downloads.apache.org/tomcat/tomcat-9/v9.0.62/bin/apache-tomcat-9.0.62.tar.gz | tar -xz -C /usr/local/tomcat --strip-components=1 \
  && rm -rf /usr/local/tomcat/webapps/* /usr/local/tomcat/webapps.dist/* \
  && chown -R tomcat:tomcat /usr/local/tomcat
 
# 设置工作目录
WORKDIR $CATALINA_HOME
 
# 暴露8080端口
EXPOSE 8080
 
# 切换用户
USER tomcat
 
# 设置启动脚本
ENTRYPOINT ["catalina.sh", "run"]

保存这个文件为Dockerfile,然后在该文件所在目录下运行以下命令来构建镜像:




docker build -t my-tomcat .

这里my-tomcat是你给镜像起的名字,可以根据自己的喜好命名。构建完成后,你可以使用以下命令来运行Tomcat容器:




docker run -it --rm -p 8080:8080 my-tomcat

这样就可以在浏览器中通过http://localhost:8080访问到Tomcat的默认页面了。

2024-08-29



// 算法题2:给定一个字符串,请找出一个最长的不包含重复字符的子字符串的长度。
 
public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        Set<Character> set = new HashSet<>();
        int ans = 0, i = 0, j = 0;
 
        while (i < n && j < n) {
            if (!set.contains(s.charAt(j))){
                set.add(s.charAt(j++));
                ans = Math.max(ans, j - i);
            } else {
                set.remove(s.charAt(i++));
            }
        }
 
        return ans;
    }
 
    public static void main(String[] args) {
        Solution solution = new Solution();
        String input = "abcabcbb";
        System.out.println("最长不含重复字符的子字符串长度为: " + solution.lengthOfLongestSubstring(input));
    }
}

这段代码使用了一个哈希集合来存储已经遍历过的字符,并通过两个指针i和j来维护一个滑动窗口。算法的核心思想是不断地扩大窗口直到遇到重复的字符,然后移除窗口的左边字符直到不再重复,并更新最长子字符串长度。这个方法的时间复杂度为O(N),N为字符串的长度,因为我们只遍历字符串一次。

2024-08-29

在Spring Boot应用中添加访问地址和Swagger文档输出,通常涉及以下步骤:

  1. 添加访问地址:在Spring Boot中,你可以通过@RequestMapping@GetMapping等注解来指定控制器方法的访问地址。
  2. 集成Swagger:使用Swagger可以生成API文档,并提供在线测试功能。你需要添加Swagger的依赖,并配置Swagger。

以下是一个简单的示例:

添加Maven依赖(pom.xml):




<!-- Swagger -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

Swagger配置类(SwaggerConfig.java):




import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
 
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .build();
    }
}

控制器类(YourController.java):




import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api")
public class YourController {
 
    @GetMapping("/hello")
    public String hello() {
        return "Hello World!";
    }
}

启动Spring Boot应用后,你可以通过访问http://<host>:<port>/api/hello来访问你定义的地址,通过访问http://<host>:<port>/swagger-ui.html来查看Swagger文档。

请注意,具体的端口和主机取决于你的部署环境和配置。以上代码示例使用了默认的端口8080。如果你使用的是不同的端口或者有自定义的配置,请相应地修改访问地址。