springboot工程中使用tcp协议

//goto docker\docker-compose.yml version: '3.7' services: springboot-tcp: image: registry.cn-shanghai.aliyuncs.com/00fly/springboot-tcp:1.0.0 container_name: springboot-tcp deploy: resources: limits: cpus: '1.0' memory: 200M reservations: cpus: '0.05' memory: 200M ports: - 8080:8081 restart: on-failure logging: driver: json-file options: max-size: '5m' max-file: '1' //goto docker\restart.sh #!/bin/bash docker-compose down && docker-compose up -d && docker stats //goto docker\stop.sh #!/bin/bash docker-compose down //goto docker\wait-for.sh #!/bin/sh TIMEOUT=15 QUIET=0 echoerr() { if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi } usage() { exitcode="$1" cat << USAGE >&2 Usage: $cmdname host:port [-t timeout] [-- command args] -q | --quiet Do not output any status messages -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout -- COMMAND ARGS Execute command with args after the test finishes USAGE exit "$exitcode" } wait_for() { for i in `seq $TIMEOUT` ; do nc -z "$HOST" "$PORT" > /dev/null 2>&1 result=$? if [ $result -eq 0 ] ; then if [ $# -gt 0 ] ; then exec "$@" fi exit 0 fi sleep 1 done echo "Operation timed out" >&2 exit 1 } while [ $# -gt 0 ] do case "$1" in *:* ) HOST=$(printf "%s\n" "$1"| cut -d : -f 1) PORT=$(printf "%s\n" "$1"| cut -d : -f 2) shift 1 ;; -q | --quiet) QUIET=1 shift 1 ;; -t) TIMEOUT="$2" if [ "$TIMEOUT" = "" ]; then break; fi shift 2 ;; --timeout=*) TIMEOUT="${1#*=}" shift 1 ;; --) shift break ;; --help) usage 0 ;; *) echoerr "Unknown argument: $1" usage 1 ;; esac done if [ "$HOST" = "" -o "$PORT" = "" ]; then echoerr "Error: you need to provide a host and port to test." usage 2 fi wait_for "$@" //goto Dockerfile #基础镜像 FROM adoptopenjdk/openjdk8-openj9:alpine-slim COPY docker/wait-for.sh / RUN chmod +x /wait-for.sh && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo 'Asia/Shanghai' >/etc/timezone #引入运行包 COPY target/*.jar /app.jar #指定交互端口 EXPOSE 8081 CMD ["--server.port=8081"] #项目的启动方式 ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Xshareclasses", "-Xquickstart", "-jar", "/app.jar"] //goto pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fly</groupId> <artifactId>springboot-tcp</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.4.RELEASE</version> <relativePath /> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <docker.hub>registry.cn-shanghai.aliyuncs.com</docker.hub> <java.version>1.8</java.version> <skipTests>true</skipTests> </properties> <dependencies> <!-- Compile --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.8</version> </dependency> <!-- 异步日志,需要加入disruptor依赖 --> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!-- Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <!-- 阿里云maven仓库 --> <repositories> <repository> <id>public</id> <name>aliyun nexus</name> <url>https://maven.aliyun.com/repository/public/</url> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>public</id> <name>aliyun nexus</name> <url>https://maven.aliyun.com/repository/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- 添加docker-maven插件 --> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.40.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>build</goal> <!--<goal>push</goal>--> <!--<goal>remove</goal>--> </goals> </execution> </executions> <configuration> <!-- 连接到带docker环境的linux服务器编译image --> <!-- <dockerHost>http://192.168.182.10:2375</dockerHost> --> <!-- Docker 推送镜像仓库地址 --> <pushRegistry>${docker.hub}</pushRegistry> <images> <image> <name> ${docker.hub}/00fly/${project.artifactId}:${project.version}</name> <build> <dockerFileDir>${project.basedir}</dockerFileDir> </build> </image> </images> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/**</include> </includes> <filtering>false</filtering> </resource> </resources> </build> </project> //goto src\main\java\com\fly\BootApplication.java package com.fly; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class BootApplication { public static void main(String[] args) { SpringApplication.run(BootApplication.class, args); } } //goto src\main\java\com\fly\core\config\AsyncThreadPoolConfig.java package com.fly.core.config; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import lombok.extern.slf4j.Slf4j; /** * * 异步线程池配置 * * @author 00fly * @version [版本号, 2023年10月22日] * @see [相关类/方法] * @since [产品/模块版本] */ @Slf4j @Configuration @EnableAsync public class AsyncThreadPoolConfig implements AsyncConfigurer { @Bean ThreadPoolTaskExecutor taskExecutor() { int processors = Runtime.getRuntime().availableProcessors(); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(Math.max(processors, 5)); executor.setMaxPoolSize(Math.max(processors, 5) * 2); executor.setQueueCapacity(10000); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("asyncTask-"); // ThreadPoolExecutor类有几个内部实现类来处理这类情况: // AbortPolicy 丢弃任务,抛运行时异常 // CallerRunsPolicy 执行任务 // DiscardPolicy 忽视,什么都不会发生 // DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); return executor; } @Override public Executor getAsyncExecutor() { return taskExecutor(); } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (ex, method, params) -> { log.info("Exception message - {}", ex.getMessage()); log.info("Method name - {}", method.getName()); for (Object param : params) { log.info("Parameter value - {}", param); } }; } } //goto src\main\java\com\fly\core\config\Knife4jConfig.java package com.fly.core.config; import java.util.Collections; import java.util.List; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; import io.swagger.annotations.ApiOperation; import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; /** * Knife4jConfig * */ @EnableKnife4j @Configuration @EnableSwagger2WebMvc @ConditionalOnWebApplication @Import(BeanValidatorPluginsConfiguration.class) public class Knife4jConfig { /** * 开发、测试环境接口文档打开 * * @return * @see [类、类#方法、类#成员] */ @Bean Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) .enable(true) .select() .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) // 包下的类,生成接口文档 .build() .securitySchemes(security()); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("数据接口API").description("接口文档").termsOfServiceUrl("http://00fly.online/").version("1.0.0").build(); } private List<ApiKey> security() { return Collections.singletonList(new ApiKey("token", "token", "header")); } } //goto src\main\java\com\fly\core\config\WebClientConfig.java package com.fly.core.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; /** * 配置WebClient */ @Configuration public class WebClientConfig { @Bean WebClient webClient() { return WebClient.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build(); } } //goto src\main\java\com\fly\core\config\WebMvcConfig.java package com.fly.core.config; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * * mvc配置 * * @author 00fly * @version [版本号, 2021年4月23日] * @see [相关类/方法] * @since [产品/模块版本] */ @Configuration @ConditionalOnWebApplication public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) { converters.add(stringHttpMessageConverter()); converters.add(mappingJackson2HttpMessageConverter()); } @Override public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { configurer.defaultContentType(MediaType.APPLICATION_JSON); configurer.ignoreUnknownPathExtensions(false); configurer.favorPathExtension(true); configurer.favorParameter(false); final Map<String, MediaType> mediaTypes = new ConcurrentHashMap<>(3); mediaTypes.put("atom", MediaType.APPLICATION_ATOM_XML); mediaTypes.put("html", MediaType.TEXT_HTML); mediaTypes.put("json", MediaType.APPLICATION_JSON); configurer.mediaTypes(mediaTypes); } @Bean StringHttpMessageConverter stringHttpMessageConverter() { return new StringHttpMessageConverter(); } @Bean MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { final MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); final List<MediaType> list = new ArrayList<>(); list.add(MediaType.APPLICATION_JSON); list.add(MediaType.APPLICATION_XML); list.add(MediaType.TEXT_PLAIN); list.add(MediaType.TEXT_HTML); list.add(MediaType.TEXT_XML); messageConverter.setSupportedMediaTypes(list); return messageConverter; } /** * 等价于mvc中<mvc:view-controller path="/" view-name="redirect:index" /><br> * 等价于mvc中<mvc:view-controller path="/index" view-name="index.html" /> * * @param registry */ @Override public void addViewControllers(final ViewControllerRegistry registry) { registry.addViewController("/").setViewName("redirect:index"); registry.addViewController("/index").setViewName("index.html"); } } //goto src\main\java\com\fly\core\exception\GlobalExceptionHandler.java package com.fly.core.exception; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.springframework.validation.BindException; imp
上一篇:c++_ 多态


下一篇:SQL进阶技巧:统计各时段观看直播的人数