| @@ -0,0 +1,43 @@ | |||||
| <?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> | |||||
| <parent> | |||||
| <artifactId>mallink</artifactId> | |||||
| <groupId>com.iformall</groupId> | |||||
| <version>1.0</version> | |||||
| </parent> | |||||
| <artifactId>mallinkWebSocketServer</artifactId> | |||||
| <dependencies> | |||||
| <dependency> | |||||
| <groupId>com.iformall</groupId> | |||||
| <artifactId>mallinkService</artifactId> | |||||
| <version>1.0</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-websocket</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-reactor-netty</artifactId> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-maven-plugin</artifactId> | |||||
| <configuration> | |||||
| <executable>true</executable> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </project> | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.iformall; | |||||
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | |||||
| import org.rocketmq.starter.annotation.EnableRocketMQ; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.boot.SpringApplication; | |||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||||
| import tk.mybatis.spring.annotation.MapperScan; | |||||
| /** | |||||
| * @author Stormeye | |||||
| * @date 2019/03/20 | |||||
| */ | |||||
| @SpringBootApplication | |||||
| @MapperScan(basePackages = {"com.iformall.mapper"}) | |||||
| @EnableSwagger2 | |||||
| @EnableEncryptableProperties | |||||
| public class SocketServerApplication { | |||||
| @Value("${fm.exception}") | |||||
| private boolean fmException; | |||||
| @Bean | |||||
| public boolean isFmException() { | |||||
| return fmException; | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SocketServerApplication.class, args); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,29 @@ | |||||
| package com.iformall; | |||||
| /** | |||||
| * @author Stormeye | |||||
| * @version 2019/03/20 | |||||
| */ | |||||
| import org.springframework.context.ApplicationEvent; | |||||
| import org.springframework.context.ApplicationListener; | |||||
| import org.springframework.messaging.simp.stomp.StompHeaderAccessor; | |||||
| import org.springframework.stereotype.Component; | |||||
| import org.springframework.web.socket.messaging.SessionSubscribeEvent; | |||||
| /** | |||||
| * 订阅监听 | |||||
| */ | |||||
| @Component | |||||
| public class SubscribeEventListener implements ApplicationListener { | |||||
| @Override | |||||
| public void onApplicationEvent(ApplicationEvent event) { | |||||
| if (event instanceof SessionSubscribeEvent) { | |||||
| SessionSubscribeEvent sessionSubscribeEvent = (SessionSubscribeEvent) event; | |||||
| StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(sessionSubscribeEvent.getMessage()); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
| import org.springframework.stereotype.Component; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Component | |||||
| @ConfigurationProperties(prefix = "aws") | |||||
| public class AwsProperty { | |||||
| // AWS ACCESS KEY | |||||
| private String access; | |||||
| private String secret; | |||||
| private String clientRegion; | |||||
| private String bucketName; | |||||
| public String getAccess() { | |||||
| return access; | |||||
| } | |||||
| public void setAccess(String access) { | |||||
| this.access = access; | |||||
| } | |||||
| public String getSecret() { | |||||
| return secret; | |||||
| } | |||||
| public void setSecret(String secret) { | |||||
| this.secret = secret; | |||||
| } | |||||
| public String getClientRegion() { | |||||
| return clientRegion; | |||||
| } | |||||
| public void setClientRegion(String clientRegion) { | |||||
| this.clientRegion = clientRegion; | |||||
| } | |||||
| public String getBucketName() { | |||||
| return bucketName; | |||||
| } | |||||
| public void setBucketName(String bucketName) { | |||||
| this.bucketName = bucketName; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,24 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
| import org.springframework.stereotype.Component; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Component | |||||
| @ConfigurationProperties(prefix = "pay") | |||||
| public class PayProperty { | |||||
| /** | |||||
| * 真实支付 | |||||
| */ | |||||
| private boolean real; | |||||
| public boolean isReal() { | |||||
| return real; | |||||
| } | |||||
| public void setReal(boolean real) { | |||||
| this.real = real; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| package com.iformall.config; | |||||
| import lombok.Data; | |||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
| import org.springframework.stereotype.Component; | |||||
| @Data | |||||
| @Component | |||||
| @ConfigurationProperties(prefix="spring.rabbitmq") | |||||
| public class RabbitMqProperty { | |||||
| private String host; | |||||
| private int port; | |||||
| private String username; | |||||
| private String password; | |||||
| private String virtualHost; | |||||
| } | |||||
| @@ -0,0 +1,129 @@ | |||||
| package com.iformall.config; | |||||
| import com.iformall.domain.po.PushLimit; | |||||
| import com.iformall.domain.po.WxCUser; | |||||
| import com.iformall.domain.po.WxScoreRules; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.cache.CacheManager; | |||||
| import org.springframework.cache.annotation.CachingConfigurerSupport; | |||||
| import org.springframework.cache.annotation.EnableCaching; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.data.redis.cache.RedisCacheConfiguration; | |||||
| import org.springframework.data.redis.cache.RedisCacheManager; | |||||
| import org.springframework.data.redis.connection.RedisConnectionFactory; | |||||
| import org.springframework.data.redis.core.RedisTemplate; | |||||
| import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; | |||||
| import org.springframework.data.redis.serializer.StringRedisSerializer; | |||||
| import java.time.Duration; | |||||
| import java.util.HashMap; | |||||
| import java.util.HashSet; | |||||
| import java.util.Map; | |||||
| import java.util.Set; | |||||
| /** | |||||
| * Created by Stormeye on 2018/10/1. | |||||
| */ | |||||
| @Configuration | |||||
| @EnableCaching | |||||
| public class RedisConfig extends CachingConfigurerSupport { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| //缓存管理器 | |||||
| @Bean | |||||
| public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { | |||||
| /* | |||||
| //user信息缓存配置 | |||||
| RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user"); | |||||
| Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(); | |||||
| redisCacheConfigurationMap.put("user", userCacheConfiguration); | |||||
| //初始化一个RedisCacheWriter | |||||
| RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); | |||||
| // 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现 | |||||
| // ClassLoader loader = this.getClass().getClassLoader(); | |||||
| // JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader); | |||||
| // RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer); | |||||
| // RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); | |||||
| RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); | |||||
| //设置默认超过期时间是30秒 | |||||
| defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); | |||||
| //初始化RedisCacheManager | |||||
| RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); | |||||
| return cacheManager; | |||||
| */ | |||||
| RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置 | |||||
| config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置 | |||||
| .disableCachingNullValues(); // 不缓存空值 | |||||
| // 设置一个初始化的缓存空间set集合 | |||||
| Set<String> cacheNames = new HashSet<>(); | |||||
| cacheNames.add("my-redis-cache1"); | |||||
| cacheNames.add("my-redis-cache2"); | |||||
| // 对每个缓存空间应用不同的配置 | |||||
| Map<String, RedisCacheConfiguration> configMap = new HashMap<>(); | |||||
| configMap.put("my-redis-cache1", config); | |||||
| configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120))); | |||||
| RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory) // 使用自定义的缓存配置初始化一个cacheManager | |||||
| .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置 | |||||
| .withInitialCacheConfigurations(configMap) | |||||
| .build(); | |||||
| return cacheManager; | |||||
| } | |||||
| @Bean("pushLimitRedisTemplate") | |||||
| public RedisTemplate<String, PushLimit> getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, PushLimit> template = new RedisTemplate<String, PushLimit>(); | |||||
| Jackson2JsonRedisSerializer<PushLimit> j = new Jackson2JsonRedisSerializer<PushLimit>(PushLimit.class); | |||||
| // value值的序列化 | |||||
| template.setValueSerializer(j); | |||||
| template.setHashKeySerializer(j); | |||||
| // key的序列化 | |||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setConnectionFactory(connectionFactory); | |||||
| return template; | |||||
| } | |||||
| @Bean("scoreRuleRedisTemplate") | |||||
| public RedisTemplate<String, WxScoreRules> getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, WxScoreRules> template = new RedisTemplate<String, WxScoreRules>(); | |||||
| Jackson2JsonRedisSerializer<WxScoreRules> j = new Jackson2JsonRedisSerializer<WxScoreRules>(WxScoreRules.class); | |||||
| // value值的序列化 | |||||
| template.setValueSerializer(j); | |||||
| template.setHashKeySerializer(j); | |||||
| // key的序列化 | |||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setConnectionFactory(connectionFactory); | |||||
| return template; | |||||
| } | |||||
| @Bean("cuserTokenRedisTemplate") | |||||
| public RedisTemplate<String, WxCUser> getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, WxCUser> template = new RedisTemplate<String, WxCUser>(); | |||||
| Jackson2JsonRedisSerializer<WxCUser> j = new Jackson2JsonRedisSerializer<WxCUser>(WxCUser.class); | |||||
| // value值的序列化 | |||||
| template.setValueSerializer(j); | |||||
| template.setHashKeySerializer(j); | |||||
| // key的序列化 | |||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setConnectionFactory(connectionFactory); | |||||
| return template; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.config; | |||||
| import javax.servlet.*; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.IOException; | |||||
| import java.util.Optional; | |||||
| /** | |||||
| * 前后端分离RESTful接口过滤器 | |||||
| * | |||||
| * @author xuguoqin | |||||
| * | |||||
| */ | |||||
| public class RestFilter implements Filter { | |||||
| @Override | |||||
| public void init(FilterConfig filterConfig) throws ServletException { | |||||
| } | |||||
| @Override | |||||
| public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | |||||
| throws IOException, ServletException { | |||||
| HttpServletRequest req = null; | |||||
| if (request instanceof HttpServletRequest) { | |||||
| req = (HttpServletRequest) request; | |||||
| } | |||||
| HttpServletResponse res = null; | |||||
| if (response instanceof HttpServletResponse) { | |||||
| res = (HttpServletResponse) response; | |||||
| } | |||||
| if (req != null && res != null) { | |||||
| //设置允许传递的参数 | |||||
| res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); | |||||
| //设置允许带上cookie | |||||
| res.setHeader("Access-Control-Allow-Credentials", "true"); | |||||
| String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer")); | |||||
| //设置允许的请求来源 | |||||
| res.setHeader("Access-Control-Allow-Origin", origin); | |||||
| //设置允许的请求方法 | |||||
| res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS"); | |||||
| } | |||||
| chain.doFilter(request, response); | |||||
| } | |||||
| @Override | |||||
| public void destroy() { | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,24 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.http.client.ClientHttpRequestFactory; | |||||
| import org.springframework.http.client.SimpleClientHttpRequestFactory; | |||||
| import org.springframework.web.client.RestTemplate; | |||||
| @Configuration | |||||
| public class RestTemplateConfig { | |||||
| @Bean | |||||
| public RestTemplate restTemplate(ClientHttpRequestFactory factory) { | |||||
| return new RestTemplate(factory); | |||||
| } | |||||
| @Bean | |||||
| public ClientHttpRequestFactory simpleClientHttpRequestFactory() { | |||||
| SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); | |||||
| factory.setReadTimeout(5000);//ms | |||||
| factory.setConnectTimeout(10000);//ms | |||||
| return factory; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,79 @@ | |||||
| package com.iformall.config; | |||||
| import com.fasterxml.jackson.annotation.JsonInclude; | |||||
| import com.fasterxml.jackson.databind.DeserializationConfig; | |||||
| import com.fasterxml.jackson.databind.DeserializationFeature; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import com.fasterxml.jackson.databind.module.SimpleModule; | |||||
| import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.http.converter.HttpMessageConverter; | |||||
| import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | |||||
| import org.springframework.web.servlet.config.annotation.CorsRegistry; | |||||
| import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |||||
| import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | |||||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||||
| import java.math.BigDecimal; | |||||
| import java.math.BigInteger; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.List; | |||||
| @Configuration | |||||
| @EnableWebMvc | |||||
| public class WebConfig implements WebMvcConfigurer { | |||||
| @Override | |||||
| public void addResourceHandlers(ResourceHandlerRegistry registry) { | |||||
| registry.addResourceHandler("swagger-ui.html") | |||||
| .addResourceLocations("classpath:/META-INF/resources/"); | |||||
| registry.addResourceHandler("/webjars/**") | |||||
| .addResourceLocations("classpath:/META-INF/resources/webjars/"); | |||||
| //registry.addResourceHandler("/app/**").addResourceLocations("classpath:/app/"); | |||||
| } | |||||
| @Override | |||||
| public void addCorsMappings(CorsRegistry registry) { | |||||
| registry.addMapping("/**") | |||||
| .allowedOrigins("*") | |||||
| .allowCredentials(true) | |||||
| .allowedMethods("GET", "POST", "DELETE", "PUT") | |||||
| .maxAge(3600); | |||||
| } | |||||
| @Override | |||||
| public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | |||||
| MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); | |||||
| //ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然 | |||||
| ObjectMapper objectMapper = new ObjectMapper(); | |||||
| SimpleModule simpleModule = new SimpleModule(); | |||||
| //不显示为null的字段 | |||||
| objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); | |||||
| DeserializationConfig dc = objectMapper.getDeserializationConfig(); | |||||
| // 设置反序列化日期格式、忽略不存在get、set的属性 | |||||
| objectMapper.setConfig( | |||||
| dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) | |||||
| .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) | |||||
| ); | |||||
| //序列化将Long转String类型 | |||||
| simpleModule.addSerializer(Long.class, ToStringSerializer.instance); | |||||
| simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); | |||||
| SimpleModule bigIntegerModule = new SimpleModule(); | |||||
| //序列化将BigInteger转String类型 | |||||
| bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance); | |||||
| SimpleModule bigDecimalModule = new SimpleModule(); | |||||
| //序列化将BigDecimal转String类型 | |||||
| bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); | |||||
| objectMapper.registerModule(simpleModule); | |||||
| objectMapper.registerModule(bigDecimalModule); | |||||
| objectMapper.registerModule(bigIntegerModule); | |||||
| jackson2HttpMessageConverter.setObjectMapper(objectMapper); | |||||
| converters.add(jackson2HttpMessageConverter); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,105 @@ | |||||
| package com.iformall.config; | |||||
| import com.iformall.interceptor.AuthHandshakeInterceptor; | |||||
| import lombok.Data; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.http.server.ServerHttpRequest; | |||||
| import org.springframework.messaging.simp.config.MessageBrokerRegistry; | |||||
| import org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler; | |||||
| import org.springframework.web.socket.WebSocketHandler; | |||||
| import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; | |||||
| import org.springframework.web.socket.config.annotation.StompEndpointRegistry; | |||||
| import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; | |||||
| import org.springframework.web.socket.server.support.DefaultHandshakeHandler; | |||||
| import java.security.Principal; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * websocket 配置 | |||||
| * https://docs.spring.io/spring-security/site/docs/4.0.x/reference/html/websocket.html | |||||
| * https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html | |||||
| * https://stackoverflow.com/questions/48903044/how-to-secure-websocket-application-spring-boot-stomp | |||||
| * | |||||
| * @author Stormeye | |||||
| * @version 2018/03/20 | |||||
| */ | |||||
| @Configuration | |||||
| @EnableWebSocketMessageBroker | |||||
| public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { | |||||
| @Autowired | |||||
| private RabbitMqProperty property; | |||||
| @Autowired | |||||
| private AuthHandshakeInterceptor authHandshakeInterceptor; | |||||
| /** | |||||
| * 配置了一个简单的消息代理, | |||||
| * 如果不重载,默认情况下回自动配置一个简单的内存消息代理,用来处理以"/topic"为前缀的消息。这里重载configureMessageBroker()方法, | |||||
| * 消息代理将会处理前缀为"/topic"和"/queue"的消息。 | |||||
| */ | |||||
| @Override | |||||
| public void configureMessageBroker(MessageBrokerRegistry registry) { | |||||
| // 这句话表示在topic和user这两个域上可以向客户端发消息。 | |||||
| /*registry.enableSimpleBroker("/topic", "/user") | |||||
| .setHeartbeatValue(new long[]{10000L, 10000L}) | |||||
| .setTaskScheduler(new DefaultManagedTaskScheduler());*/ | |||||
| registry.enableStompBrokerRelay("/topic", "/queue") | |||||
| .setRelayHost(property.getHost()) // rabbitmq-host服务器地址 | |||||
| .setRelayPort(61613) // rabbitmq-stomp 服务器服务端口 | |||||
| .setClientLogin(property.getUsername()) // 登陆账户 | |||||
| .setClientPasscode(property.getPassword()); // 登陆密码 | |||||
| // 这句话表示客户单向服务器端发送时的主题上面需要加"/app"作为前缀。/app/xxx | |||||
| registry.setApplicationDestinationPrefixes("/app"); | |||||
| // 这句话表示给指定用户发送一对一的主题前缀是"/user"。 /user/xxx | |||||
| registry.setUserDestinationPrefix("/user"); | |||||
| } | |||||
| /** | |||||
| * 连接站点配置 | |||||
| * 将"/gs-guide-websocket"路径注册为STOMP端点,这个路径与发送和接收消息的目的路径有所不同,这是一个端点,客户端在订阅或发布消息到目的地址前,要连接该端点, | |||||
| * 即用户发送请求url="/gs-guide-websocket"与STOMP server进行连接。之后再转发到订阅url; | |||||
| * PS:端点的作用——客户端在订阅或发布消息到目的地址前,要连接该端点。 | |||||
| */ | |||||
| @Override | |||||
| public void registerStompEndpoints(StompEndpointRegistry registry) { | |||||
| /* | |||||
| * 在网页上可以通过"/gs-guide-websocket"来和服务器的WebSocket连接 | |||||
| * 这个和客户端创建连接时的url有关,其中setAllowedOrigins()方法表示允许连接的域名,withSockJS()方法表示支持以SockJS方式连接服务器。 | |||||
| */ | |||||
| registry.addEndpoint("/ws").setAllowedOrigins("*") | |||||
| .addInterceptors(authHandshakeInterceptor); | |||||
| } | |||||
| /** | |||||
| * 输入通道配置 | |||||
| * | |||||
| * @param registration | |||||
| */ | |||||
| /* | |||||
| @Override | |||||
| public void configureClientInboundChannel(ChannelRegistration registration) { | |||||
| registration.interceptors(inboundChannelInterceptor); | |||||
| registration.taskExecutor() // 线程信息 | |||||
| .corePoolSize(400) // 核心线程池 | |||||
| .maxPoolSize(800) // 最多线程池数 | |||||
| .keepAliveSeconds(60); // 超过核心线程数后,空闲线程超时60秒则杀死 | |||||
| }*/ | |||||
| /** | |||||
| * 消息传输参数配置 | |||||
| * | |||||
| * @param registration | |||||
| */ | |||||
| /* | |||||
| @Override | |||||
| public void configureWebSocketTransport(WebSocketTransportRegistration registration) { | |||||
| registration.setSendTimeLimit(15 * 1000) // 超时时间 | |||||
| .setSendBufferSizeLimit(512 * 1024) // 缓存空间 | |||||
| .setMessageSizeLimit(128 * 1024); // 消息大小 | |||||
| } | |||||
| */ | |||||
| } | |||||
| @@ -0,0 +1,147 @@ | |||||
| package com.iformall.controller; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxCUser; | |||||
| import com.iformall.domain.po.WxCUserBasicInfo; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.interceptor.AuthHandshakeInterceptor; | |||||
| import com.iformall.service.WxAppinfoService; | |||||
| import com.iformall.service.WxCUserBasicInfoService; | |||||
| import com.iformall.service.WxCUserService; | |||||
| import com.iformall.utils.IPUtil; | |||||
| import com.iformall.utils.MaUtil; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.WebDataBinder; | |||||
| import org.springframework.web.bind.annotation.InitBinder; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import org.springframework.web.context.request.RequestContextHolder; | |||||
| import org.springframework.web.context.request.ServletRequestAttributes; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.beans.PropertyEditorSupport; | |||||
| import java.text.ParseException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| @RestController | |||||
| public class BaseController { | |||||
| @Autowired | |||||
| private WxCUserService wxCUserService; | |||||
| @Autowired | |||||
| private WxAppinfoService wxAppinfoService; | |||||
| @Autowired | |||||
| private WxCUserBasicInfoService wxCUserBasicInfoService; | |||||
| @InitBinder | |||||
| public void InitBinder(WebDataBinder dataBinder) { | |||||
| dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { | |||||
| public void setAsText(String value) { | |||||
| try { | |||||
| setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)); | |||||
| } catch (ParseException e) { | |||||
| try { | |||||
| setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value)); | |||||
| } catch (ParseException e1) { | |||||
| setValue(null); | |||||
| } | |||||
| } | |||||
| } | |||||
| public String getAsText() { | |||||
| return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue()); | |||||
| } | |||||
| }); | |||||
| } | |||||
| public Long getUserId() { | |||||
| ServletRequestAttributes ll = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); | |||||
| HttpServletRequest request = ll.getRequest(); | |||||
| Long cUserId = (Long) request.getAttribute(AuthHandshakeInterceptor.LOGIN_USER_KEY); | |||||
| return cUserId; | |||||
| } | |||||
| public WxCUser getUser() { | |||||
| Long cUserId = getUserId(); | |||||
| WxCUser user = wxCUserService.getById(cUserId); | |||||
| if (user == null) | |||||
| throw new MallinkException(ErrorCode.USER_IS_EMPTY); | |||||
| return user; | |||||
| } | |||||
| public String getTenantId() { | |||||
| HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); | |||||
| String tenantId = (String) request.getAttribute(AuthHandshakeInterceptor.TENANT_ID); | |||||
| return tenantId; | |||||
| } | |||||
| public WxAppinfo getAppInfo(String appId) { | |||||
| return wxAppinfoService.getByAppId(appId); | |||||
| } | |||||
| public WxMaService getWeappService(String appId) { | |||||
| WxAppinfo appinfo = wxAppinfoService.getByAppId(appId); | |||||
| if (appinfo == null) { | |||||
| return null; | |||||
| } | |||||
| WxMaService service = MaUtil.getWeappService(appinfo); | |||||
| return service; | |||||
| } | |||||
| public WxMaService getWeappServiceByAppInfo(WxAppinfo appinfo) { | |||||
| WxMaService service = MaUtil.getWeappService(appinfo); | |||||
| return service; | |||||
| } | |||||
| public void saveToBasicInfo(WxCUser user) { | |||||
| String phone = user.getPhone(); | |||||
| if (phone != null && phone.contains("*")) { | |||||
| phone = user.getVerifyCodePhone(); | |||||
| } | |||||
| if (StringUtils.isBlank(phone)) | |||||
| return; | |||||
| List<WxCUserBasicInfo> list = wxCUserBasicInfoService.findByPhone(user.getTenantId(), phone); | |||||
| if (list.size() > 0) { | |||||
| WxCUserBasicInfo basicInfo = list.get(0); | |||||
| // 微信名称 | |||||
| if (basicInfo.getNickName() == null || basicInfo.getNickName().equals(user.getNickName())) { | |||||
| basicInfo.setNickName(user.getNickName()); | |||||
| } | |||||
| // 性别 | |||||
| if (basicInfo.getSex() == null) { | |||||
| basicInfo.setSex(user.getGender()); | |||||
| } | |||||
| // 成长值 | |||||
| if (basicInfo.getPoins() == null) { | |||||
| basicInfo.setPoins(user.getScore()); | |||||
| } | |||||
| wxCUserBasicInfoService.updateObj(basicInfo, user.getId()); | |||||
| } else { | |||||
| Date cur = new Date(); | |||||
| WxCUserBasicInfo basicInfo = new WxCUserBasicInfo(); | |||||
| basicInfo.setId(user.getId()); | |||||
| basicInfo.setTenantId(user.getTenantId()); | |||||
| basicInfo.setPhone(phone); | |||||
| basicInfo.setNickName(user.getNickName()); | |||||
| basicInfo.setSex(user.getGender()); | |||||
| basicInfo.setPoins(user.getScore()); | |||||
| basicInfo.setCreateDate(cur); | |||||
| basicInfo.setUpdateDate(cur); | |||||
| wxCUserBasicInfoService.save(basicInfo); | |||||
| } | |||||
| } | |||||
| public String getIpAddr() { | |||||
| HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); | |||||
| String ipaddress = IPUtil.getIpAddr(request); | |||||
| return ipaddress; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| package com.iformall.controller; | |||||
| import com.iformall.common.ResultData; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| @RestController | |||||
| @Api(description = "登录相关接口") | |||||
| public class HomeController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Value("${version}") | |||||
| private String version; | |||||
| @ApiOperation("获取后端版本号") | |||||
| @GetMapping("/version") | |||||
| public ResultData version() { | |||||
| return new ResultData(version); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,58 @@ | |||||
| package com.iformall.controller; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.messaging.simp.SimpMessagingTemplate; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @RestController | |||||
| @RequestMapping("/websocket") | |||||
| public class SendController { | |||||
| @Autowired | |||||
| private SimpMessagingTemplate messagingTemplate; | |||||
| /** | |||||
| * 通知消息 | |||||
| */ | |||||
| @GetMapping("/noticea") | |||||
| public void noticea() { | |||||
| messagingTemplate.convertAndSend("/topic/1001A", JSON.toJSONString("这是A通知消息!!")); | |||||
| } | |||||
| /** | |||||
| * 通知消息 | |||||
| */ | |||||
| @GetMapping("/noticeb") | |||||
| public void noticeb() { | |||||
| messagingTemplate.convertAndSend("/topic/1001B", JSON.toJSONString("这是B通知消息!!")); | |||||
| } | |||||
| /** | |||||
| * 通知消息 | |||||
| */ | |||||
| @GetMapping("/noticec") | |||||
| public void noticec() { | |||||
| messagingTemplate.convertAndSend("/topic/1001C", JSON.toJSONString("这是B通知消息!!")); | |||||
| } | |||||
| /** | |||||
| * 具体用户消息 | |||||
| */ | |||||
| @GetMapping("/user/{name}") | |||||
| public void user(@PathVariable("name") String name) { | |||||
| messagingTemplate.convertAndSendToUser(name, "/message", JSON.toJSONString("这是发送给sa;fa;sfj" + name + "用户的消息!!")); | |||||
| ///messagingTemplate.convertAndSendToUser(name, "/user/"+name+"/message", JSON.toJSONString("这是发送给" + name + "用户的消息!!")); | |||||
| //messagingTemplate.convertAndSend("/user/"+name+"/message", JSON.toJSONString("用户的消息!!")); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,62 @@ | |||||
| package com.iformall.controller.websocket; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.interceptor.AuthHandshakeInterceptor; | |||||
| import lombok.Data; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.messaging.handler.annotation.DestinationVariable; | |||||
| import org.springframework.messaging.handler.annotation.MessageMapping; | |||||
| import org.springframework.messaging.simp.SimpMessageSendingOperations; | |||||
| import org.springframework.messaging.simp.stomp.StompHeaderAccessor; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import javax.websocket.Session; | |||||
| import java.security.Principal; | |||||
| /** | |||||
| * websocket Controller | |||||
| * | |||||
| * @author Stormeye | |||||
| */ | |||||
| @RestController | |||||
| public class ReceiverController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| SimpMessageSendingOperations simpMessageSendingOperations; | |||||
| /** | |||||
| * 接收客户端发来的消息 | |||||
| */ | |||||
| @MessageMapping("/message") | |||||
| public void handleSubscribe(String msg, StompHeaderAccessor stompHeaderAccessor) { | |||||
| //System.out.println("测试发送消息:随机消息" +session.getId()); | |||||
| Principal user = stompHeaderAccessor.getUser(); | |||||
| String tenantId = (String) stompHeaderAccessor.getSessionAttributes().get(AuthHandshakeInterceptor.TENANT_ID); | |||||
| Long userId = (Long) stompHeaderAccessor.getSessionAttributes().get(AuthHandshakeInterceptor.LOGIN_USER_KEY); | |||||
| logger.info("客户端[" + stompHeaderAccessor.getSessionId() + "]发来消息:, " + msg + "\n" + stompHeaderAccessor.getSessionAttributes().toString()); | |||||
| JSONObject json = JSONObject.parseObject(msg); | |||||
| String to = json.getString("to"); | |||||
| if (StringUtils.isNotBlank(to)) { | |||||
| simpMessageSendingOperations.convertAndSendToUser(to, "/message", msg); | |||||
| } else { | |||||
| simpMessageSendingOperations.convertAndSendToUser("oX7SP4qpcX7LTmLjNuuFSQFXuK0M", "/message", msg); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 接收客户端发来的群聊消息 | |||||
| */ | |||||
| @MessageMapping("/chat-group/{roomId}") | |||||
| public void handleGroupMsg(@DestinationVariable String roomId, String msg) { | |||||
| logger.info("客户端发来群组消息:" + msg); | |||||
| simpMessageSendingOperations.convertAndSend("/topic/chat-group/" + roomId, msg); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,93 @@ | |||||
| package com.iformall.interceptor; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.WxCUser; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.service.WxCUserService; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.http.server.ServerHttpRequest; | |||||
| import org.springframework.http.server.ServerHttpResponse; | |||||
| import org.springframework.http.server.ServletServerHttpRequest; | |||||
| import org.springframework.stereotype.Component; | |||||
| import org.springframework.web.socket.WebSocketHandler; | |||||
| import org.springframework.web.socket.server.HandshakeInterceptor; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpSession; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * websocket 握手 | |||||
| * | |||||
| * @author Stormeye | |||||
| * @version 2019/03/20 | |||||
| */ | |||||
| @Component | |||||
| public class AuthHandshakeInterceptor implements HandshakeInterceptor { | |||||
| private Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| WxCUserService wxCUserService; | |||||
| public static final String LOGIN_USER_KEY = "LOGIN_USER_KEY"; | |||||
| public static final String TENANT_ID = "TENANT_ID"; | |||||
| @Override | |||||
| public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { | |||||
| if (request instanceof ServletServerHttpRequest) { | |||||
| ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request; | |||||
| // 获取token认证 | |||||
| String token = serverHttpRequest.getServletRequest().getHeader("token"); | |||||
| // 如果header中不存在token,则从参数中获取token | |||||
| if(StringUtils.isBlank(token)){ | |||||
| token = serverHttpRequest.getServletRequest().getParameter("token"); | |||||
| } | |||||
| //token为空 | |||||
| if(StringUtils.isBlank(token)){ | |||||
| throw new MallinkException(ErrorCode.NET_TOKEN_EMPTY); | |||||
| } | |||||
| // 查询token信息 | |||||
| WxCUser wxCUser = wxCUserService.getByToken(token); | |||||
| if(wxCUser == null || wxCUser.getExpireTime().getTime() < System.currentTimeMillis()){ | |||||
| throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), "URL:" + serverHttpRequest.getServletRequest().getRequestURI() + " token失效,请重新登录"); | |||||
| } | |||||
| HttpSession session = serverHttpRequest.getServletRequest().getSession(); | |||||
| if (session != null) { | |||||
| //attributes.put("userId", session.getAttribute("userId")); | |||||
| attributes.put(LOGIN_USER_KEY, wxCUser.getId()); | |||||
| attributes.put(TENANT_ID, wxCUser.getTenantId()); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /* | |||||
| HttpSession session = getSession(request); | |||||
| if(session==null || session.getAttribute("user")==null){ | |||||
| logger.error("websocket权限拒绝"); | |||||
| return false; | |||||
| } | |||||
| attributes.put("user",session.getAttribute("user")); | |||||
| */ | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { | |||||
| } | |||||
| // 参考 HttpSessionHandshakeInterceptor | |||||
| private HttpSession getSession(ServerHttpRequest request) { | |||||
| if (request instanceof ServletServerHttpRequest) { | |||||
| ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request; | |||||
| return serverRequest.getServletRequest().getSession(false); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,89 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true | |||||
| username: ENC(dZ8fmrtuBMQYaRytKQgTqg==) | |||||
| password: ENC(WGu0+1DPIHrqorDhrbq1+7wr7xNG53mN) | |||||
| type: com.alibaba.druid.pool.DruidDataSource | |||||
| driver-class-name: com.mysql.cj.jdbc.Driver | |||||
| filters: stat | |||||
| maxActive: 20 | |||||
| initialSize: 1 | |||||
| maxWait: 60000 | |||||
| minIdle: 1 | |||||
| timeBetweenEvictionRunsMillis: 28000 | |||||
| minEvictableIdleTimeMillis: 28000 | |||||
| validationQuery: select 'x' | |||||
| testWhileIdle: true | |||||
| testOnBorrow: false | |||||
| testOnReturn: false | |||||
| poolPreparedStatements: true | |||||
| maxOpenPreparedStatements: 20 | |||||
| connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" | |||||
| #jackson: | |||||
| #date-format: yyyy-MM-dd HH:mm:ss | |||||
| # REDIS | |||||
| redis: | |||||
| host: 202.165.179.86 | |||||
| port: 6379 | |||||
| password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 50 | |||||
| max-idle: 50 | |||||
| max-wait: -1 | |||||
| min-idle: 10 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(R0bER9E9OB9/YQcpNXMyYDwofNVb8/pFl4nrApS8mi0=) | |||||
| password: ENC(50YqJd0iK/2r2YnmEd5RKaki3ktU73UDapBJrVYfqmc=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: localhost | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) | |||||
| secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) | |||||
| jasypt: | |||||
| encryptor: | |||||
| password: oRqdnDbK5pj3eMmB | |||||
| fm: | |||||
| exception: false | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall.mapper: debug | |||||
| path: ./logs/w | |||||
| @@ -0,0 +1,75 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true | |||||
| username: ENC(NUzgQOdJnCbVLKT6BaX0aw==) | |||||
| password: ENC(mvuoDRiu0jqYaKNRwwTuXZ6U7aoIaqsjdiPqTLgi/nY=) | |||||
| type: com.alibaba.druid.pool.DruidDataSource | |||||
| driver-class-name: com.mysql.cj.jdbc.Driver | |||||
| filters: stat | |||||
| maxActive: 20 | |||||
| initialSize: 1 | |||||
| maxWait: 60000 | |||||
| minIdle: 1 | |||||
| timeBetweenEvictionRunsMillis: 28000 | |||||
| minEvictableIdleTimeMillis: 28000 | |||||
| validationQuery: select 'x' | |||||
| testWhileIdle: true | |||||
| testOnBorrow: false | |||||
| testOnReturn: false | |||||
| poolPreparedStatements: true | |||||
| maxOpenPreparedStatements: 20 | |||||
| connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" | |||||
| # REDIS | |||||
| redis: | |||||
| host: 127.0.0.1 | |||||
| port: 6379 | |||||
| password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 8 | |||||
| max-idle: 8 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(I2YKxnRVPY7J1r/bwzwHOhQCjj3nVqCWEbVTJvBq7y0=) | |||||
| password: ENC(APQMO9XQRzMKd0eap+oSSOYH9MQe/r5K0YFF9A9mizU=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| # RABBITMQ | |||||
| rabbitmq: | |||||
| host: localhost | |||||
| port: 5672 | |||||
| username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) | |||||
| password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) | |||||
| secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) | |||||
| fm: | |||||
| exception: true | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall: debug | |||||
| path: ./logs/w | |||||
| @@ -0,0 +1,73 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true | |||||
| username: ENC(Uc0AjgkytxHHCwZrmDASWg==) | |||||
| password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=) | |||||
| type: com.alibaba.druid.pool.DruidDataSource | |||||
| driver-class-name: com.mysql.cj.jdbc.Driver | |||||
| filters: stat | |||||
| maxActive: 20 | |||||
| initialSize: 1 | |||||
| maxWait: 60000 | |||||
| minIdle: 1 | |||||
| timeBetweenEvictionRunsMillis: 28000 | |||||
| minEvictableIdleTimeMillis: 28000 | |||||
| validationQuery: select 'x' | |||||
| testWhileIdle: true | |||||
| testOnBorrow: false | |||||
| testOnReturn: false | |||||
| poolPreparedStatements: true | |||||
| maxOpenPreparedStatements: 20 | |||||
| connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" | |||||
| # REDIS | |||||
| redis: | |||||
| host: 127.0.0.1 | |||||
| port: 6379 | |||||
| password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 8 | |||||
| max-idle: 8 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(HFbRXtAFVxU36Hk0yT3reyvRuLrw3RhMlbxFj9Ev/VY=) | |||||
| password: ENC(pk4+/3C5n2hMYmgi+VTqI4P1m77DllW8y4KElMXXmIo=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| # RABBITMQ | |||||
| rabbitmq: | |||||
| host: 127.0.0.1 | |||||
| port: 5672 | |||||
| username: ENC(aSRr6mnSryEqzHHz1hJf1g==) | |||||
| password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=) | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) | |||||
| secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) | |||||
| fm: | |||||
| exception: true | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall: debug | |||||
| path: ./logs/w | |||||
| @@ -0,0 +1,76 @@ | |||||
| server: | |||||
| port: 7100 | |||||
| servlet: | |||||
| context-path: /W | |||||
| spring: | |||||
| application: | |||||
| name: mallink | |||||
| profiles: | |||||
| active: dev | |||||
| jackson: | |||||
| date-format: yyyy-MM-dd HH:mm:ss | |||||
| time-zone: GMT+8 | |||||
| default-property-inclusion: non_null | |||||
| servlet: | |||||
| multipart: | |||||
| max-file-size: 2MB | |||||
| max-request-size: 2MB | |||||
| cache: | |||||
| type: REDIS | |||||
| cache-names: redis_cache #缓存的名字(可以不指定) | |||||
| redis: | |||||
| time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) | |||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: 202.165.179.86 | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| # @{link} https://github.com/abel533 | |||||
| #Mybatis | |||||
| mybatis: | |||||
| type-aliases-package: com.iformall.domain.po | |||||
| mapper-locations: classpath:mapper/*Mapper.xml | |||||
| configuration: | |||||
| map-underscore-to-camel-case: true | |||||
| cache-enabled: true | |||||
| lazy-loading-enabled: true | |||||
| use-generated-keys: true | |||||
| default-fetch-size: 100 | |||||
| default-statement-timeout: 10 | |||||
| #PageHelper | |||||
| pagehelper: | |||||
| helperDialect: mysql | |||||
| reasonable: false | |||||
| supportMethodsArguments: true | |||||
| params: count=countSql | |||||
| offset-as-page-num: true | |||||
| page-size-zero: true | |||||
| row-bounds-with-count: true | |||||
| mapper: | |||||
| mappers: | |||||
| - com.iformall.common.CommonMapper | |||||
| pay: | |||||
| real: true | |||||
| version: @project.version@ | |||||
| debug: true | |||||
| @@ -0,0 +1,100 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <configuration scan="true" scanPeriod="10 seconds"> | |||||
| <!-- 外部指定路径 --> | |||||
| <springProperty scop="context" name="logPath" source="logging.path" /> | |||||
| <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | |||||
| <encoder> | |||||
| <Pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] --%mdc{client}%msg%n</Pattern> | |||||
| </encoder> | |||||
| </appender> | |||||
| <appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/trace.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/trace.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| </appender> | |||||
| <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/info.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/info.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>INFO</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/debug.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/debug.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>DEBUG</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/warn.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/warn.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>WARN</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/error.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/error.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>ERROR</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <root level="TRACE"> | |||||
| <appender-ref ref="TRACE_FILE" /> | |||||
| <appender-ref ref="INFO_FILE" /> | |||||
| <!-- <appender-ref ref="DEBUG_FILE" /> --> | |||||
| <!-- <appender-ref ref="WARN_FILE" /> --> | |||||
| <appender-ref ref="ERROR_FILE" /> | |||||
| </root> | |||||
| <root level="INFO"> | |||||
| <appender-ref ref="STDOUT" /> | |||||
| </root> | |||||
| </configuration> | |||||
| @@ -18,6 +18,7 @@ | |||||
| <module>mallinkBApi</module> | <module>mallinkBApi</module> | ||||
| <module>mallinkSchedule</module> | <module>mallinkSchedule</module> | ||||
| <module>mallinkMQConsumer</module> | <module>mallinkMQConsumer</module> | ||||
| <module>mallinkWebSocketServer</module> | |||||
| </modules> | </modules> | ||||
| <parent> | <parent> | ||||
| @@ -72,10 +73,6 @@ | |||||
| <optional>true</optional> | <optional>true</optional> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-websocket</artifactId> | |||||
| </dependency> | |||||
| <dependency> | <dependency> | ||||
| <groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
| <artifactId>spring-boot-starter-web-services</artifactId> | <artifactId>spring-boot-starter-web-services</artifactId> | ||||