12 files modified
11 files added
| | |
| | | import org.springframework.boot.SpringApplication; |
| | | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | import org.springframework.web.socket.config.annotation.EnableWebSocket; |
| | | import springfox.documentation.swagger2.annotations.EnableSwagger2; |
| | | |
| | | /** |
| | |
| | | */ |
| | | @EnableScheduling |
| | | @EnableSwagger2 |
| | | @EnableWebSocket |
| | | @SpringBootApplication |
| | | @MapperScan("com.xcong.excoin.modules.*.dao") |
| | | @MapperScan({"com.xcong.excoin.modules.*.dao", "com.xcong.excoin.common.*.dao"}) |
| | | public class ExcoinApplication { |
| | | |
| | | public static void main(String[] args) { |
| | |
| | | |
| | | public static final BigDecimal DEFAULT_PRICE = BigDecimal.valueOf(1.28); |
| | | |
| | | public static final String DICTIONARY_TYPE_FISH = "FISH_TYPE"; |
| | | |
| | | public static final String CANNON_TYPE = "CANNON_TYPE"; |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.common.initialization; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.xcong.excoin.common.contants.AppContants; |
| | | import com.xcong.excoin.common.system.dao.DataDictionaryCustomDao; |
| | | import com.xcong.excoin.common.system.entity.DataDictionaryCustom; |
| | | import com.xcong.excoin.modules.fish.dao.CannonSettingDao; |
| | | import com.xcong.excoin.modules.fish.entity.CannonSetting; |
| | | import com.xcong.excoin.utils.RedisUtils; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Slf4j |
| | | @Component |
| | | public class InitJob { |
| | | |
| | | @Autowired |
| | | private RedisUtils redisUtils; |
| | | @Autowired |
| | | private DataDictionaryCustomDao dictionaryCustomDao; |
| | | @Autowired |
| | | private CannonSettingDao cannonSettingDao; |
| | | |
| | | @PostConstruct |
| | | public void init() { |
| | | log.info("####项目初始化数据####"); |
| | | |
| | | // 初始化鱼类数据到redis缓存 |
| | | List<DataDictionaryCustom> fishTypes = dictionaryCustomDao.selectDicByType(AppContants.DICTIONARY_TYPE_FISH); |
| | | if (CollUtil.isNotEmpty(fishTypes)) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | for (DataDictionaryCustom fishType : fishTypes) { |
| | | Integer cnt = StrUtil.isEmpty(fishType.getValue()) ? 0 : Integer.parseInt(fishType.getValue()); |
| | | map.put(fishType.getCode(), cnt); |
| | | |
| | | redisUtils.hmset(AppContants.DICTIONARY_TYPE_FISH, map); |
| | | } |
| | | } |
| | | |
| | | // 初始化大炮数据到redis缓存 |
| | | List<CannonSetting> settings = cannonSettingDao.selectByMap(null); |
| | | if (CollUtil.isNotEmpty(settings)) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | for (CannonSetting setting : settings) { |
| | | map.put(setting.getCode(), setting.getGoldConsume()); |
| | | |
| | | redisUtils.hmset(AppContants.CANNON_TYPE, map); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.common.system.dao; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.xcong.excoin.common.system.entity.DataDictionaryCustom; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | public interface DataDictionaryCustomDao extends BaseMapper<DataDictionaryCustom> { |
| | | |
| | | List<DataDictionaryCustom> selectDicByType(String type); |
| | | |
| | | DataDictionaryCustom selectDicDataByTypeAndCode(@Param("type") String type, @Param("code") String code); |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.common.system.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.xcong.excoin.common.system.base.BaseEntity; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-09-25 |
| | | **/ |
| | | @Data |
| | | @TableName("data_dictionary_custom") |
| | | public class DataDictionaryCustom extends BaseEntity { |
| | | |
| | | private String type; |
| | | |
| | | private String code; |
| | | |
| | | private String value; |
| | | |
| | | private String description; |
| | | } |
| | |
| | | public static final String ROUTING_KEY_USDT_ADDRESS = "routing_key_usdt_address"; |
| | | |
| | | |
| | | public static final String EXCHANGE_FISH_HIT = "EXCHANGE_FISH_HIT"; |
| | | |
| | | public static final String QUEUE_FISH_HIT = "QUEUE_FISH_HIT"; |
| | | |
| | | public static final String ROUTING_KEY_FISH_HIT = "ROUTING_KEY_FISH_HIT"; |
| | | |
| | | /** |
| | | * 撮合交易 |
| | | */ |
| | |
| | | } |
| | | |
| | | @Bean |
| | | public DirectExchange fishHitExchange() { |
| | | return new DirectExchange(EXCHANGE_FISH_HIT); |
| | | } |
| | | |
| | | |
| | | @Bean |
| | | public Queue fishHitQueue() { |
| | | return new Queue(QUEUE_FISH_HIT, true); |
| | | } |
| | | |
| | | @Bean |
| | | public Binding fishHitbinding() { |
| | | return BindingBuilder.bind(fishHitQueue()).to(fishHitExchange()).with(ROUTING_KEY_FISH_HIT); |
| | | } |
| | | |
| | | @Bean |
| | | public DirectExchange usdtAddressExchange() { |
| | | return new DirectExchange(EXCHANGE_USDT_ADDRESS); |
| | | } |
| | |
| | | package com.xcong.excoin.configurations; |
| | | |
| | | import com.xcong.excoin.websocket.handler.FishHitWebSocketHandler; |
| | | import com.xcong.excoin.websocket.handler.FishHitWebSocketHandshakeInterceptor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.web.socket.config.annotation.EnableWebSocket; |
| | | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; |
| | | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; |
| | | import org.springframework.web.socket.server.standard.ServerEndpointExporter; |
| | | |
| | | //@Configuration |
| | | public class WebSocketConfig { |
| | | @Slf4j |
| | | @Configuration |
| | | public class WebSocketConfig implements WebSocketConfigurer { |
| | | |
| | | @Autowired |
| | | private FishHitWebSocketHandler fishHitWebSocketHandler; |
| | | @Autowired |
| | | private FishHitWebSocketHandshakeInterceptor fishHitWebSocketHandshakeInterceptor; |
| | | |
| | | /** |
| | | * 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint |
| | | */ |
| | |
| | | public ServerEndpointExporter serverEndpointExporter() { |
| | | return new ServerEndpointExporter(); |
| | | } |
| | | |
| | | @Override |
| | | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { |
| | | registry.addHandler(fishHitWebSocketHandler, "websocket/fish/hit") |
| | | .setAllowedOrigins("*") |
| | | .addInterceptors(fishHitWebSocketHandshakeInterceptor); |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.configurations.interceptor; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.web.servlet.HandlerInterceptor; |
| | | import org.springframework.web.servlet.ModelAndView; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | @Slf4j |
| | | @Component |
| | | public class WebCommonInterceptor implements HandlerInterceptor { |
| | | |
| | | |
| | | private String getUrl(HttpServletRequest request) { |
| | | return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getRequestURI(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
| | | log.info("#Begin Request# - [{}]", getUrl(request)); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { |
| | | } |
| | | |
| | | @Override |
| | | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { |
| | | log.info("#End Request# - [{}]", getUrl(request)); |
| | | } |
| | | } |
| | |
| | | .antMatchers("/api/orderCoin/deal/list").permitAll()
|
| | | .antMatchers("/api/helpCenter/**").permitAll()
|
| | | .antMatchers("/trade/**").permitAll()
|
| | | .antMatchers("/websocket/**").permitAll()
|
| | | .anyRequest().authenticated()
|
| | | .and().apply(securityConfiguereAdapter());
|
| | | }
|
| | |
| | | @ApiOperation(value = "代币金币互转") |
| | | @PostMapping(value = "/coinGoldExchange") |
| | | public Result coinGoldExchange(@RequestBody @Valid CoinGoldExchangeDto coinGoldExchangeDto) { |
| | | log.info("请求coinGoldExchange方法"); |
| | | return memberCannonService.coinGoldExchange(coinGoldExchangeDto); |
| | | } |
| | | |
| | |
| | | int updateTotalBalanceAndAvailableBalance(@Param("id") Long id, @Param("availableBalance") BigDecimal availableBalance, @Param("totalBalance") BigDecimal totalBalance, @Param("frozenBalance") BigDecimal frozenBalance); |
| | | |
| | | GoldAccountVo selectAccountGoldVoByMemberId(Long memberId); |
| | | |
| | | MemberAccountGold selectByMemberIdForLock(@Param("memberId") Long memberId); |
| | | } |
| | |
| | | public class OwnCannonVo { |
| | | |
| | | private Long id; |
| | | private Long memberId; |
| | | @ApiModelProperty(value = "炮台图片")//炮台图片 |
| | | private String cannonImg; |
| | | @ApiModelProperty(value = "炮弹图片")//炮弹图片 |
| | | private String bulletImg; |
| | | @ApiModelProperty(value = "炮台UUID")//炮台UUID |
| | | private String cannonUuid; |
| | | @ApiModelProperty(value = "炮台名称")//炮台名称 |
| | | private String cannonName; |
| | | private String name; |
| | | @ApiModelProperty(value = "炮台编码")//炮台编码 |
| | | private String cannonCode; |
| | | private String code; |
| | | @ApiModelProperty(value = "炮台兑换价格")//炮台兑换价格 |
| | | private BigDecimal cannonPrice; |
| | | private BigDecimal exchangePrice; |
| | | @ApiModelProperty(value = "每发炮弹消耗金币数")//消耗金币 |
| | | private BigDecimal goldConsume; |
| | | @ApiModelProperty(value = "1:主动购买 2:系统赠送")//1:主动购买 2:系统赠送 |
| | | private Integer type; |
| | | |
| | | @ApiModelProperty(value = "是否拥有 1-是 2-否") |
| | | private int isHas; |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.rabbit.consumer; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xcong.excoin.configurations.RabbitMqConfig; |
| | | import com.xcong.excoin.modules.fish.dao.MemberAccountGoldDao; |
| | | import com.xcong.excoin.modules.fish.entity.MemberAccountGold; |
| | | import com.xcong.excoin.websocket.fish.model.MsgModel; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.amqp.rabbit.annotation.RabbitListener; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Slf4j |
| | | @Component |
| | | @ConditionalOnProperty(prefix = "app", name = "fish-hit", havingValue = "true") |
| | | public class FishHitConsumer { |
| | | |
| | | @Autowired |
| | | private MemberAccountGoldDao memberAccountGoldDao; |
| | | |
| | | @RabbitListener(queues = RabbitMqConfig.QUEUE_FISH_HIT) |
| | | public void fishHit(String content) { |
| | | log.info("收到打渔消息:{}", content); |
| | | MsgModel msg = JSONObject.parseObject(content, MsgModel.class); |
| | | |
| | | synchronized (this) { |
| | | MemberAccountGold accountGold = memberAccountGoldDao.selectByMemberIdForLock(msg.getMemberId()); |
| | | BigDecimal available = accountGold.getAvailableBalance(); |
| | | |
| | | BigDecimal gold = BigDecimal.valueOf(msg.getObtain()).subtract(msg.getConsume()); |
| | | |
| | | if (gold.compareTo(BigDecimal.ZERO) < 0 && gold.abs().compareTo(available) > 0) { |
| | | log.info("余额不足"); |
| | | return; |
| | | } |
| | | memberAccountGoldDao.updateTotalBalanceAndAvailableBalance(accountGold.getId(), gold, gold, BigDecimal.ZERO); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.rabbit.producer; |
| | | |
| | | import cn.hutool.core.util.IdUtil; |
| | | import com.xcong.excoin.configurations.RabbitMqConfig; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | 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; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Slf4j |
| | | @Component |
| | | public class FishHitProducer implements RabbitTemplate.ConfirmCallback { |
| | | |
| | | private RabbitTemplate rabbitTemplate; |
| | | |
| | | @Autowired |
| | | public FishHitProducer(RabbitTemplate rabbitTemplate) { |
| | | this.rabbitTemplate = rabbitTemplate; |
| | | rabbitTemplate.setConfirmCallback(this); |
| | | } |
| | | |
| | | public void sendFishHitMsg(String content) { |
| | | log.info("打渔发送消息:{}", content); |
| | | CorrelationData correlationData = new CorrelationData(IdUtil.simpleUUID()); |
| | | rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_FISH_HIT, RabbitMqConfig.ROUTING_KEY_FISH_HIT, content, correlationData); |
| | | } |
| | | |
| | | @Override |
| | | public void confirm(CorrelationData correlationData, boolean ack, String cause) { |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.websocket.fish; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xcong.excoin.common.contants.AppContants; |
| | | import com.xcong.excoin.modules.member.dao.MemberDao; |
| | | import com.xcong.excoin.rabbit.producer.FishHitProducer; |
| | | import com.xcong.excoin.utils.RedisUtils; |
| | | import com.xcong.excoin.websocket.fish.model.MsgModel; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.websocket.*; |
| | | import javax.websocket.server.ServerEndpoint; |
| | | import java.math.BigDecimal; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Slf4j |
| | | @Component |
| | | //@ServerEndpoint(value = "/websocket/fish/hit") |
| | | public class HitFishWebSocket { |
| | | |
| | | @Autowired |
| | | private RedisUtils redisUtils; |
| | | @Autowired |
| | | private FishHitProducer fishHitProducer; |
| | | |
| | | private final Map<Long, Session> MEMBER_SESSIONS = new ConcurrentHashMap<>(); |
| | | private final Map<String, Long> SID_MID = new ConcurrentHashMap<>(); |
| | | |
| | | @OnOpen |
| | | public void onOpen(Session session) { |
| | | } |
| | | |
| | | @OnClose |
| | | public void onClose(Session session) {} |
| | | |
| | | /** |
| | | * |
| | | * @param message { type : "hit", fortId : 1, fishType : "fish1" } |
| | | * |
| | | * @param session |
| | | */ |
| | | @OnMessage |
| | | public void onMessage(String message, Session session) { |
| | | JSONObject reqParam = JSONObject.parseObject(message); |
| | | if (!reqParam.containsKey("hit") && !reqParam.containsKey("login")) { |
| | | session.getAsyncRemote().sendText("{code:-1}"); |
| | | return; |
| | | } |
| | | |
| | | // 登录逻辑 |
| | | if (reqParam.containsKey("login")) { |
| | | String token = reqParam.getString("token"); |
| | | if (StrUtil.isBlank(token)) { |
| | | session.getAsyncRemote().sendText("{ code:-1, msg: \"token error\" }"); |
| | | return; |
| | | } |
| | | |
| | | String redisStr = AppContants.APP_LOGIN_PREFIX + token; |
| | | String memberStr = redisUtils.getString(redisStr); |
| | | if (StrUtil.isBlank(memberStr)) { |
| | | session.getAsyncRemote().sendText("{ code:-1, msg: \"Unauthorized\"}"); |
| | | return; |
| | | } |
| | | |
| | | JSONObject memberObject = JSONObject.parseObject(memberStr); |
| | | Long memberId = memberObject.getLong("memberId"); |
| | | MEMBER_SESSIONS.put(memberId, session); |
| | | SID_MID.put(session.getId(), memberId); |
| | | session.getAsyncRemote().sendText("{ code:0, msg: \"login succes\" }"); |
| | | return; |
| | | } |
| | | |
| | | // 打中鱼奖励金币 |
| | | int fishGold = 0; |
| | | String fishType = reqParam.getString("fishType"); |
| | | |
| | | // 如果请求参数中包含鱼类型,且类型不为空,则说明打中 |
| | | if (reqParam.containsKey("fishType") && StrUtil.isNotBlank(fishType)) { |
| | | Object fishTypeObj = redisUtils.hget(AppContants.DICTIONARY_TYPE_FISH, fishType); |
| | | if (fishTypeObj == null) { |
| | | session.getAsyncRemote().sendText("{code : -1, msg : \"fish error\"}"); |
| | | return; |
| | | } |
| | | |
| | | fishGold = (int) fishTypeObj; |
| | | } |
| | | |
| | | String fortId = reqParam.getString("fortId"); |
| | | if (!reqParam.containsKey("fortId") || fortId == null) { |
| | | return; |
| | | } |
| | | |
| | | Object fortObj = redisUtils.hget(AppContants.CANNON_TYPE, fortId); |
| | | if (fortObj == null) { |
| | | session.getAsyncRemote().sendText("{code : -1, msg : \"fort error\"}"); |
| | | return; |
| | | } |
| | | |
| | | // 消耗金币 |
| | | BigDecimal consume = (BigDecimal) fortObj; |
| | | |
| | | MsgModel msg = new MsgModel(consume, fishGold, SID_MID.get(session.getId())); |
| | | // 发送打渔消息 |
| | | fishHitProducer.sendFishHitMsg(JSONObject.toJSONString(msg)); |
| | | } |
| | | |
| | | @OnError |
| | | public void onError(Session session, Throwable error) { |
| | | log.error("捕鱼异常", error); |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.websocket.fish.model; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Data |
| | | public class MsgModel { |
| | | |
| | | /** |
| | | * 消耗金币 |
| | | */ |
| | | private BigDecimal consume; |
| | | |
| | | /** |
| | | * 获得金币 |
| | | */ |
| | | private int obtain; |
| | | |
| | | /** |
| | | * 用户ID |
| | | */ |
| | | private Long memberId; |
| | | |
| | | public MsgModel(BigDecimal consume, int obtain, Long memberId) { |
| | | this.consume = consume; |
| | | this.obtain = obtain; |
| | | this.memberId = memberId; |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.websocket.handler; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xcong.excoin.common.contants.AppContants; |
| | | import com.xcong.excoin.netty.handler.WebSocketServerHandler; |
| | | import com.xcong.excoin.rabbit.producer.FishHitProducer; |
| | | import com.xcong.excoin.utils.RedisUtils; |
| | | import com.xcong.excoin.websocket.fish.model.MsgModel; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.web.socket.*; |
| | | import org.springframework.web.socket.handler.TextWebSocketHandler; |
| | | |
| | | import javax.websocket.Session; |
| | | import java.math.BigDecimal; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Slf4j |
| | | @Component |
| | | public class FishHitWebSocketHandler extends TextWebSocketHandler { |
| | | |
| | | @Autowired |
| | | private RedisUtils redisUtils; |
| | | @Autowired |
| | | private FishHitProducer fishHitProducer; |
| | | |
| | | private final Map<Long, WebSocketSession> MEMBER_SESSIONS = new ConcurrentHashMap<>(); |
| | | private final Map<String, Long> SID_MID = new ConcurrentHashMap<>(); |
| | | |
| | | |
| | | @Override |
| | | public void afterConnectionEstablished(WebSocketSession session) throws Exception { |
| | | Object token = session.getAttributes().get("token"); |
| | | if (token != null) { |
| | | String redisStr = AppContants.APP_LOGIN_PREFIX + token; |
| | | String memberStr = redisUtils.getString(redisStr); |
| | | if (StrUtil.isBlank(memberStr)) { |
| | | session.sendMessage(new TextMessage("{ code:-1, msg: \"Unauthorized\"}")); |
| | | return; |
| | | } |
| | | |
| | | JSONObject memberObject = JSONObject.parseObject(memberStr); |
| | | Long memberId = memberObject.getLong("id"); |
| | | MEMBER_SESSIONS.put(memberId, session); |
| | | SID_MID.put(session.getId(), memberId); |
| | | session.sendMessage(new TextMessage("{ code:0, msg: \"login succes\" }")); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * |
| | | * @param content { type : "hit", fortId : 1, fishType : "fish1" } |
| | | * @param session |
| | | */ |
| | | @Override |
| | | public void handleTextMessage(WebSocketSession session, TextMessage content) throws Exception { |
| | | String message = content.getPayload(); |
| | | |
| | | JSONObject reqParam = JSONObject.parseObject(message); |
| | | String type = reqParam.getString("type"); |
| | | if (!("hit").equals(type)) { |
| | | session.sendMessage(new TextMessage("{code:-1}")); |
| | | return; |
| | | } |
| | | |
| | | // 打中鱼奖励金币 |
| | | int fishGold = 0; |
| | | String fishType = reqParam.getString("fishType"); |
| | | |
| | | // 如果请求参数中包含鱼类型,且类型不为空,则说明打中 |
| | | if (reqParam.containsKey("fishType") && StrUtil.isNotBlank(fishType)) { |
| | | Object fishTypeObj = redisUtils.hget(AppContants.DICTIONARY_TYPE_FISH, fishType); |
| | | if (fishTypeObj == null) { |
| | | session.sendMessage(new TextMessage("{code : -1, msg : \"fish error\"}")); |
| | | return; |
| | | } |
| | | |
| | | fishGold = (int) fishTypeObj; |
| | | } |
| | | |
| | | String fortId = reqParam.getString("fortId"); |
| | | if (!reqParam.containsKey("fortId") || fortId == null) { |
| | | return; |
| | | } |
| | | |
| | | Object fortObj = redisUtils.hget(AppContants.CANNON_TYPE, fortId); |
| | | if (fortObj == null) { |
| | | session.sendMessage(new TextMessage("{code : -1, msg : \"fort error\"}")); |
| | | return; |
| | | } |
| | | |
| | | // 消耗金币 |
| | | BigDecimal consume = (BigDecimal) fortObj; |
| | | |
| | | MsgModel msg = new MsgModel(consume, fishGold, SID_MID.get(session.getId())); |
| | | // 发送打渔消息 |
| | | fishHitProducer.sendFishHitMsg(JSONObject.toJSONString(msg)); |
| | | } |
| | | |
| | | @Override |
| | | public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { |
| | | } |
| | | |
| | | @Override |
| | | public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { |
| | | Long memberId = SID_MID.get(session.getId()); |
| | | |
| | | SID_MID.remove(session.getId()); |
| | | MEMBER_SESSIONS.remove(memberId); |
| | | } |
| | | } |
New file |
| | |
| | | package com.xcong.excoin.websocket.handler; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.http.HttpUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.server.ServerHttpRequest; |
| | | import org.springframework.http.server.ServerHttpResponse; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.web.socket.WebSocketHandler; |
| | | import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; |
| | | |
| | | import java.nio.charset.Charset; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2021-11-26 |
| | | **/ |
| | | @Slf4j |
| | | @Component |
| | | public class FishHitWebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor { |
| | | |
| | | |
| | | @Override |
| | | public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { |
| | | String query = request.getURI().getQuery(); |
| | | if (StrUtil.isBlank(query)) { |
| | | return false; |
| | | } |
| | | |
| | | HashMap<String, String> paramMap = (HashMap<String, String>) HttpUtil.decodeParamMap(query, Charset.defaultCharset()); |
| | | String token = paramMap.get("token"); |
| | | if (StrUtil.isBlank(token)) { |
| | | return false; |
| | | } |
| | | |
| | | attributes.put("token", token); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | loop-job: false |
| | | rabbit-consumer: false |
| | | block-job: true |
| | | fish-hit: false |
| | | |
| | | aliyun: |
| | | oss: |
| | |
| | | ## redis配置 |
| | | redis: |
| | | ## Redis数据库索引(默认为0) |
| | | database: 0 |
| | | database: 5 |
| | | ## Redis服务器地址 |
| | | host: 154.91.195.155 |
| | | host: 120.27.238.55 |
| | | ## Redis服务器连接端口 |
| | | port: 6379 |
| | | ## Redis服务器连接密码(默认为空) |
| | | password: ann123!@# |
| | | password: xcong123 |
| | | jedis: |
| | | pool: |
| | | ## 连接池最大连接数(使用负值表示没有限制) |
| | |
| | | loop-job: false |
| | | rabbit-consumer: false |
| | | block-job: false |
| | | fish-hit: true |
| | | |
| | | aliyun: |
| | | oss: |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.xcong.excoin.common.system.dao.DataDictionaryCustomDao"> |
| | | |
| | | <select id="selectDicByType" resultType="com.xcong.excoin.common.system.entity.DataDictionaryCustom"> |
| | | select * from data_dictionary_custom where type=#{type} |
| | | </select> |
| | | |
| | | <select id="selectDicDataByTypeAndCode" resultType="com.xcong.excoin.common.system.entity.DataDictionaryCustom"> |
| | | select * from data_dictionary_custom a |
| | | where a.type=#{type} and a.code=#{code} |
| | | </select> |
| | | </mapper> |
| | |
| | | </select> |
| | | |
| | | <select id="selectCannonOwnRecordsByMemberId" resultType="com.xcong.excoin.modules.fish.vo.OwnCannonVo"> |
| | | select a.*,b.gold_consume goldConsume,b.cannon_img cannonImg,b.bullet_img bulletImg |
| | | from cannon_own_record a |
| | | left join cannon_setting b on a.cannon_code = b.code |
| | | where a.member_id = #{memberId} |
| | | select |
| | | a.*, |
| | | case when b.id is null then 0 else 1 end isHas |
| | | from cannon_setting a |
| | | left join cannon_own_record b on a.code=b.cannon_code and b.member_id=#{memberId} |
| | | </select> |
| | | |
| | | <select id="selectCannonOwnRecordsByIdAndMemberId" resultType="com.xcong.excoin.modules.fish.entity.CannonOwnRecord"> |
| | |
| | | select a.* from member_account_gold a where a.member_id = #{memberId} |
| | | </select> |
| | | |
| | | <select id="selectByMemberIdForLock" resultType="com.xcong.excoin.modules.fish.entity.MemberAccountGold"> |
| | | select a.* from member_account_gold a where a.member_id = #{memberId} for update |
| | | </select> |
| | | </mapper> |