commit 9b26a4c96f36744e252bf7cdba6fde5c35a1ce44 Author: wudi <3362189749@qq.com> Date: Tue Dec 5 21:07:28 2023 +0800 月考推送 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..9968edb --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..132404b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bwie-auth/.gitignore b/bwie-auth/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-auth/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-auth/pom.xml b/bwie-auth/pom.xml new file mode 100644 index 0000000..00cad91 --- /dev/null +++ b/bwie-auth/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.bwie + tenement + 1.0-SNAPSHOT + + + bwie-auth + + + + + com.bwie + bwie-common + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + + + org.springframework.kafka + spring-kafka + + + + + diff --git a/bwie-auth/src/main/java/com/bwie/AuthApplication.java b/bwie-auth/src/main/java/com/bwie/AuthApplication.java new file mode 100644 index 0000000..154c7d6 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/AuthApplication.java @@ -0,0 +1,21 @@ +package com.bwie; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @ClassName AuthApplication + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:37 + */ +@SpringBootApplication +@EnableFeignClients +@EnableCircuitBreaker +public class AuthApplication { + public static void main(String[] args) { + SpringApplication.run(AuthApplication.class); + } +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/config/ConfirmCallbackConfig.java b/bwie-auth/src/main/java/com/bwie/auth/config/ConfirmCallbackConfig.java new file mode 100644 index 0000000..5d0233a --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/config/ConfirmCallbackConfig.java @@ -0,0 +1,48 @@ +package com.bwie.auth.config; + +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @ClassName: + * @Description: 消息发送到 broker的确认 重写 confirm 方法 + * @Author: zhuwenqiang + * @Date: 2023/10/23 + */ +@Component +public class ConfirmCallbackConfig implements RabbitTemplate.ConfirmCallback { + + @Autowired + private RabbitTemplate rabbitTemplate; + + /** + * 当前类被初始化的时候执行的方法 + * + */ + @PostConstruct + public void init() { + // 设置 rabbitTemplate 的消息发送到交换机确认 + rabbitTemplate.setConfirmCallback(this); + } + + /** + * 消息发送到交换机 无论成功或者失败 都会执行 + * + * @param correlationData correlation data for the callback. + * @param ack true for ack, false for nack true 成功 false 失败 + * @param cause An optional cause, for nack, when available, otherwise null. + */ + @Override + public void confirm(CorrelationData correlationData, boolean ack, String cause) { + if (ack) { + System.out.println("消息发送到broker成功!"); + } else { + System.out.println("消息发送到broker失败,失败的原因是:" + cause); + } + } + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/config/RabbitAdminConfig.java b/bwie-auth/src/main/java/com/bwie/auth/config/RabbitAdminConfig.java new file mode 100644 index 0000000..d2abf6c --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/config/RabbitAdminConfig.java @@ -0,0 +1,53 @@ +package com.bwie.auth.config; + +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * RabbitAdmin是RabbitMQ的一个Java客户端库,它提供了管理RabbitMQ资源的功能。它是通过与RabbitMQ服务器进行交互来执行管理操作的。 + */ +@Configuration +public class RabbitAdminConfig { + + @Value("${spring.rabbitmq.host}") + private String host; + @Value("${spring.rabbitmq.username}") + private String username; + @Value("${spring.rabbitmq.password}") + private String password; + @Value("${spring.rabbitmq.virtualhost}") + private String virtualhost; + + /** + * 构建 RabbitMQ的连接工厂 + * @return + */ + @Bean + public ConnectionFactory connectionFactory() { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); + connectionFactory.setAddresses(host); + connectionFactory.setUsername(username); + connectionFactory.setPassword(password); + connectionFactory.setVirtualHost(virtualhost); + // 配置发送确认回调时,次配置必须配置,否则即使在RabbitTemplate配置了ConfirmCallback也不会生效 + connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED); + connectionFactory.setPublisherReturns(true); + return connectionFactory; + } + + /** + * 自己初始化 RabbitAdmin + * @param connectionFactory + * @return + */ + @Bean + public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); + rabbitAdmin.setAutoStartup(true); + return rabbitAdmin; + } +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/config/RabbitmqConfig.java b/bwie-auth/src/main/java/com/bwie/auth/config/RabbitmqConfig.java new file mode 100644 index 0000000..1aea523 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/config/RabbitmqConfig.java @@ -0,0 +1,16 @@ +package com.bwie.auth.config; + +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitmqConfig { + // 消息转换配置 SimpleMessageConverter String byte[] serializable + @Bean + public MessageConverter jsonMessageConverter() { + return new Jackson2JsonMessageConverter(); + } + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/config/ReturnsCallbackConfig.java b/bwie-auth/src/main/java/com/bwie/auth/config/ReturnsCallbackConfig.java new file mode 100644 index 0000000..3fec6bf --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/config/ReturnsCallbackConfig.java @@ -0,0 +1,40 @@ +package com.bwie.auth.config; + +import org.springframework.amqp.core.ReturnedMessage; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @ClassName: + * @Description: 消息发送到队列的确认 + * @Author: zhuwenqiang + * @Date: 2023/10/23 + */ +@Component +public class ReturnsCallbackConfig implements RabbitTemplate.ReturnsCallback { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @PostConstruct + public void init() { + rabbitTemplate.setReturnsCallback(this); + } + + /** + * 只有发送到队列失败才会执行 + * + * @param returnedMessage the returned message and metadata. + */ + @Override + public void returnedMessage(ReturnedMessage returnedMessage) { + System.out.println("消息" + returnedMessage.getMessage().toString() + + "被交换机" + returnedMessage.getExchange() + "回退!" + + "退回原因为:" + returnedMessage.getReplyText()); + // TODO 补偿 可以再发 做日志记录 + } + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/controller/AuthController.java b/bwie-auth/src/main/java/com/bwie/auth/controller/AuthController.java new file mode 100644 index 0000000..0573693 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/controller/AuthController.java @@ -0,0 +1,44 @@ +package com.bwie.auth.controller; + +import com.bwie.auth.service.AuthService; +import com.bwie.common.domain.User; +import com.bwie.common.domain.request.UserReq; +import com.bwie.common.domain.response.JwtRes; +import com.bwie.common.result.Result; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Generated; + +/** + * @ClassName AuthController + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:21 + */ +@RestController +public class AuthController { + + @Autowired + private AuthService service; + + @PostMapping("/login") + public Result login(@RequestBody UserReq req){ + Result result = service.login(req); + + return result; + } + + @GetMapping("/userInfo") + public Result userInfo(){ + + User user= service.userInfo(); + + return Result.success(user); + } + + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/feign/AuthFeignService.java b/bwie-auth/src/main/java/com/bwie/auth/feign/AuthFeignService.java new file mode 100644 index 0000000..d57865a --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/feign/AuthFeignService.java @@ -0,0 +1,19 @@ +package com.bwie.auth.feign; + +import com.bwie.common.domain.User; +import com.bwie.common.result.Result; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * @ClassName AuthFeignService + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:22 + */ +@FeignClient("bwie-user") +public interface AuthFeignService { + @PostMapping("/findByNum") + public Result findByNum(@RequestParam String num); +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/feign/impl/AuthFeignServiceImpl.java b/bwie-auth/src/main/java/com/bwie/auth/feign/impl/AuthFeignServiceImpl.java new file mode 100644 index 0000000..66b6674 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/feign/impl/AuthFeignServiceImpl.java @@ -0,0 +1,28 @@ +package com.bwie.auth.feign.impl; + +import com.bwie.auth.service.AuthService; +import com.bwie.auth.service.impl.AuthServiceImpl; +import com.bwie.common.domain.request.UserReq; +import com.bwie.common.domain.response.JwtRes; +import com.bwie.common.result.Result; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + +/** + * @ClassName AuthFeignServiceImpl + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:32 + */ +@Component +public class AuthFeignServiceImpl implements FallbackFactory { + @Override + public AuthService create(Throwable cause) { + return new AuthServiceImpl() { + @Override + public Result login(UserReq req) { + return Result.error("服务器异常"); + } + }; + } +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/service/AuthService.java b/bwie-auth/src/main/java/com/bwie/auth/service/AuthService.java new file mode 100644 index 0000000..6c27533 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/service/AuthService.java @@ -0,0 +1,20 @@ +package com.bwie.auth.service; + +import com.bwie.common.domain.User; +import com.bwie.common.domain.request.UserReq; +import com.bwie.common.domain.response.JwtRes; +import com.bwie.common.result.Result; + +/** + * @ClassName AuthService + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:21 + */ +public interface AuthService { + Result login(UserReq req); + + + User userInfo(); + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/service/impl/AuthServiceImpl.java b/bwie-auth/src/main/java/com/bwie/auth/service/impl/AuthServiceImpl.java new file mode 100644 index 0000000..fd9a51f --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/service/impl/AuthServiceImpl.java @@ -0,0 +1,98 @@ +package com.bwie.auth.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.bwie.auth.feign.AuthFeignService; +import com.bwie.auth.service.AuthService; +import com.bwie.common.Exception.ServiceException; +import com.bwie.common.constants.JwtConstants; +import com.bwie.common.constants.TokenConstants; +import com.bwie.common.domain.User; +import com.bwie.common.domain.request.UserReq; +import com.bwie.common.domain.response.JwtRes; +import com.bwie.common.result.Result; +import com.bwie.common.utils.JwtUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.HashMap; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * @ClassName AuthServiceImpl + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:21 + */ +@Service +public class AuthServiceImpl implements AuthService{ + + @Autowired + private AuthFeignService service; + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private HttpServletRequest request; + + + @Override + public Result login(UserReq req) { + + Result byNum = service.findByNum(req.getNum()); + + User data = byNum.getData(); + + if (byNum.getCode()==500){ + throw new ServiceException(byNum.getMsg()); + } + + if (data==null){ + throw new ServiceException("用户不存在"); + } + + if (!req.getPwd().equals(data.getPwd())){ + throw new ServiceException("密码错误"); + } + + //获取当前登录时间 + + User user = new User(); + + user.setGetLoginDate(new Date()); + + HashMap map = new HashMap<>(); + + String userKey = UUID.randomUUID().toString().replace("-", ""); + + map.put(JwtConstants.USER_KEY,userKey); + + String token = JwtUtils.createToken(map); + + redisTemplate.opsForValue().set(TokenConstants.LOGIN_TOKEN_KEY + userKey, JSONObject.toJSONString(data), 30, TimeUnit.MINUTES); + + JwtRes jwtRes = new JwtRes(); + jwtRes.setToken(token); + jwtRes.setExTime("15FZ"); + + return Result.success(jwtRes); + } + + @Override + public User userInfo() { + + String token = request.getHeader(TokenConstants.TOKEN); + + String userKey = JwtUtils.getUserKey(token); + + String s = redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey); + + return JSONObject.parseObject(s, User.class); + } + + +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/utils/DLXQueue.java b/bwie-auth/src/main/java/com/bwie/auth/utils/DLXQueue.java new file mode 100644 index 0000000..d76e2c2 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/utils/DLXQueue.java @@ -0,0 +1,77 @@ +package com.bwie.auth.utils; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; + +@Component +public class DLXQueue { + // routingKey + private static final String DEAD_ROUTING_KEY = "dead.routingkey"; + private static final String ROUTING_KEY = "routingkey"; + private static final String DEAD_EXCHANGE = "dead.exchange"; + private static final String EXCHANGE = "common.exchange"; + @Autowired + RabbitTemplate rabbitTemplate; + @Resource + RabbitAdmin rabbitAdmin; + + /** + * 发送死信队列,过期后进入死信交换机,进入死信队列 + * + * @param queueName 队列名称 + * @param deadQueueName 死信队列名称 + * @param params 消息内容 + * @param expiration 过期时间 毫秒 + */ + public void sendDLXQueue(String queueName, String deadQueueName, Object params, Integer expiration) { + /** + * ----------------------------------先创建一个ttl队列和死信队列-------------------------------------------- + */ + Map map = new HashMap<>(); + // 队列设置存活时间,单位ms, 必须是整形数据。 + map.put("x-message-ttl", expiration); + // 设置死信交换机 + map.put("x-dead-letter-exchange", DEAD_EXCHANGE); + // 设置死信交换器路由 + map.put("x-dead-letter-routing-key", DEAD_ROUTING_KEY); + /*参数1:队列名称 参数2:持久化 参数3:是否排他 参数4:自动删除队列 参数5:队列参数*/ + Queue queue = new Queue(queueName, true, false, false, map); + rabbitAdmin.declareQueue(queue); + /** + * ---------------------------------创建交换机--------------------------------------------- + */ + DirectExchange directExchange = new DirectExchange(EXCHANGE, true, false); + rabbitAdmin.declareExchange(directExchange); + /** + * ---------------------------------队列绑定交换机--------------------------------------------- + */ + Binding binding = BindingBuilder.bind(queue).to(directExchange).with(ROUTING_KEY); + rabbitAdmin.declareBinding(binding); + /** + * ---------------------------------在创建一个死信交换机和队列,接收死信队列--------------------------------------------- + */ + DirectExchange deadExchange = new DirectExchange(DEAD_EXCHANGE, true, false); + rabbitAdmin.declareExchange(deadExchange); + + Queue deadQueue = new Queue(deadQueueName, true, false, false); + rabbitAdmin.declareQueue(deadQueue); + /** + * ---------------------------------队列绑定死信交换机--------------------------------------------- + */ + // 将队列和交换机绑定 + Binding deadbinding = BindingBuilder.bind(deadQueue).to(deadExchange).with(DEAD_ROUTING_KEY); + rabbitAdmin.declareBinding(deadbinding); + // 发送消息 + rabbitTemplate.convertAndSend(EXCHANGE, ROUTING_KEY, params); + } +} diff --git a/bwie-auth/src/main/java/com/bwie/auth/utils/DelayedQueue.java b/bwie-auth/src/main/java/com/bwie/auth/utils/DelayedQueue.java new file mode 100644 index 0000000..0df9f49 --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/utils/DelayedQueue.java @@ -0,0 +1,79 @@ +package com.bwie.auth.utils; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.CustomExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * 发送延迟队列的工具类 + */ +@Component +public class DelayedQueue { + + // routingKey + private static final String DELAYED_ROUTING_KEY = "delayed.routingkey"; + + // 延迟队列交换机 + private static final String DELAYED_EXCHANGE = "delayed.exchange"; + + @Autowired + RabbitTemplate rabbitTemplate; + + @Resource + RabbitAdmin rabbitAdmin; + + /** + * 发送延迟队列 + * + * @param queueName 队列名称 + * @param params 消息内容 + * @param expiration 延迟时间 毫秒 + */ + public void sendDelayedQueue(String queueName, Object params, Integer expiration) { + // 先创建一个队列 + Queue queue = new Queue(queueName); + rabbitAdmin.declareQueue(queue); + + // 创建延迟队列交换机 + CustomExchange customExchange = createCustomExchange(); + rabbitAdmin.declareExchange(customExchange); + + // 将队列和交换机绑定 + Binding binding = BindingBuilder.bind(queue).to(customExchange).with(DELAYED_ROUTING_KEY).noargs(); + rabbitAdmin.declareBinding(binding); + + // 发送延迟消息 + rabbitTemplate.convertAndSend(DELAYED_EXCHANGE, DELAYED_ROUTING_KEY, params, msg -> { + // 发送消息的时候 延迟时长 + msg.getMessageProperties().setMessageId(UUID.randomUUID().toString().replaceAll("-", "")); + msg.getMessageProperties().setDelay(expiration); + return msg; + }); + } + + private CustomExchange createCustomExchange() { + Map arguments = new HashMap<>(); + /** + * 参数说明: + * 1.交换机的名称 + * 2.交换机的类型 + * 3.是否需要持久化 + * 4.是否自动删除 + * 5.其它参数 + */ + arguments.put("x-delayed-type", "direct"); + return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, arguments); + } + +} + diff --git a/bwie-auth/src/main/java/com/bwie/auth/utils/TtlQueue.java b/bwie-auth/src/main/java/com/bwie/auth/utils/TtlQueue.java new file mode 100644 index 0000000..51db22d --- /dev/null +++ b/bwie-auth/src/main/java/com/bwie/auth/utils/TtlQueue.java @@ -0,0 +1,66 @@ +package com.bwie.auth.utils; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; + +/** + * 发送TTL队列 设置 消息的存活时间 如果超过了存活时间 + * 该条消息还没有被消费 则自动从队列中消息 ,如果配置了死信队列则消息会进入死信队列 + */ +@Component +public class TtlQueue { + // routingKey + private static final String TTL_KEY = "ttl.routingkey"; + private static final String TTL_EXCHANGE = "ttl.exchange"; + + @Autowired + RabbitTemplate rabbitTemplate; + + @Resource + RabbitAdmin rabbitAdmin; + + /** + * 发送TTL队列 + * + * @param queueName 队列名称 + * @param params 消息内容 + * @param expiration 过期时间 毫秒 + */ + public void sendTtlQueue(String queueName, Object params, Integer expiration) { + /** + * ----------------------------------先创建一个ttl队列-------------------------------------------- + */ + Map map = new HashMap<>(); + // 队列设置存活时间,单位ms,必须是整形数据。 + map.put("x-message-ttl", expiration); + /*参数1:队列名称 参数2:持久化 参数3:是否排他 参数4:自动删除队列 参数5:队列参数*/ + Queue queue = new Queue(queueName, true, false, false, map); + rabbitAdmin.declareQueue(queue); + + /** + * ---------------------------------创建交换机--------------------------------------------- + */ + DirectExchange directExchange = new DirectExchange(TTL_EXCHANGE, true, false); + rabbitAdmin.declareExchange(directExchange); + /** + * ---------------------------------队列绑定交换机--------------------------------------------- + */ + // 将队列和交换机绑定 + Binding binding = BindingBuilder.bind(queue).to(directExchange).with(TTL_KEY); + rabbitAdmin.declareBinding(binding); + + // 发送消息 + rabbitTemplate.convertAndSend(TTL_EXCHANGE, TTL_KEY, params); + } +} + diff --git a/bwie-auth/src/main/resources/bootstrap.yml b/bwie-auth/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..47dd1cf --- /dev/null +++ b/bwie-auth/src/main/resources/bootstrap.yml @@ -0,0 +1,40 @@ +# Tomcat +server: + port: 9001 +# Spring +spring: + main: + allow-circular-references: true + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + application: + # 应用名称 + name: bwie-auth + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 150.158.3.45:8848 + config: + # 配置中心地址 + server-addr: 150.158.3.45:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + rabbitmq: + username: guest + password: guest + virtualHost: / + port: 5672 + host: 150.158.3.45 + listener: + simple: + prefetch: 1 # 每次只能获取一条,处理完成才能获取下一条 + publisher-confirm-type: correlated #确认消息已发送到交换机(Exchange) + publisher-returns: true #确认消息已发送到队列(Queue) diff --git a/bwie-common/.gitignore b/bwie-common/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-common/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-common/pom.xml b/bwie-common/pom.xml new file mode 100644 index 0000000..9cccb29 --- /dev/null +++ b/bwie-common/pom.xml @@ -0,0 +1,156 @@ + + + 4.0.0 + + com.bwie + tenement + 1.0-SNAPSHOT + + + bwie-common + + + + + + + javax.servlet + javax.servlet-api + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + com.alibaba + fastjson + 1.2.80 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.apache.commons + commons-lang3 + + + + org.projectlombok + lombok + + + + + cn.hutool + hutool-all + 5.8.3 + + + + + com.aliyun + dysmsapi20170525 + 2.0.1 + + + + org.springframework.boot + spring-boot-starter-amqp + + + + + com.aliyun.oss + aliyun-sdk-oss + 3.12.0 + + + + + + org.springframework.boot + spring-boot-starter-mail + + + + + com.alibaba + fastjson + 1.2.15 + + + + org.apache.httpcomponents + httpclient + 4.2.1 + + + + org.apache.httpcomponents + httpcore + 4.2.1 + + + + commons-lang + commons-lang + 2.6 + + + + org.eclipse.jetty + jetty-util + 9.3.7.v20160115 + + + + + + + + + + + diff --git a/bwie-common/src/main/java/com/bwie/common/Exception/ServiceException.java b/bwie-common/src/main/java/com/bwie/common/Exception/ServiceException.java new file mode 100644 index 0000000..6847f92 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/Exception/ServiceException.java @@ -0,0 +1,67 @@ +package com.bwie.common.Exception; + +/** + * @ClassName: + * @Description: 业务异常 + * @Author: zhuwenqiang + * @Date: 2023/11/28 + */ +public class ServiceException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + private Integer code; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + *

+ */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public ServiceException() { + } + + public ServiceException(String message) { + this.message = message; + } + + public ServiceException(String message, Integer code) { + this.message = message; + this.code = code; + } + + public String getDetailMessage() { + return detailMessage; + } + + public ServiceException setDetailMessage(String detailMessage) { + this.detailMessage = detailMessage; + return this; + } + + @Override + public String getMessage() { + return message; + } + + public ServiceException setMessage(String message) { + this.message = message; + return this; + } + + public Integer getCode() { + return code; + } + +} diff --git a/bwie-common/src/main/java/com/bwie/common/constants/Constants.java b/bwie-common/src/main/java/com/bwie/common/constants/Constants.java new file mode 100644 index 0000000..2fdc9fe --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/constants/Constants.java @@ -0,0 +1,18 @@ +package com.bwie.common.constants; + +/** + * @description: 系统常量 + * @author DongZl + */ +public class Constants { + /** + * 成功标记 + */ + public static final Integer SUCCESS = 200; + public static final String SUCCESS_MSG = "操作成功"; + /** + * 失败标记 + */ + public static final Integer ERROR = 500; + public static final String ERROR_MSG = "操作异常"; +} diff --git a/bwie-common/src/main/java/com/bwie/common/constants/JwtConstants.java b/bwie-common/src/main/java/com/bwie/common/constants/JwtConstants.java new file mode 100644 index 0000000..03692c1 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/constants/JwtConstants.java @@ -0,0 +1,29 @@ +package com.bwie.common.constants; + +/** + * @author DongZl + * @description: Jwt常量 + */ +public class JwtConstants { + + /** + * 用户ID字段 + */ + public static final String DETAILS_USER_ID = "user_id"; + + /** + * 用户名字段 + */ + public static final String DETAILS_USERNAME = "username"; + + /** + * 用户标识 + */ + public static final String USER_KEY = "user_key"; + + /** + * 令牌秘钥 + */ + public final static String SECRET = "abcdefghijklmnopqrstuvwxyz"; + +} diff --git a/bwie-common/src/main/java/com/bwie/common/constants/MQQueueNameConstants.java b/bwie-common/src/main/java/com/bwie/common/constants/MQQueueNameConstants.java new file mode 100644 index 0000000..4262fb7 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/constants/MQQueueNameConstants.java @@ -0,0 +1,27 @@ +package com.bwie.common.constants; + +/** + * @ClassName: + * @Description: + * @Author: zhuwenqiang + * @Date: 2023/10/25 + */ +public class MQQueueNameConstants { + + /** + * 登录日志队列名称 + */ + public static final String LOGIN_LOG_QUEUE_NAME = "login_log_queue_name"; + + /** + * 添加 + */ + public static final String ADD_GOODS_ES_QUEUE_NAME = "add_goods_es_queue_name"; + + + /** + * 统计网站每日访问人次 + */ + public static final String WEBSITE_STATS_QUEUE = "website_stats_queue"; + +} diff --git a/bwie-common/src/main/java/com/bwie/common/constants/QueueConstants.java b/bwie-common/src/main/java/com/bwie/common/constants/QueueConstants.java new file mode 100644 index 0000000..1e38a29 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/constants/QueueConstants.java @@ -0,0 +1,10 @@ +package com.bwie.common.constants; + + +public class QueueConstants { + + public static final String SEND_CODE_QUEUE = "send_code_queue"; + public static final String SEND_CODE_PREVENT_REPEAT_ID = "send_code_prevent_repeat_id:"; + public static final String BLOG_UPDATE_QUEUE = "blog_update_queue"; + public static final String BLOG_UPDATE_PREVENT_REPEAT_ID = "blog_update_prevent_repeat_id:"; +} diff --git a/bwie-common/src/main/java/com/bwie/common/constants/RabbitMQConstants.java b/bwie-common/src/main/java/com/bwie/common/constants/RabbitMQConstants.java new file mode 100644 index 0000000..a99a980 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/constants/RabbitMQConstants.java @@ -0,0 +1,11 @@ +package com.bwie.common.constants; + +/** + * @BelongsProject: Bob_Up_Like_A_Cork + * @BelongsPackage: com.bwie.common.constants + * @Author: zhangquan + * @CreateTime: 2023/8/1 20:11 + */ +public class RabbitMQConstants { + public static final String SEND_CODE="send_code"; +} diff --git a/bwie-common/src/main/java/com/bwie/common/constants/TokenConstants.java b/bwie-common/src/main/java/com/bwie/common/constants/TokenConstants.java new file mode 100644 index 0000000..1871fb7 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/constants/TokenConstants.java @@ -0,0 +1,24 @@ +package com.bwie.common.constants; + +/** + * @author DongZl + * @description: 令牌常量 + */ +public class TokenConstants { + /** + * 缓存有效期,默认720(分钟) + */ + public final static long EXPIRATION = 720; + /** + * 缓存刷新时间,默认120(分钟) + */ + public final static long REFRESH_TIME = 120; + /** + * 权限缓存前缀 + */ + public final static String LOGIN_TOKEN_KEY = "login_tokens:"; + /** + * token标识 + */ + public static final String TOKEN = "token"; +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/Out.java b/bwie-common/src/main/java/com/bwie/common/domain/Out.java new file mode 100644 index 0000000..654b83d --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/Out.java @@ -0,0 +1,21 @@ +package com.bwie.common.domain; + +import lombok.Data; + +/** + * @ClassName Out + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 12:57 + */ +@Data +public class Out { + + private Integer outId; + private String outType; + + + + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/Rentahouse.java b/bwie-common/src/main/java/com/bwie/common/domain/Rentahouse.java new file mode 100644 index 0000000..a7f6acf --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/Rentahouse.java @@ -0,0 +1,31 @@ +package com.bwie.common.domain; + +import lombok.Data; + +import java.util.Date; + +/** + * @ClassName Rentahouse + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 17:47 + */ +@Data +public class Rentahouse { + + private Integer id; + private String name; + private Date applicationTime; + private String sex; + private Integer age; + private String selectedHouse; + private Integer rentalType; + private String housingType; + private Integer loanAmount; + private Integer examineAndApprove; + private String remark; + + private String rentalTypes; + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/Renthouse.java b/bwie-common/src/main/java/com/bwie/common/domain/Renthouse.java new file mode 100644 index 0000000..ba9b515 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/Renthouse.java @@ -0,0 +1,31 @@ +package com.bwie.common.domain; + +import lombok.Data; + +/** + * @ClassName Renthouse + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 14:50 + */ +@Data +public class Renthouse { + + private Integer renthouseId; + private Integer signaboutId; + private Integer actualPrice; + private Integer discountPrice; + + + private Integer tenenmentId; + + private String tenementName; + private Integer outId; + private String area; + private String tenementPig; + private Integer monthRent; + private Integer tenementStatus; + + private String outType; + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/Signabout.java b/bwie-common/src/main/java/com/bwie/common/domain/Signabout.java new file mode 100644 index 0000000..afb52e6 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/Signabout.java @@ -0,0 +1,18 @@ +package com.bwie.common.domain; + +import lombok.Data; + +/** + * @ClassName Signabout + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 15:03 + */ +@Data +public class Signabout { + + private Integer signaboutId; + private Integer signaboutTime; + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/Tenement.java b/bwie-common/src/main/java/com/bwie/common/domain/Tenement.java new file mode 100644 index 0000000..3262024 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/Tenement.java @@ -0,0 +1,26 @@ +package com.bwie.common.domain; + +import lombok.Data; + +/** + * @ClassName Tenement + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:48 + */ +@Data +public class Tenement { + + private String tenementId; + private String tenementName; + private Integer outId; + private String area; + private String tenementPig; + private Integer monthRent; + private Integer tenementStatus; + + private String outType; + + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/User.java b/bwie-common/src/main/java/com/bwie/common/domain/User.java new file mode 100644 index 0000000..2123c44 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/User.java @@ -0,0 +1,25 @@ +package com.bwie.common.domain; + +import lombok.Data; + +import java.util.Date; + +/** + * @ClassName User + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:16 + */ +@Data +public class User { + private Integer id; + private String name; + private String num; + private String pwd; + private Integer roleId; + private String roleName; + + private Date getLoginDate; + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/dto/RentahouseDTO.java b/bwie-common/src/main/java/com/bwie/common/domain/dto/RentahouseDTO.java new file mode 100644 index 0000000..24b7c26 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/dto/RentahouseDTO.java @@ -0,0 +1,22 @@ +package com.bwie.common.domain.dto; + +import lombok.Data; + +/** + * @ClassName RentahouseDTO + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 17:53 + */ +@Data +public class RentahouseDTO { + + private String name; + + private Integer examineAndApprove; + + private Integer pageNum=1; + private Integer pageSize=3; + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/dto/TenementDTO.java b/bwie-common/src/main/java/com/bwie/common/domain/dto/TenementDTO.java new file mode 100644 index 0000000..e4c3e5c --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/dto/TenementDTO.java @@ -0,0 +1,32 @@ +package com.bwie.common.domain.dto; + +import lombok.Data; + +/** + * @ClassName TenementDTO + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:53 + */ +@Data +public class TenementDTO { + + //价格 + + private Integer monthRentStart; + private Integer monthRentEnd; + + //出租方式 + + private Integer outId; + + //房屋名称 + private String tenementName; + + + //分页 + private Integer pageNum=1; + private Integer pageSize=3; + + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/request/UserReq.java b/bwie-common/src/main/java/com/bwie/common/domain/request/UserReq.java new file mode 100644 index 0000000..f57b298 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/request/UserReq.java @@ -0,0 +1,17 @@ +package com.bwie.common.domain.request; + +import lombok.Data; + +/** + * @ClassName UserReq + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:23 + */ +@Data +public class UserReq { + + private String num; + private String pwd; + +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/response/JwtRes.java b/bwie-common/src/main/java/com/bwie/common/domain/response/JwtRes.java new file mode 100644 index 0000000..f85ff80 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/response/JwtRes.java @@ -0,0 +1,18 @@ +package com.bwie.common.domain.response; + +import lombok.Data; + +/** + * @ClassName JwtRes + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:23 + */ +@Data +public class JwtRes { + + + + private String token; + private String exTime; +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/vo/RentahouseVo.java b/bwie-common/src/main/java/com/bwie/common/domain/vo/RentahouseVo.java new file mode 100644 index 0000000..712664c --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/vo/RentahouseVo.java @@ -0,0 +1,33 @@ +package com.bwie.common.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @ClassName RentahouseVo + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 17:55 + */ +@Data +public class RentahouseVo { + + private Integer id; + private String name; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date applicationTime; + private String sex; + private Integer age; + private String selectedHouse; + private Integer rentalType; + private String housingType; + private Integer loanAmount; + private Integer examineAndApprove; + private String remark; + + private String rentalTypes; +} diff --git a/bwie-common/src/main/java/com/bwie/common/domain/vo/TenementVo.java b/bwie-common/src/main/java/com/bwie/common/domain/vo/TenementVo.java new file mode 100644 index 0000000..ed2242e --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/domain/vo/TenementVo.java @@ -0,0 +1,24 @@ +package com.bwie.common.domain.vo; + +import lombok.Data; + +/** + * @ClassName TenementVo + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:54 + */ +@Data +public class TenementVo { + + private String tenementId; + private String tenementName; + private Integer outId; + private String area; + private String tenementPig; + private Integer monthRent; + private Integer tenementStatus; + + private String outType; + +} diff --git a/bwie-common/src/main/java/com/bwie/common/handler/GlobalExceptionHandler.java b/bwie-common/src/main/java/com/bwie/common/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..249843d --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/handler/GlobalExceptionHandler.java @@ -0,0 +1,45 @@ +package com.bwie.common.handler; + +import com.bwie.common.Exception.ServiceException; + +import com.bwie.common.result.Result; +import lombok.extern.log4j.Log4j2; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; +import java.rmi.ServerException; + +/** + * @ClassName: + * @Description: 全局异常处理器 + * @Author: zhuwenqiang + * @Date: 2023/11/28 + */ +@RestControllerAdvice +@Log4j2 +public class GlobalExceptionHandler { + + /** + * 处理 业务异常 + * @return + */ + @ExceptionHandler(ServiceException.class) + public Result serviceExceptionHandler(ServiceException serviceException, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',业务处理失败'{}'", requestURI, serviceException.getMessage()); + return Result.error(Result.FAIL, serviceException.getMessage()); + } + +// +// /** +// * 处理 业务异常 +// * @return +// */ +// @ExceptionHandler(Exception.class) +// public Result exceptionHandler() { +// +// return Result.error(); +// } + +} diff --git a/bwie-common/src/main/java/com/bwie/common/result/PageResult.java b/bwie-common/src/main/java/com/bwie/common/result/PageResult.java new file mode 100644 index 0000000..85ecdda --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/result/PageResult.java @@ -0,0 +1,34 @@ +package com.bwie.common.result; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author DongZl + * @description: 列表返回结果集 + */ +@Data +public class PageResult implements Serializable { + /** + * 总条数 + */ + private long total; + /** + * 结果集合 + */ + private List list; + public PageResult() { + } + public PageResult(long total, List list) { + this.total = total; + this.list = list; + } + public static PageResult toPageResult(long total, List list){ + return new PageResult(total , list); + } + public static Result> toResult(long total, List list){ + return Result.success(PageResult.toPageResult(total,list)); + } +} diff --git a/bwie-common/src/main/java/com/bwie/common/result/Result.java b/bwie-common/src/main/java/com/bwie/common/result/Result.java new file mode 100644 index 0000000..30b1e73 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/result/Result.java @@ -0,0 +1,76 @@ +package com.bwie.common.result; + +import com.bwie.common.constants.Constants; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author DongZl + * @description: 响应信息主体 + */ +@Data +public class Result implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 成功 + */ + public static final int SUCCESS = Constants.SUCCESS; + /** + * 失败 + */ + public static final int FAIL = Constants.ERROR; + /** + * 返回状态码 + */ + private int code; + /** + * 响应信息 + */ + private String msg; + /** + * 响应数据 + */ + private T data; + + public static Result success() { + return restResult(null, SUCCESS, Constants.SUCCESS_MSG); + } + + public static Result success(T data) { + return restResult(data, SUCCESS, Constants.SUCCESS_MSG); + } + + public static Result success(T data, String msg) { + return restResult(data, SUCCESS, msg); + } + + public static Result error() { + return restResult(null, FAIL, Constants.ERROR_MSG); + } + + public static Result error(String msg) { + return restResult(null, FAIL, msg); + } + + public static Result error(T data) { + return restResult(data, FAIL, Constants.ERROR_MSG); + } + + public static Result error(T data, String msg) { + return restResult(data, FAIL, msg); + } + + public static Result error(int code, String msg) { + return restResult(null, code, msg); + } + + private static Result restResult(T data, int code, String msg) { + Result apiResult = new Result<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/HttpUtils.java b/bwie-common/src/main/java/com/bwie/common/utils/HttpUtils.java new file mode 100644 index 0000000..1c7e2f3 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/HttpUtils.java @@ -0,0 +1,310 @@ +package com.bwie.common.utils; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class HttpUtils { + /** + * get + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/IpUtils.java b/bwie-common/src/main/java/com/bwie/common/utils/IpUtils.java new file mode 100644 index 0000000..20c1405 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/IpUtils.java @@ -0,0 +1,312 @@ +package com.bwie.common.utils; + +import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * 获取IP方法 + * + * @author ruoyi + */ +public class IpUtils { + public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; + // 匹配 ip + public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")"; + public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))"; + // 匹配网段 + public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")"; + + /** + * 获取客户端IP + * + * @param request 请求对象 + * @return IP地址 + */ + public static String getIpAddr(HttpServletRequest request) { + if (request == null) { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param ip IP地址 + * @return 结果 + */ + public static boolean internalIp(String ip) { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param addr byte地址 + * @return 结果 + */ + private static boolean internalIp(byte[] addr) { + if (StringUtils.isNull(addr) || addr.length < 2) { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) { + case SECTION_1: + return true; + case SECTION_2: + if (b1 >= SECTION_3 && b1 <= SECTION_4) { + return true; + } + case SECTION_5: + switch (b1) { + case SECTION_6: + return true; + } + default: + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) { + if (text.length() == 0) { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try { + long l; + int i; + switch (elements.length) { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } catch (NumberFormatException e) { + return null; + } + return bytes; + } + + /** + * 获取IP地址 + * + * @return 本地IP地址 + */ + public static String getHostIp() { + try { + return InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + } + return "127.0.0.1"; + } + + /** + * 获取主机名 + * + * @return 本地主机名 + */ + public static String getHostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + } + return "未知"; + } + + /** + * 从多级反向代理中获得第一个非unknown IP地址 + * + * @param ip 获得的IP地址 + * @return 第一个非unknown IP地址 + */ + public static String getMultistageReverseProxyIp(String ip) { + // 多级反向代理检测 + if (ip != null && ip.indexOf(",") > 0) { + final String[] ips = ip.trim().split(","); + for (String subIp : ips) { + if (false == isUnknown(subIp)) { + ip = subIp; + break; + } + } + } + return StringUtils.substring(ip, 0, 255); + } + + /** + * 检测给定字符串是否为未知,多用于检测HTTP请求相关 + * + * @param checkString 被检测的字符串 + * @return 是否未知 + */ + public static boolean isUnknown(String checkString) { + return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); + } + + /** + * 是否为IP + */ + public static boolean isIP(String ip) { + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP); + } + + /** + * 是否为IP,或 *为间隔的通配符地址 + */ + public static boolean isIpWildCard(String ip) { + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD); + } + + /** + * 检测参数是否在ip通配符里 + */ + public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip) { + String[] s1 = ipWildCard.split("\\."); + String[] s2 = ip.split("\\."); + boolean isMatchedSeg = true; + for (int i = 0; i < s1.length && !s1[i].equals("*"); i++) { + if (!s1[i].equals(s2[i])) { + isMatchedSeg = false; + break; + } + } + return isMatchedSeg; + } + + /** + * 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串 + */ + public static boolean isIPSegment(String ipSeg) { + return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG); + } + + /** + * 判断ip是否在指定网段中 + */ + public static boolean ipIsInNetNoCheck(String iparea, String ip) { + int idx = iparea.indexOf('-'); + String[] sips = iparea.substring(0, idx).split("\\."); + String[] sipe = iparea.substring(idx + 1).split("\\."); + String[] sipt = ip.split("\\."); + long ips = 0L, ipe = 0L, ipt = 0L; + for (int i = 0; i < 4; ++i) { + ips = ips << 8 | Integer.parseInt(sips[i]); + ipe = ipe << 8 | Integer.parseInt(sipe[i]); + ipt = ipt << 8 | Integer.parseInt(sipt[i]); + } + if (ips > ipe) { + long t = ips; + ips = ipe; + ipe = t; + } + return ips <= ipt && ipt <= ipe; + } + + /** + * 校验ip是否符合过滤串规则 + * + * @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99` + * @param ip 校验IP地址 + * @return boolean 结果 + */ + public static boolean isMatchedIp(String filter, String ip) { + if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip)) { + return false; + } + String[] ips = filter.split(";"); + for (String iStr : ips) { + if (isIP(iStr) && iStr.equals(ip)) { + return true; + } else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip)) { + return true; + } else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip)) { + return true; + } + } + return false; + } +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/JwtUtils.java b/bwie-common/src/main/java/com/bwie/common/utils/JwtUtils.java new file mode 100644 index 0000000..f560aa9 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/JwtUtils.java @@ -0,0 +1,109 @@ +package com.bwie.common.utils; + +import com.bwie.common.constants.JwtConstants; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +import java.util.Map; + +/** + * @description: Jwt工具类 + * @author DongZl + */ +public class JwtUtils { + + /** + * 秘钥 + */ + public static String secret = JwtConstants.SECRET; + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + public static String createToken(Map claims){ + String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + public static Claims parseToken(String token){ + return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } + /** + * 根据令牌获取用户标识 + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserKey(String token){ + Claims claims = parseToken(token); + return getValue(claims, JwtConstants.USER_KEY); + } + /** + * 根据令牌获取用户标识 + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserKey(Claims claims){ + return getValue(claims, JwtConstants.USER_KEY); + } + /** + * 根据令牌获取用户ID + * + * @param token 令牌 + * @return 用户ID + */ + public static String getUserId(String token){ + Claims claims = parseToken(token); + return getValue(claims, JwtConstants.DETAILS_USER_ID); + } + /** + * 根据身份信息获取用户ID + * + * @param claims 身份信息 + * @return 用户ID + */ + public static String getUserId(Claims claims){ + return getValue(claims, JwtConstants.DETAILS_USER_ID); + } + /** + * 根据令牌获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public static String getUserName(String token){ + Claims claims = parseToken(token); + return getValue(claims, JwtConstants.DETAILS_USERNAME); + } + /** + * 根据身份信息获取用户名 + * + * @param claims 身份信息 + * @return 用户名 + */ + public static String getUserName(Claims claims){ + return getValue(claims, JwtConstants.DETAILS_USERNAME); + } + /** + * 根据身份信息获取键值 + * + * @param claims 身份信息 + * @param key 键 + * @return 值 + */ + public static String getValue(Claims claims, String key){ + Object obj = claims.get(key); + return obj == null ? "" : obj.toString(); + } +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/MsgUtil.java b/bwie-common/src/main/java/com/bwie/common/utils/MsgUtil.java new file mode 100644 index 0000000..7927992 --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/MsgUtil.java @@ -0,0 +1,66 @@ +package com.bwie.common.utils; + +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class MsgUtil { + //取code +// @Cacheable(key = "#phone",value = "bbb") +// public String getCacheCode(String phone){ +// +// return null; +// } +// +// //把当前注解的返回值装进去 //存code +// @CachePut(key = "#codeEntity.phone",value = "bbb") +// public String saveCacheCode(CodeEntity codeEntity){ +// +// return codeEntity.getCode(); +// } + + public String sendMsg(String phone,String code){ + String result = null; + String host = "https://gyytz.market.alicloudapi.com"; + String path = "/sms/smsSend"; + String method = "POST"; + String appcode = "e384ae674976450f90d65587e7cd7f87"; + Map headers = new HashMap(); + //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 + headers.put("Authorization", "APPCODE " + appcode); + Map querys = new HashMap(); + querys.put("mobile", phone); + querys.put("param", "**code**:"+code+",**minute**:5"); + + //smsSignId(短信前缀)和templateId(短信模板),可登录国阳云控制台自助申请。参考文档:http://help.guoyangyun.com/Problem/Qm.html + + querys.put("smsSignId", "2e65b1bb3d054466b82f0c9d125465e2"); + querys.put("templateId", "908e94ccf08b4476ba6c876d13f084ad"); + Map bodys = new HashMap(); + + + try { + /** + * 重要提示如下: + * HttpUtils请从\r\n\t \t* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java\r\n\t \t* 下载 + * + * 相应的依赖请参照 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml + */ + HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys); +// System.out.println(response.toString()); + //获取response的body + result = EntityUtils.toString(response.getEntity()); + System.out.println(result); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/OssUtil.java b/bwie-common/src/main/java/com/bwie/common/utils/OssUtil.java new file mode 100644 index 0000000..c045b5a --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/OssUtil.java @@ -0,0 +1,153 @@ +package com.bwie.common.utils; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.model.GetObjectRequest; +import com.aliyun.oss.model.PutObjectRequest; +import lombok.extern.log4j.Log4j2; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.time.LocalDateTime; +import java.util.UUID; + +/** + * Oss服务调用 + */ +@Log4j2 +public class OssUtil { + + /** + * Endpoint 存储对象概述 阿里云主账号AccessKey,accessKeySecret拥有所有API的访问权限 访问路径前缀 存储对象概述 + */ + private static String endPoint = "oss-cn-shanghai.aliyuncs.com"; + private static String accessKeyId = "LTAI5t7q5mELDW6mXhTZ7zcQ"; + private static String accessKeySecret = "xYAfqdnsSAG2zdBJtptTgYCWKhmWw9"; + private static String accessPre = "https://mall-bw.oss-cn-shanghai.aliyuncs.com/"; + + /** + * bucket名称 + * @return + */ + private static String bucketName = "mall-bw"; + + private static OSS ossClient ; + + static { + ossClient = new OSSClientBuilder().build( + endPoint, + accessKeyId, + accessKeySecret); + log.info("oss服务连接成功!"); + } + + /** + * 默认路径上传本地文件 + * @param filePath + */ + public static String uploadFile(String filePath){ + return uploadFileForBucket(bucketName,getOssFilePath(filePath) ,filePath); + } + + /** + * 默认路径上传multipartFile文件 + * @param multipartFile + */ + public static String uploadMultipartFile(MultipartFile multipartFile) { + return uploadMultipartFile(bucketName, getOssFilePath(multipartFile.getOriginalFilename()), multipartFile); + } + /** + * 上传 multipartFile 类型文件 + * @param bucketName + * @param ossPath + * @param multipartFile + */ + public static String uploadMultipartFile(String bucketName , String ossPath , MultipartFile multipartFile){ + InputStream inputStream = null; + try { + inputStream = multipartFile.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + uploadFileInputStreamForBucket(bucketName, ossPath, inputStream); + return accessPre+ossPath; + } + + /** + * 使用File上传PutObject上传文件 ** 程序默认使用次方法上传 + * @param bucketName 实例名称 + * @param ossPath oss存储路径 + * @param filePath 本地文件路径 + */ + public static String uploadFileForBucket(String bucketName , String ossPath , String filePath) { + // 创建PutObjectRequest对象。 + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossPath, new File(filePath)); + + // 上传 + ossClient.putObject(putObjectRequest); + return accessPre+ossPath; + } + + /** + * 使用文件流上传到指定的bucket实例 + * @param bucketName 实例名称 + * @param ossPath oss存储路径 + * @param filePath 本地文件路径 + */ + public static String uploadFileInputStreamForBucket(String bucketName , String ossPath , String filePath){ + + // 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。 + InputStream inputStream = null; + try { + inputStream = new FileInputStream(filePath); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。 + uploadFileInputStreamForBucket(bucketName, ossPath, inputStream); + return accessPre+ossPath; + } + + public static void uploadFileInputStreamForBucket(String bucketName , String ossPath , InputStream inputStream ){ + ossClient.putObject(bucketName, ossPath, inputStream); + } + + /** + * 下载 + * @param ossFilePath + * @param filePath + */ + public static void downloadFile(String ossFilePath , String filePath ){ + downloadFileForBucket(bucketName , ossFilePath , filePath); + } + /** + * 下载 + * @param bucketName 实例名称 + * @param ossFilePath oss存储路径 + * @param filePath 本地文件路径 + */ + public static void downloadFileForBucket(String bucketName , String ossFilePath , String filePath ){ + ossClient.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(filePath)); + } + + /** + * + * @return + */ + public static String getOssDefaultPath(){ + LocalDateTime now = LocalDateTime.now(); + String url = + now.getYear()+"/"+ + now.getMonth()+"/"+ + now.getDayOfMonth()+"/"+ + now.getHour()+"/"+ + now.getMinute()+"/"; + return url; + } + + public static String getOssFilePath(String filePath){ + String fileSuf = filePath.substring(filePath.indexOf(".") + 1); + return getOssDefaultPath() + UUID.randomUUID().toString() + "." + fileSuf; + } + +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/StringUtils.java b/bwie-common/src/main/java/com/bwie/common/utils/StringUtils.java new file mode 100644 index 0000000..93c47fd --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/StringUtils.java @@ -0,0 +1,68 @@ +package com.bwie.common.utils; + +import org.springframework.util.AntPathMatcher; + +import java.util.Collection; +import java.util.List; + +/** + * @author DongZl + * @description: 字符串处理工具类 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) { + return object == null; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) { + return isNull(coll) || coll.isEmpty(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) { + if (isEmpty(str) || isEmpty(strs)) { + return false; + } + for (String pattern : strs) { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } +} diff --git a/bwie-common/src/main/java/com/bwie/common/utils/TelSmsUtils.java b/bwie-common/src/main/java/com/bwie/common/utils/TelSmsUtils.java new file mode 100644 index 0000000..e913e1b --- /dev/null +++ b/bwie-common/src/main/java/com/bwie/common/utils/TelSmsUtils.java @@ -0,0 +1,88 @@ +package com.bwie.common.utils; + +import com.alibaba.fastjson.JSONObject; +import com.aliyun.dysmsapi20170525.Client; +import com.aliyun.dysmsapi20170525.models.SendSmsRequest; +import com.aliyun.dysmsapi20170525.models.SendSmsResponse; +import com.aliyun.teaopenapi.models.Config; +import lombok.extern.log4j.Log4j2; + +import java.util.Map; + +/** + * 短信工具类 + */ +@Log4j2 +public class TelSmsUtils { + + /** + * 阿里云主账号AccessKey,accessKeySecret拥有所有API的访问权限 + */ + private static String accessKeyId = "LTAI5tMRrNoxsBPgb6bYZWTW"; + private static String accessKeySecret = "r9LXZtt3ewEG2DHQ6DbAc65F0AFRA7"; + private static String templateCode = "SMS0001"; + + /** + * 短信访问域名 + */ + private static String endpoint = "dysmsapi.aliyuncs.com"; + /** + * 短信签名 + */ + private static String signName = "登录验证"; + + /** + * 实例化短信对象 + */ + private static Client client; + + static { + log.info("初始化短信服务开始"); + long startTime = System.currentTimeMillis(); + try { + client = initClient(); + log.info("初始化短信成功:{}",signName); + } catch (Exception e) { + e.printStackTrace(); + } + log.info("初始化短信服务结束:耗时:{}MS",(System.currentTimeMillis()-startTime)); + } + /** + * 初始化短信对象 + * @return + * @throws Exception + */ + private static Client initClient() throws Exception{ + Config config = new Config() + // 您的AccessKey ID + .setAccessKeyId(accessKeyId) + // 您的AccessKey Secret + .setAccessKeySecret(accessKeySecret); + // 访问的域名 + config.endpoint = endpoint; + return new Client(config); + } + + /** + * 发送单条短信 + * @param tel + * @param + * @param sendDataMap + */ + public static String sendSms(String tel, Map sendDataMap){ + SendSmsRequest sendSmsRequest = new SendSmsRequest() + .setPhoneNumbers(tel) + .setSignName(signName) + .setTemplateCode(templateCode) + .setTemplateParam(JSONObject.toJSONString(sendDataMap)); + SendSmsResponse sendSmsResponse = null; + try { + log.info("发送短信验证码:消息内容是:【{}】", JSONObject.toJSONString(sendDataMap)); + sendSmsResponse = client.sendSms(sendSmsRequest); + } catch (Exception e) { + log.error("短信发送异常,手机号:【{}】,短信内容:【{}】,异常信息:【{}】", tel, sendDataMap, e); + } + return JSONObject.toJSONString(sendSmsResponse.getBody()); + } + +} diff --git a/bwie-common/src/main/resources/META-INF/spring.factories b/bwie-common/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..b0bd9bd --- /dev/null +++ b/bwie-common/src/main/resources/META-INF/spring.factories @@ -0,0 +1,5 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.bwie.common.Exception.ServiceException,\ + com.bwie.common.handler.GlobalExceptionHandler,\ + com.bwie.common.utils.MsgUtil + diff --git a/bwie-gateway/.gitignore b/bwie-gateway/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-gateway/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-gateway/pom.xml b/bwie-gateway/pom.xml new file mode 100644 index 0000000..dc783da --- /dev/null +++ b/bwie-gateway/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + com.bwie + tenement + 1.0-SNAPSHOT + + + bwie-gateway + + + + + com.bwie + bwie-common + + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + com.alibaba.cloud + spring-cloud-alibaba-sentinel-gateway + + + + com.alibaba.csp + sentinel-spring-cloud-gateway-adapter + + + + diff --git a/bwie-gateway/src/main/java/com/bwie/GateWayApplication.java b/bwie-gateway/src/main/java/com/bwie/GateWayApplication.java new file mode 100644 index 0000000..6f40c63 --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/GateWayApplication.java @@ -0,0 +1,17 @@ +package com.bwie; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @ClassName GateWayApplication + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:15 + */ +@SpringBootApplication +public class GateWayApplication { + public static void main(String[] args) { + SpringApplication.run(GateWayApplication.class); + } +} diff --git a/bwie-gateway/src/main/java/com/bwie/gateway/config/IgnoreWhiteConfig.java b/bwie-gateway/src/main/java/com/bwie/gateway/config/IgnoreWhiteConfig.java new file mode 100644 index 0000000..5705d6f --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/gateway/config/IgnoreWhiteConfig.java @@ -0,0 +1,32 @@ +package com.bwie.gateway.config; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * @description: 放行白名单配置 + * @author DongZl + */ +@Configuration +@RefreshScope +@ConfigurationProperties(prefix = "ignore") +@Data +@Log4j2 +public class IgnoreWhiteConfig { + /** + * 放行白名单配置,网关不校验此处的白名单 + */ + private List whites = new ArrayList<>(); + + public void setWhites(List whites) { + log.info("加载网关路径白名单:{}", JSONObject.toJSONString(whites)); + this.whites = whites; + } +} diff --git a/bwie-gateway/src/main/java/com/bwie/gateway/filters/AuthFilter.java b/bwie-gateway/src/main/java/com/bwie/gateway/filters/AuthFilter.java new file mode 100644 index 0000000..aebfd96 --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/gateway/filters/AuthFilter.java @@ -0,0 +1,105 @@ +package com.bwie.gateway.filters; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONObject; +import com.bwie.common.constants.TokenConstants; +import com.bwie.common.domain.User; +import com.bwie.common.utils.JwtUtils; +import com.bwie.common.utils.StringUtils; +import com.bwie.gateway.config.IgnoreWhiteConfig; +import com.bwie.gateway.utils.GatewayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @ClassName: + * @Description: 鉴权过滤器 + * @Author: zhuwenqiang + * @Date: 2023/8/18 + */ +@Component +public class AuthFilter implements GlobalFilter, Ordered { + + @Autowired + private IgnoreWhiteConfig ignoreWhiteConfig; + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 过滤方法 验证 token + * @param exchange 请求的上下文 通过这个参数 可以获取到 请求对象 以及 响应对象 + * @param chain 网关过滤器链 chain 放行 或者 拦截 + * @return Mono + */ + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // 验证当前的请求 是否需要拦截 【配置白名单请求 不拦截的请求 】 将白名单请求配置到配置文件中 + // 获取系统白名单请求 + List whites = ignoreWhiteConfig.getWhites(); + // 获取当前的请求 URI + ServerHttpRequest request = exchange.getRequest(); + String path = request.getURI().getPath(); + boolean matches = StringUtils.matches(path, whites); + if (matches) { // 放行 + return chain.filter(exchange); + } + // 获取token + String token = request.getHeaders().getFirst(TokenConstants.TOKEN); + // token 非空验证 + if (StringUtils.isEmpty(token)) { + // 不放行 提示错误信息 + return GatewayUtils.errorResponse(exchange, "token不能为空!", HttpStatus.UNAUTHORIZED); + } + try { + // token 合法性性 + JwtUtils.parseToken(token); + } catch (Exception ex) { + return GatewayUtils.errorResponse(exchange, "token格式错误!"); + } + // token 是否过期 + // 获取 UserKey + String userKey = JwtUtils.getUserKey(token); + if (!redisTemplate.hasKey(TokenConstants.LOGIN_TOKEN_KEY + userKey)) { + return GatewayUtils.errorResponse(exchange, "token过期!"); + } + + //续期 + // 从redis 取 + String userJson = redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey); + //反序列化 + User user = JSONObject.parseObject(userJson, User.class); + //获取用户登录时间 + Date loginDate = user.getGetLoginDate(); + + long between = DateUtil.between(loginDate, new Date(), DateUnit.MINUTE); + if (between<=15){ + redisTemplate.expire(TokenConstants.LOGIN_TOKEN_KEY+userKey,30, TimeUnit.MINUTES); + } + + // 放行 + return chain.filter(exchange); + } + + /** + * 当存在多个filter的时候 用来执行执行的优先级 + * @return 数字 数字的值越小 执行的优先级越高 + */ + @Override + public int getOrder() { + return 0; + } +} diff --git a/bwie-gateway/src/main/java/com/bwie/gateway/utils/GatewayUtils.java b/bwie-gateway/src/main/java/com/bwie/gateway/utils/GatewayUtils.java new file mode 100644 index 0000000..7b789e5 --- /dev/null +++ b/bwie-gateway/src/main/java/com/bwie/gateway/utils/GatewayUtils.java @@ -0,0 +1,98 @@ +package com.bwie.gateway.utils; + +import com.alibaba.fastjson.JSONObject; +import com.bwie.common.result.Result; +import com.bwie.common.utils.StringUtils; +import lombok.extern.log4j.Log4j2; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * @author DongZl + * @description: 网关处理工具类 + */ +@Log4j2 +public class GatewayUtils { + /** + * 添加请求头参数 + * @param mutate 修改对象 + * @param key 键 + * @param value 值 + */ + public static void addHeader(ServerHttpRequest.Builder mutate, String key, Object value) { + if (StringUtils.isEmpty(key)){ + log.warn("添加请求头参数键不可以为空"); + return; + } + if (value == null) { + log.warn("添加请求头参数:[{}]值为空",key); + return; + } + String valueStr = value.toString(); + mutate.header(key, valueStr); + log.info("添加请求头参数成功 - 键:[{}] , 值:[{}]", key , value); + } + + /** + * 删除请求头参数 + * @param mutate 修改对象 + * @param key 键 + */ + public static void removeHeader(ServerHttpRequest.Builder mutate, String key) { + if (StringUtils.isEmpty(key)){ + log.warn("删除请求头参数键不可以为空"); + return; + } + mutate.headers(httpHeaders -> httpHeaders.remove(key)).build(); + log.info("删除请求头参数 - 键:[{}]",key); + } + + /** + * 错误结果响应 + * @param exchange 响应上下文 + * @param msg 响应消息 + * @return + */ + public static Mono errorResponse(ServerWebExchange exchange, String msg, HttpStatus httpStatus) { + ServerHttpResponse response = exchange.getResponse(); + //设置HTTP响应头状态 + response.setStatusCode(httpStatus); + //设置HTTP响应头文本格式 + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json"); + //定义响应内容 + Result result = Result.error(msg); + String resultJson = JSONObject.toJSONString(result); + log.error("[鉴权异常处理]请求路径:[{}],异常信息:[{}],响应结果:[{}]", exchange.getRequest().getPath(), msg, resultJson); + DataBuffer dataBuffer = response.bufferFactory().wrap(resultJson.getBytes()); + //进行响应 + return response.writeWith(Mono.just(dataBuffer)); + } + + /** + * 错误结果响应 + * @param exchange 响应上下文 + * @param msg 响应消息 + * @return + */ + public static Mono errorResponse(ServerWebExchange exchange, String msg) { + ServerHttpResponse response = exchange.getResponse(); + //设置HTTP响应头状态 + response.setStatusCode(HttpStatus.OK); + //设置HTTP响应头文本格式 + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json"); + //定义响应内容 + Result result = Result.error(msg); + String resultJson = JSONObject.toJSONString(result); + log.error("[鉴权异常处理]请求路径:[{}],异常信息:[{}],响应结果:[{}]", exchange.getRequest().getPath(), msg, resultJson); + DataBuffer dataBuffer = response.bufferFactory().wrap(resultJson.getBytes()); + //进行响应 + return response.writeWith(Mono.just(dataBuffer)); + } + + +} diff --git a/bwie-gateway/src/main/resources/bootstrap.yml b/bwie-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..fae8b41 --- /dev/null +++ b/bwie-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,29 @@ +# Tomcat +server: + port: 18080 +# Spring +spring: + application: + # 应用名称 + name: bwie-gateway + profiles: + # 环境配置 + active: dev + main: + # 允许使用循环引用 + allow-circular-references: true + # 允许定义相同的bean对象 去覆盖原有的 + allow-bean-definition-overriding: true + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 150.158.3.45:8848 + config: + # 配置中心地址 + server-addr: 150.158.3.45:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/bwie-model/.gitignore b/bwie-model/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-model/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-model/bwei-tenement/.gitignore b/bwie-model/bwei-tenement/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-model/bwei-tenement/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-model/bwei-tenement/pom.xml b/bwie-model/bwei-tenement/pom.xml new file mode 100644 index 0000000..5dd0c9d --- /dev/null +++ b/bwie-model/bwei-tenement/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + com.bwie + bwie-model + 1.0-SNAPSHOT + + + bwei-tenement + + + + + com.bwie + bwie-common + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba + druid-spring-boot-starter + 1.2.8 + + + + mysql + mysql-connector-java + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.2 + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.1 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.github.tobato + fastdfs-client + 1.26.5 + + + + + + + diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/TenementApplication.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/TenementApplication.java new file mode 100644 index 0000000..23de5e7 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/TenementApplication.java @@ -0,0 +1,18 @@ +package com.bwie; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @ClassName TenementApplication + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 12:32 + */ +@SpringBootApplication +public class TenementApplication { + public static void main(String[] args) { + SpringApplication.run(TenementApplication.class); + } + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/ConfirmCallbackConfig.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/ConfirmCallbackConfig.java new file mode 100644 index 0000000..96a9737 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/ConfirmCallbackConfig.java @@ -0,0 +1,48 @@ +package com.bwie.tenement.config; + +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @ClassName: + * @Description: 消息发送到 broker的确认 重写 confirm 方法 + * @Author: zhuwenqiang + * @Date: 2023/10/23 + */ +@Component +public class ConfirmCallbackConfig implements RabbitTemplate.ConfirmCallback { + + @Autowired + private RabbitTemplate rabbitTemplate; + + /** + * 当前类被初始化的时候执行的方法 + * + */ + @PostConstruct + public void init() { + // 设置 rabbitTemplate 的消息发送到交换机确认 + rabbitTemplate.setConfirmCallback(this); + } + + /** + * 消息发送到交换机 无论成功或者失败 都会执行 + * + * @param correlationData correlation data for the callback. + * @param ack true for ack, false for nack true 成功 false 失败 + * @param cause An optional cause, for nack, when available, otherwise null. + */ + @Override + public void confirm(CorrelationData correlationData, boolean ack, String cause) { + if (ack) { + System.out.println("消息发送到broker成功!"); + } else { + System.out.println("消息发送到broker失败,失败的原因是:" + cause); + } + } + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/RabbitAdminConfig.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/RabbitAdminConfig.java new file mode 100644 index 0000000..faff505 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/RabbitAdminConfig.java @@ -0,0 +1,53 @@ +package com.bwie.tenement.config; + +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * RabbitAdmin是RabbitMQ的一个Java客户端库,它提供了管理RabbitMQ资源的功能。它是通过与RabbitMQ服务器进行交互来执行管理操作的。 + */ +@Configuration +public class RabbitAdminConfig { + + @Value("${spring.rabbitmq.host}") + private String host; + @Value("${spring.rabbitmq.username}") + private String username; + @Value("${spring.rabbitmq.password}") + private String password; + @Value("${spring.rabbitmq.virtualhost}") + private String virtualhost; + + /** + * 构建 RabbitMQ的连接工厂 + * @return + */ + @Bean + public ConnectionFactory connectionFactory() { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); + connectionFactory.setAddresses(host); + connectionFactory.setUsername(username); + connectionFactory.setPassword(password); + connectionFactory.setVirtualHost(virtualhost); + // 配置发送确认回调时,次配置必须配置,否则即使在RabbitTemplate配置了ConfirmCallback也不会生效 + connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED); + connectionFactory.setPublisherReturns(true); + return connectionFactory; + } + + /** + * 自己初始化 RabbitAdmin + * @param connectionFactory + * @return + */ + @Bean + public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); + rabbitAdmin.setAutoStartup(true); + return rabbitAdmin; + } +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/RabbitmqConfig.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/RabbitmqConfig.java new file mode 100644 index 0000000..7719451 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/RabbitmqConfig.java @@ -0,0 +1,16 @@ +package com.bwie.tenement.config; + +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitmqConfig { + // 消息转换配置 SimpleMessageConverter String byte[] serializable + @Bean + public MessageConverter jsonMessageConverter() { + return new Jackson2JsonMessageConverter(); + } + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/ReturnsCallbackConfig.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/ReturnsCallbackConfig.java new file mode 100644 index 0000000..024f46a --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/config/ReturnsCallbackConfig.java @@ -0,0 +1,40 @@ +package com.bwie.tenement.config; + +import org.springframework.amqp.core.ReturnedMessage; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @ClassName: + * @Description: 消息发送到队列的确认 + * @Author: zhuwenqiang + * @Date: 2023/10/23 + */ +@Component +public class ReturnsCallbackConfig implements RabbitTemplate.ReturnsCallback { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @PostConstruct + public void init() { + rabbitTemplate.setReturnsCallback(this); + } + + /** + * 只有发送到队列失败才会执行 + * + * @param returnedMessage the returned message and metadata. + */ + @Override + public void returnedMessage(ReturnedMessage returnedMessage) { + System.out.println("消息" + returnedMessage.getMessage().toString() + + "被交换机" + returnedMessage.getExchange() + "回退!" + + "退回原因为:" + returnedMessage.getReplyText()); + // TODO 补偿 可以再发 做日志记录 + } + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/controller/TenementController.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/controller/TenementController.java new file mode 100644 index 0000000..4d667e6 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/controller/TenementController.java @@ -0,0 +1,113 @@ +package com.bwie.tenement.controller; + +import com.bwie.common.domain.Out; +import com.bwie.common.domain.Renthouse; +import com.bwie.common.domain.Signabout; +import com.bwie.common.domain.dto.RentahouseDTO; +import com.bwie.common.domain.vo.RentahouseVo; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.PageResult; +import com.bwie.common.result.Result; +import com.bwie.common.utils.OssUtil; +import com.bwie.tenement.service.TenementService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * @ClassName TenementController + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:47 + */ +@RestController +public class TenementController { + + @Autowired + private TenementService service; + + @PostMapping("/findAll") + public Result> findAll (){ + + Result> result = service.findAll(); + + return result; + } + + + //出租方式i + @PostMapping("/findOut") + public Result>findOut(){ + + Result> result = service.findOut(); + + return result; + } + + //录入 + @PostMapping("/add") + public Result add(@RequestBody TenementVo vo){ + Result result = service.add(vo); + + return result; + } + + + @PostMapping("/ossPig") + public Result ossPig(@RequestParam("file") MultipartFile file) { + + String s = OssUtil.uploadMultipartFile(file); + + + return Result.success(s); + } + //租房 + @PostMapping("/toadd") + public Result toadd(@RequestBody Renthouse renthouse ){ + Result result = service.toadd(renthouse); + + return result; + } + + //合同 + @PostMapping("/findSignabout") + public Result>findSignabout(){ + + Result> result = service.findSignabout(); + + return result; + } + + @PostMapping("/findRe") + public Result>findRe(){ + + Result> result = service.findRe(); + + return result; + } + + + //审批列表 + + @PostMapping("/spList") + public Result> spList(@RequestBody RentahouseDTO dto){ + + Result> result = service.spList(dto); + + return result; + } + @PostMapping("/upd") + public Result upd (@RequestBody RentahouseVo vo){ + + Result result = service.upd(vo); + + return result; + } + + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/mapper/TenementMapper.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/mapper/TenementMapper.java new file mode 100644 index 0000000..9b9df27 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/mapper/TenementMapper.java @@ -0,0 +1,43 @@ +package com.bwie.tenement.mapper; + +import com.bwie.common.domain.Out; +import com.bwie.common.domain.Rentahouse; +import com.bwie.common.domain.Renthouse; +import com.bwie.common.domain.Signabout; +import com.bwie.common.domain.dto.RentahouseDTO; +import com.bwie.common.domain.vo.RentahouseVo; +import com.bwie.common.domain.vo.TenementVo; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * @ClassName TenementMapper + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:47 + */ +@Mapper +public interface TenementMapper { + List findAll(); + + List findOut(); + + int add(TenementVo vo); + + List findSignabout(); + + int toadd(Renthouse renthouse); + + Signabout findAllSignabout(); + + List findRe(); + + TenementVo finAllTen(); + + List spList(RentahouseDTO dto); + + int upd(RentahouseVo vo); + + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/mq/UpdConsumer.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/mq/UpdConsumer.java new file mode 100644 index 0000000..d15e770 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/mq/UpdConsumer.java @@ -0,0 +1,77 @@ +package com.bwie.tenement.mq; + +import com.bwie.common.domain.vo.RentahouseVo; +import com.bwie.common.result.Result; +import com.bwie.common.utils.MsgUtil; +import com.bwie.tenement.mapper.TenementMapper; +import com.rabbitmq.client.Channel; +import lombok.extern.log4j.Log4j2; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + + +import java.io.IOException; +import java.util.UUID; + +/** + * @ClassName UpdConsumer + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 18:53 + */ +@Component +@Log4j2 +public class UpdConsumer { + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private TenementMapper mapper; + + @Autowired + private MsgUtil msgUtil; + + + @RabbitListener(queuesToDeclare = {@Queue("upd")}) + public Result UpdConsumer (Message message, RentahouseVo vo, Channel channel){ + String messageId = message.getMessageProperties().getMessageId(); + + Long add = redisTemplate.opsForSet().add("upd", messageId); + + try { + if (add==1){ + + int i = mapper.upd(vo); + if (i>0){ + + String code= UUID.randomUUID().toString(); + + msgUtil.sendMsg("17669723291",code); + + return Result.success("更新成功"); + } + } + //手动确认 + channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); + } catch (IOException e) { + redisTemplate.opsForSet().remove("upd", messageId); + try { + channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + return Result.error("失败"); + } + + + + + +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/service/TenementService.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/service/TenementService.java new file mode 100644 index 0000000..0de5563 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/service/TenementService.java @@ -0,0 +1,37 @@ +package com.bwie.tenement.service; + +import com.bwie.common.domain.Out; +import com.bwie.common.domain.Renthouse; +import com.bwie.common.domain.Signabout; +import com.bwie.common.domain.dto.RentahouseDTO; +import com.bwie.common.domain.vo.RentahouseVo; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.PageResult; +import com.bwie.common.result.Result; + +import java.util.List; + +/** + * @ClassName TenementService + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:47 + */ + +public interface TenementService { + Result> findAll(); + + Result> findOut(); + + Result add(TenementVo vo); + + Result toadd(Renthouse renthouse); + + Result> findSignabout(); + + Result> findRe(); + + Result> spList(RentahouseDTO dto); + + Result upd(RentahouseVo vo); +} diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/service/impl/TenementServiceImpl.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/service/impl/TenementServiceImpl.java new file mode 100644 index 0000000..31ff36a --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/service/impl/TenementServiceImpl.java @@ -0,0 +1,155 @@ +package com.bwie.tenement.service.impl; + +import com.bwie.common.domain.Out; +import com.bwie.common.domain.Renthouse; +import com.bwie.common.domain.Signabout; +import com.bwie.common.domain.dto.RentahouseDTO; +import com.bwie.common.domain.vo.RentahouseVo; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.PageResult; +import com.bwie.common.result.Result; +import com.bwie.tenement.mapper.TenementMapper; +import com.bwie.tenement.service.TenementService; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +/** + * @ClassName TenementServiceImpl + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:47 + */ +@Service +public class TenementServiceImpl implements TenementService { + + + @Autowired + private TenementMapper mapper; + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Override + public Result> findAll() { + + List mapperAll = mapper.findAll(); + + + return Result.success(mapperAll); + } + + @Override + public Result> findOut() { + List mapperOut = mapper.findOut(); + + + return Result.success(mapperOut); + } + + @Override + public Result add(TenementVo vo) { + + int i = mapper.add(vo); + + if (i>0){ + return Result.success("录入成功"); + } + + return Result.error("录入失败"); + } + + @Override + @Transactional + public Result toadd(Renthouse renthouse) { + +// TenementVo tenementVo = mapper.finAllTen(); +// +// Signabout signabout = mapper.findAllSignabout(); +// //实际价格 +// renthouse.setActualPrice(tenementVo.getMonthRent()*signabout.getSignaboutTime()); +// +// +// if (signabout.getSignaboutTime() ==3 || signabout.getSignaboutTime() == 6 || signabout.getSignaboutTime()==12){ +// +// renthouse.setDiscountPrice((int) (renthouse.getActualPrice() * 0.95)); +// } +// if (signabout.getSignaboutTime() ==24 ){ +// +// renthouse.setDiscountPrice((int) (renthouse.getActualPrice() * 0.9)); +// } +// if (signabout.getSignaboutTime() ==36 ){ +// +// renthouse.setDiscountPrice((int) (renthouse.getActualPrice() * 8.5)); +// } + + int i = mapper.toadd(renthouse); + + if (i>0){ + + return Result.success("签约成功"); + } + + return Result.error("签约失败"); + } + + @Override + public Result> findSignabout() { + + + List mapperSignabout = mapper.findSignabout(); + +// Signabout signabout = new Signabout(); + + redisTemplate.opsForValue().set("合同",mapperSignabout+""); + + return Result.success(mapperSignabout); + } + + @Override + public Result> findRe() { + List mapperSignabout = mapper.findRe(); + return Result.success(mapperSignabout); + } + + @Override + public Result> spList(RentahouseDTO dto) { + + PageHelper.startPage(dto.getPageNum(), dto.getPageSize()); + + + List list = mapper.spList(dto); + + PageInfo info = new PageInfo<>(list); + + System.out.println(list); + + return PageResult.toResult(info.getTotal(), list); + } + + @Override + public Result upd(RentahouseVo vo) { + + rabbitTemplate.convertAndSend("upd",vo,message -> { + + message.getMessageProperties().setMessageId(UUID.randomUUID().toString()); + + return message; + }); + + + return Result.success(); + } +} + + diff --git a/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/util/FastUtil.java b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/util/FastUtil.java new file mode 100644 index 0000000..8ec774d --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/java/com/bwie/tenement/util/FastUtil.java @@ -0,0 +1,55 @@ +package com.bwie.tenement.util; + +import org.springframework.stereotype.Component; +import com.github.tobato.fastdfs.domain.fdfs.StorePath; +import com.github.tobato.fastdfs.service.FastFileStorageClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + +/** + * @BelongsProject: 0107day02 + * @BelongsPackage: com.bw.config + * @Author: zhupengfei + * @CreateTime: 2023-02-01 08:52 + */ +@Component +public class FastUtil { + private static final Logger log = LoggerFactory.getLogger(FastUtil.class); + + @Resource + private FastFileStorageClient storageClient ; + + /** + * 上传文件 + */ + public String upload(MultipartFile multipartFile) throws Exception{ + String originalFilename = multipartFile.getOriginalFilename(). + substring(multipartFile.getOriginalFilename(). + lastIndexOf(".") + 1); + StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage( + multipartFile.getInputStream(), + multipartFile.getSize(),originalFilename , null); + return storePath.getFullPath() ; + } + /** + * 删除文件 + */ + public String deleteFile(String fileUrl) { + if (StringUtils.isEmpty(fileUrl)) { + log.info("fileUrl == >>文件路径为空..."); + return "文件路径不能为空"; + } + try { + StorePath storePath = StorePath.parseFromUrl(fileUrl); + storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); + } catch (Exception e) { + log.error(e.getMessage()); + } + return "删除成功"; + } + +} diff --git a/bwie-model/bwei-tenement/src/main/resources/bootstrap.yml b/bwie-model/bwei-tenement/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..0feef57 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/resources/bootstrap.yml @@ -0,0 +1,58 @@ +# Tomcat +server: + port: 9004 +# Spring +spring: + main: + allow-circular-references: true + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + application: + # 应用名称 + name: bwei-tenement + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 150.158.3.45:8848 + config: + # 配置中心地址 + server-addr: 150.158.3.45:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + rabbitmq: + username: guest + password: guest + virtualHost: / + port: 5672 + host: 150.158.3.45 + listener: + simple: + prefetch: 1 # 每次只能获取一条,处理完成才能获取下一条 + publisher-confirm-type: correlated #确认消息已发送到交换机(Exchange) + publisher-returns: true #确认消息已发送到队列(Queue) + +fdfs: + so-timeout: 1500 # socket 连接时长 + connect-timeout: 600 # 连接 tracker 服务器超时时长 + # 这两个是你服务器的 IP 地址,注意 23000 端口也要打开,阿里云服务器记得配置安全组。tracker 要和 stroage 服务进行交流 + tracker-list: 150.158.3.45:22122 + web-server-url: 150.158.3.45:8888 + pool: + jmx-enabled: false + # 生成缩略图 + thumb-image: + height: 500 + width: 500 + + + + + diff --git a/bwie-model/bwei-tenement/src/main/resources/mapper/TenementMapper.xml b/bwie-model/bwei-tenement/src/main/resources/mapper/TenementMapper.xml new file mode 100644 index 0000000..6f52aa7 --- /dev/null +++ b/bwie-model/bwei-tenement/src/main/resources/mapper/TenementMapper.xml @@ -0,0 +1,82 @@ + + + + + INSERT INTO `t_tenement` + (`tenement_name`, + `out_id`, + `area`, + `tenement_pig`, + `month_rent`, + `tenement_status`) + VALUES + ( #{tenementName}, #{outId}, #{area}, #{tenementPig}, #{monthRent}, 0); + + + + + + + INSERT INTO `t_renthouse` + (`signabout_id`, + `actual_price`, + `discount_price`, + tenenment_id) + VALUES (#{signaboutId}, #{actualPrice}, #{discountPrice},#{tenenmentId}); + + + + UPDATE `t_rentahouse`SET examine_and_approve = 2 WHERE `id` = 3; + + + + + + + + + + + + + + + + diff --git a/bwie-model/bwie-es/.gitignore b/bwie-model/bwie-es/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-model/bwie-es/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-model/bwie-es/pom.xml b/bwie-model/bwie-es/pom.xml new file mode 100644 index 0000000..7e3d658 --- /dev/null +++ b/bwie-model/bwie-es/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + com.bwie + bwie-model + 1.0-SNAPSHOT + + + bwie-es + + + + com.bwie + bwie-common + + + org.springframework.boot + spring-boot-starter-web + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + + + + + + + + + + + + + + + + diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/EsApplication.java b/bwie-model/bwie-es/src/main/java/com/bwie/EsApplication.java new file mode 100644 index 0000000..8c892fb --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/EsApplication.java @@ -0,0 +1,21 @@ +package com.bwie; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + *@ClassName EsApplication + *@Description 描述 + *@Author Di.Wu + *@Date 2023/12/5 12:34 + */ +@SpringBootApplication +@EnableScheduling +@EnableFeignClients +public class EsApplication { + public static void main(String[] args) { + SpringApplication.run(EsApplication.class); + } +} diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/es/config/InitEsRes.java b/bwie-model/bwie-es/src/main/java/com/bwie/es/config/InitEsRes.java new file mode 100644 index 0000000..c94caa7 --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/es/config/InitEsRes.java @@ -0,0 +1,25 @@ +package com.bwie.es.config; + +import lombok.Data; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestHighLevelClient; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "es") +@Data +public class InitEsRes { + private String host; + private int port; + private String scheme; + + @Bean + public RestHighLevelClient restHighLevelClient(){ + return new RestHighLevelClient( + RestClient.builder(new HttpHost(host,port,scheme)) + ); + } +} diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/es/controller/EsController.java b/bwie-model/bwie-es/src/main/java/com/bwie/es/controller/EsController.java new file mode 100644 index 0000000..094339f --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/es/controller/EsController.java @@ -0,0 +1,35 @@ +package com.bwie.es.controller; + +import com.bwie.common.domain.dto.TenementDTO; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.PageResult; +import com.bwie.common.result.Result; +import com.bwie.es.service.EsShopService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * @ClassName EsController + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 11:11 + */ +@RestController +public class EsController { + + + @Autowired + private EsShopService service; + + @PostMapping("/list") + public Result> list(@RequestBody TenementDTO dto){ + + Result> result = service.list(dto); + + return result; + } + + +} diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/es/feign/EsFeignService.java b/bwie-model/bwie-es/src/main/java/com/bwie/es/feign/EsFeignService.java new file mode 100644 index 0000000..7c8bffe --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/es/feign/EsFeignService.java @@ -0,0 +1,20 @@ +package com.bwie.es.feign; + +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.Result; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.List; + +/** + * @ClassName EsFeignService + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:59 + */ +@FeignClient("bwei-tenement") +public interface EsFeignService { + @PostMapping("/findAll") + public Result> findAll (); +} diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/es/service/EsShopService.java b/bwie-model/bwie-es/src/main/java/com/bwie/es/service/EsShopService.java new file mode 100644 index 0000000..f5a6025 --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/es/service/EsShopService.java @@ -0,0 +1,20 @@ +package com.bwie.es.service; + +import com.bwie.common.domain.dto.TenementDTO; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.PageResult; +import com.bwie.common.result.Result; + +import java.util.List; + +/** + * @ClassName EsShopService + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:58 + */ +public interface EsShopService { + void insertBatch(List list); + + Result> list(TenementDTO dto); +} diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/es/service/impl/EsShopServiceImpl.java b/bwie-model/bwie-es/src/main/java/com/bwie/es/service/impl/EsShopServiceImpl.java new file mode 100644 index 0000000..44ca276 --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/es/service/impl/EsShopServiceImpl.java @@ -0,0 +1,166 @@ +package com.bwie.es.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.bwie.common.domain.dto.TenementDTO; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.PageResult; +import com.bwie.common.result.Result; +import com.bwie.common.utils.StringUtils; +import com.bwie.es.service.EsShopService; +import org.elasticsearch.action.bulk.BulkRequest; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.common.text.Text; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.SearchHits; +import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @ClassName EsShopServiceImpl + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 10:58 + */ +@Service +public class EsShopServiceImpl implements EsShopService{ + + public static final String INDEX_NAME="t_tenement"; + + @Autowired + private RestHighLevelClient restHighLevelClient; + + @Override + public void insertBatch(List list) { + + //1.2.2项目启动需要将房屋列表数据添加到ES索引库中, + // 考虑数据量大的情况,实现每2000条数据同步一次 + + try { + + int in =200; + for (int i = 0; i < list.size(); i+=200) { + list.subList(i, Math.min(i+200, list.size())); + + BulkRequest bulkRequest = new BulkRequest(); + + list.forEach(vo -> { + bulkRequest.add( + new IndexRequest(INDEX_NAME) + .id(vo.getTenementId()) + .source(JSONObject.toJSONString(vo), XContentType.JSON) + ); + }); + + restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); + + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public Result> list(TenementDTO dto) { + + long total=0; + + List list = new ArrayList<>(); + + try { + + SearchRequest searchRequest = new SearchRequest(INDEX_NAME); + + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + + //房屋名称 + if (!StringUtils.isAllBlank(dto.getTenementName())){ + boolQueryBuilder.must(QueryBuilders.fuzzyQuery("tenementName", dto.getTenementName())); + } + //租房类型 + if (dto.getOutId()!=null){ + boolQueryBuilder.must(QueryBuilders.matchQuery("outId", dto.getOutId())); + } + //价格 + if (dto.getMonthRentStart()!=null){ + boolQueryBuilder.must(QueryBuilders.rangeQuery("monthRent").gte(dto.getMonthRentStart())); + } + + if (dto.getMonthRentEnd()!=null){ + boolQueryBuilder.must(QueryBuilders.rangeQuery("monthRent").lte(dto.getMonthRentEnd())); + } + + searchSourceBuilder.query(boolQueryBuilder); + + searchSourceBuilder.from((dto.getPageNum()-1)*dto.getPageSize()); + searchSourceBuilder.size(dto.getPageSize()); + + //高亮 + searchSourceBuilder.highlighter + (new HighlightBuilder() + .field("tenementName") + .preTags("") + .postTags("")); + + searchRequest.source(searchSourceBuilder); + + + SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); + + + SearchHits hits = search.getHits(); + + total = hits.getTotalHits().value; + + SearchHit[] hits1 = hits.getHits(); + + for (SearchHit hit : hits1) { + + String sourceAsString = hit.getSourceAsString(); + TenementVo tenementVo = JSONObject.parseObject(sourceAsString, TenementVo.class); + + Map highlightFields = hit.getHighlightFields(); + if (highlightFields!=null&&highlightFields.size()>0){ + HighlightField highlightField = highlightFields.get("tenementName"); + if (highlightField!=null){ + + Text[] fragments = highlightField.getFragments(); + + StringBuilder sb = new StringBuilder(); + + for (Text fragment : fragments) { + sb.append(fragment); + } + tenementVo.setTenementName(sb.toString()); + } + } + tenementVo.setTenementId(hit.getId()); + list.add(tenementVo); + } + + + } catch (IOException e) { + throw new RuntimeException(e); + } + return PageResult.toResult(total,list); + } + + +} diff --git a/bwie-model/bwie-es/src/main/java/com/bwie/es/sync/SyncBlog2Es.java b/bwie-model/bwie-es/src/main/java/com/bwie/es/sync/SyncBlog2Es.java new file mode 100644 index 0000000..4ce5607 --- /dev/null +++ b/bwie-model/bwie-es/src/main/java/com/bwie/es/sync/SyncBlog2Es.java @@ -0,0 +1,40 @@ +package com.bwie.es.sync; + +import com.alibaba.fastjson.JSON; +import com.bwie.common.domain.vo.TenementVo; +import com.bwie.common.result.Result; +import com.bwie.es.feign.EsFeignService; +import com.bwie.es.service.EsShopService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.List; + + +@Component +@Log4j2 +public class SyncBlog2Es { + + @Autowired + private EsFeignService esFeignService; + @Autowired + private EsShopService esShopService; + + @Scheduled(cron = "*/30 * * * * ?") + public void SyncBlog2EsPerMinute(){ + log.info("定时器---->博客从mysql全量同步到es的定时器正在执行,开始查询数据库..."); + Result> result = esFeignService.findAll(); + List list = result.getData(); + log.info("定时器---->博客从mysql全量同步到es的定时器正在执行,mysql查询到的博客数据为:{},开始同步...", + JSON.toJSONString(list)); + try { + esShopService.insertBatch(list); + log.info("定时器---->博客从mysql全量同步到es的定时器正在执行,同步成功..."); + } catch (Exception exception) { + exception.printStackTrace(); + log.error("定时器---->博客从mysql全量同步到es的定时器正在执行,同步失败!"+exception.getMessage()); + } + } +} diff --git a/bwie-model/bwie-es/src/main/resources/bootstrap.yml b/bwie-model/bwie-es/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..935aced --- /dev/null +++ b/bwie-model/bwie-es/src/main/resources/bootstrap.yml @@ -0,0 +1,33 @@ +# Tomcat +server: + port: 9005 +# Spring +spring: + main: + allow-circular-references: true + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + application: + # 应用名称 + name: bwie-es + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 150.158.3.45:8848 + config: + # 配置中心地址 + server-addr: 150.158.3.45:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} +es: + host: 150.158.3.45 + port: 9200 + scheme: http diff --git a/bwie-model/bwie-user/.gitignore b/bwie-model/bwie-user/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/bwie-model/bwie-user/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bwie-model/bwie-user/pom.xml b/bwie-model/bwie-user/pom.xml new file mode 100644 index 0000000..efcdc8f --- /dev/null +++ b/bwie-model/bwie-user/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.bwie + bwie-model + 1.0-SNAPSHOT + + + bwie-user + + + + + com.bwie + bwie-common + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba + druid-spring-boot-starter + 1.2.8 + + + + mysql + mysql-connector-java + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.2 + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.1 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + diff --git a/bwie-model/bwie-user/src/main/java/com/bwie/UserApplication.java b/bwie-model/bwie-user/src/main/java/com/bwie/UserApplication.java new file mode 100644 index 0000000..a61fc36 --- /dev/null +++ b/bwie-model/bwie-user/src/main/java/com/bwie/UserApplication.java @@ -0,0 +1,17 @@ +package com.bwie; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @ClassName UserApplication + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:21 + */ +@SpringBootApplication +public class UserApplication { + public static void main(String[] args) { + SpringApplication.run(UserApplication.class); + } +} diff --git a/bwie-model/bwie-user/src/main/java/com/bwie/user/controller/UserController.java b/bwie-model/bwie-user/src/main/java/com/bwie/user/controller/UserController.java new file mode 100644 index 0000000..b075a2b --- /dev/null +++ b/bwie-model/bwie-user/src/main/java/com/bwie/user/controller/UserController.java @@ -0,0 +1,35 @@ +package com.bwie.user.controller; + +import com.bwie.common.domain.User; +import com.bwie.common.result.Result; +import com.bwie.user.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @ClassName UserController + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:17 + */ +@RestController +public class UserController { + + @Autowired + private UserService userService; + + + @PostMapping("/findByNum") + public Result findByNum(@RequestParam String num){ + + User user = userService.findByNum(num); + + return Result.success(user); + + } + + + +} diff --git a/bwie-model/bwie-user/src/main/java/com/bwie/user/mapper/UserMapper.java b/bwie-model/bwie-user/src/main/java/com/bwie/user/mapper/UserMapper.java new file mode 100644 index 0000000..8402485 --- /dev/null +++ b/bwie-model/bwie-user/src/main/java/com/bwie/user/mapper/UserMapper.java @@ -0,0 +1,15 @@ +package com.bwie.user.mapper; + +import com.bwie.common.domain.User; +import org.apache.ibatis.annotations.Mapper; + +/** + * @ClassName UserMapper + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:17 + */ +@Mapper +public interface UserMapper { + User findByNum(String num); +} diff --git a/bwie-model/bwie-user/src/main/java/com/bwie/user/service/UserService.java b/bwie-model/bwie-user/src/main/java/com/bwie/user/service/UserService.java new file mode 100644 index 0000000..5d12373 --- /dev/null +++ b/bwie-model/bwie-user/src/main/java/com/bwie/user/service/UserService.java @@ -0,0 +1,13 @@ +package com.bwie.user.service; + +import com.bwie.common.domain.User; + +/** + * @ClassName UserService + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:18 + */ +public interface UserService { + User findByNum(String num); +} diff --git a/bwie-model/bwie-user/src/main/java/com/bwie/user/service/impl/UserServiceImpl.java b/bwie-model/bwie-user/src/main/java/com/bwie/user/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..eb17fcc --- /dev/null +++ b/bwie-model/bwie-user/src/main/java/com/bwie/user/service/impl/UserServiceImpl.java @@ -0,0 +1,25 @@ +package com.bwie.user.service.impl; + +import com.bwie.common.domain.User; +import com.bwie.user.mapper.UserMapper; +import com.bwie.user.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @ClassName UserServiceImpl + * @Description 描述 + * @Author Di.Wu + * @Date 2023/12/5 9:18 + */ +@Service +public class UserServiceImpl implements UserService{ + + @Autowired + private UserMapper mapper; + + @Override + public User findByNum(String num) { + return mapper.findByNum(num); + } +} diff --git a/bwie-model/bwie-user/src/main/resources/bootstrap.yml b/bwie-model/bwie-user/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..fe15999 --- /dev/null +++ b/bwie-model/bwie-user/src/main/resources/bootstrap.yml @@ -0,0 +1,29 @@ +# Tomcat +server: + port: 9002 +# Spring +spring: + main: + allow-circular-references: true + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + application: + # 应用名称 + name: bwie-user + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 150.158.3.45:8848 + config: + # 配置中心地址 + server-addr: 150.158.3.45:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/bwie-model/bwie-user/src/main/resources/mapper/UserMapper.xml b/bwie-model/bwie-user/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..0b24613 --- /dev/null +++ b/bwie-model/bwie-user/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/bwie-model/pom.xml b/bwie-model/pom.xml new file mode 100644 index 0000000..df8cc8b --- /dev/null +++ b/bwie-model/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + com.bwie + tenement + 1.0-SNAPSHOT + + + bwie-model + pom + + bwie-user + bwie-es + bwei-tenement + + + + 8 + 8 + UTF-8 + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..53136d6 --- /dev/null +++ b/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + com.bwie + tenement + 1.0-SNAPSHOT + pom + + bwie-auth + bwie-common + bwie-gateway + bwie-model + + + + + + spring-boot-starter-parent + org.springframework.boot + 2.6.2 + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + 2021.0.0 + pom + import + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + 2021.1 + pom + import + + + + com.alibaba.nacos + nacos-client + 2.0.4 + + + + + com.bwie + bwie-common + 1.0-SNAPSHOT + + + + +