孙永军 пре 1 година
родитељ
комит
02ef5bc7fc
35 измењених фајлова са 1082 додато и 0 уклоњено
  1. 17 0
      src/main/java/com/smcic/SspServerApplication.java
  2. 52 0
      src/main/java/com/smcic/api/epg/controller/EpgController.java
  3. 14 0
      src/main/java/com/smcic/api/epg/dto/DisableDTO.java
  4. 16 0
      src/main/java/com/smcic/api/epg/entity/Channel.java
  5. 24 0
      src/main/java/com/smcic/api/epg/entity/EpgDisableConfig.java
  6. 35 0
      src/main/java/com/smcic/api/epg/entity/Program.java
  7. 23 0
      src/main/java/com/smcic/api/epg/job/EpgRefreshJob.java
  8. 14 0
      src/main/java/com/smcic/api/epg/mapper/ChannelMapper.java
  9. 7 0
      src/main/java/com/smcic/api/epg/mapper/EpgDisableConfigMapper.java
  10. 16 0
      src/main/java/com/smcic/api/epg/mapper/ProgramMapper.java
  11. 7 0
      src/main/java/com/smcic/api/epg/service/IChannelService.java
  12. 7 0
      src/main/java/com/smcic/api/epg/service/IEpgDisableConfigService.java
  13. 7 0
      src/main/java/com/smcic/api/epg/service/IProgramService.java
  14. 21 0
      src/main/java/com/smcic/api/epg/service/impl/ChannelService.java
  15. 55 0
      src/main/java/com/smcic/api/epg/service/impl/EpgDisableConfigService.java
  16. 71 0
      src/main/java/com/smcic/api/epg/service/impl/ProgramService.java
  17. 31 0
      src/main/java/com/smcic/core/advice/APIException.java
  18. 13 0
      src/main/java/com/smcic/core/advice/APINoDataResponse.java
  19. 13 0
      src/main/java/com/smcic/core/advice/APIResponse.java
  20. 121 0
      src/main/java/com/smcic/core/advice/APIResponseAdvice.java
  21. 11 0
      src/main/java/com/smcic/core/advice/NoAPIResponse.java
  22. 13 0
      src/main/java/com/smcic/core/advice/ResponseMsg.java
  23. 79 0
      src/main/java/com/smcic/core/auth/AESUtil.java
  24. 38 0
      src/main/java/com/smcic/core/auth/LoginInterceptor.java
  25. 11 0
      src/main/java/com/smcic/core/auth/LoginRequired.java
  26. 88 0
      src/main/java/com/smcic/core/conf/CacheConfig.java
  27. 24 0
      src/main/java/com/smcic/core/conf/Constant.java
  28. 17 0
      src/main/java/com/smcic/core/conf/MybatisConf.java
  29. 37 0
      src/main/java/com/smcic/core/conf/WebConfig.java
  30. 24 0
      src/main/java/com/smcic/core/page/PageResponse.java
  31. 41 0
      src/main/java/com/smcic/core/util/HttpReqRespUtils.java
  32. 61 0
      src/main/resources/application.yml
  33. 16 0
      src/main/resources/com/smcic/ChannelMapper.xml
  34. 15 0
      src/main/resources/com/smcic/ProgramMapper.xml
  35. 43 0
      src/main/resources/logback.xml

+ 17 - 0
src/main/java/com/smcic/SspServerApplication.java

@@ -0,0 +1,17 @@
+package com.smcic;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@MapperScan("com.smcic")
+@EnableScheduling
+public class SspServerApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(SspServerApplication.class, args);
+    }
+
+}

+ 52 - 0
src/main/java/com/smcic/api/epg/controller/EpgController.java

@@ -0,0 +1,52 @@
+package com.smcic.api.epg.controller;
+
+import com.smcic.api.epg.dto.DisableDTO;
+import com.smcic.api.epg.entity.Channel;
+import com.smcic.api.epg.entity.Program;
+import com.smcic.api.epg.service.impl.ChannelService;
+import com.smcic.api.epg.service.impl.EpgDisableConfigService;
+import com.smcic.api.epg.service.impl.ProgramService;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("epg")
+public class EpgController {
+
+    @Resource
+    private ChannelService channelService;
+
+    @Resource
+    private ProgramService programService;
+
+    @Resource
+    private EpgDisableConfigService epgDisableConfigService;
+
+    @RequestMapping("tv")
+    public List<Channel> tv(){
+        return channelService.tvList();
+    }
+
+    @RequestMapping("fm")
+    public List<Channel> fm(){
+        return channelService.fmList();
+    }
+
+    @RequestMapping("list")
+    public List<Map<String, Object>> list(@Param("channelId") Integer channelId){
+        return programService.cacheEpg(channelId);
+    }
+
+    @PostMapping("disable")
+    public void disable(@RequestBody DisableDTO disableDTO){
+        epgDisableConfigService.disable(disableDTO);
+    }
+}

+ 14 - 0
src/main/java/com/smcic/api/epg/dto/DisableDTO.java

@@ -0,0 +1,14 @@
+package com.smcic.api.epg.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class DisableDTO {
+    private Integer channelId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+}

+ 16 - 0
src/main/java/com/smcic/api/epg/entity/Channel.java

@@ -0,0 +1,16 @@
+package com.smcic.api.epg.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Data;
+
+@Data
+public class Channel {
+
+    @TableField("channel_id")
+    private Integer channelId;
+
+    @TableField("Title")
+    private String title;
+
+    private Integer epgchannelid;
+}

+ 24 - 0
src/main/java/com/smcic/api/epg/entity/EpgDisableConfig.java

@@ -0,0 +1,24 @@
+package com.smcic.api.epg.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class EpgDisableConfig {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    private Integer channelId;
+
+    private String channelName;
+
+    private String program;
+
+    private LocalDateTime startTime;
+
+    private Integer status;
+}

+ 35 - 0
src/main/java/com/smcic/api/epg/entity/Program.java

@@ -0,0 +1,35 @@
+package com.smcic.api.epg.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+public class Program {
+
+    private Integer id;
+
+    @TableField("Title")
+    private String title;
+
+    @TableField("Category")
+    private Integer category;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @TableField("Broadcast_Date")
+    private LocalDate broadcastDate;
+
+    private String channelName;
+
+    @TableField(exist = false)
+    private Integer status = 0;
+}

+ 23 - 0
src/main/java/com/smcic/api/epg/job/EpgRefreshJob.java

@@ -0,0 +1,23 @@
+package com.smcic.api.epg.job;
+
+import com.smcic.api.epg.service.impl.ChannelService;
+import com.smcic.api.epg.service.impl.ProgramService;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class EpgRefreshJob {
+
+    @Resource
+    private ProgramService programService;
+
+    @Resource
+    private ChannelService channelService;
+
+    @Scheduled(cron = "0 */10 * * * *")
+    public void refresh() {
+        channelService.tvList().forEach(channel -> programService.setCache(channel.getChannelId()));
+    }
+}

+ 14 - 0
src/main/java/com/smcic/api/epg/mapper/ChannelMapper.java

@@ -0,0 +1,14 @@
+package com.smcic.api.epg.mapper;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smcic.api.epg.entity.Channel;
+
+import java.util.List;
+
+@DS("tide")
+public interface ChannelMapper extends BaseMapper<Channel> {
+    List<Channel> tvList();
+    List<Channel> fmList();
+    Channel channelById(Integer channelId);
+}

+ 7 - 0
src/main/java/com/smcic/api/epg/mapper/EpgDisableConfigMapper.java

@@ -0,0 +1,7 @@
+package com.smcic.api.epg.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smcic.api.epg.entity.EpgDisableConfig;
+
+public interface EpgDisableConfigMapper extends BaseMapper<EpgDisableConfig> {
+}

+ 16 - 0
src/main/java/com/smcic/api/epg/mapper/ProgramMapper.java

@@ -0,0 +1,16 @@
+package com.smcic.api.epg.mapper;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smcic.api.epg.entity.Program;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@DS("tide")
+public interface ProgramMapper extends BaseMapper<Program> {
+
+    List<Program> listByChannel(Integer channelId, LocalDateTime startTime, LocalDateTime endTime);
+
+    Program byStartAndChannel(Integer channelId, LocalDateTime startTime);
+}

+ 7 - 0
src/main/java/com/smcic/api/epg/service/IChannelService.java

@@ -0,0 +1,7 @@
+package com.smcic.api.epg.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.smcic.api.epg.entity.Channel;
+
+public interface IChannelService extends IService<Channel> {
+}

+ 7 - 0
src/main/java/com/smcic/api/epg/service/IEpgDisableConfigService.java

@@ -0,0 +1,7 @@
+package com.smcic.api.epg.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.smcic.api.epg.entity.EpgDisableConfig;
+
+public interface IEpgDisableConfigService extends IService<EpgDisableConfig> {
+}

+ 7 - 0
src/main/java/com/smcic/api/epg/service/IProgramService.java

@@ -0,0 +1,7 @@
+package com.smcic.api.epg.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.smcic.api.epg.entity.Program;
+
+public interface IProgramService extends IService<Program> {
+}

+ 21 - 0
src/main/java/com/smcic/api/epg/service/impl/ChannelService.java

@@ -0,0 +1,21 @@
+package com.smcic.api.epg.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.smcic.api.epg.entity.Channel;
+import com.smcic.api.epg.mapper.ChannelMapper;
+import com.smcic.api.epg.service.IChannelService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ChannelService extends ServiceImpl<ChannelMapper, Channel> implements IChannelService{
+
+    public List<Channel> tvList(){
+        return baseMapper.tvList();
+    }
+
+    public List<Channel> fmList(){
+        return baseMapper.fmList();
+    }
+}

+ 55 - 0
src/main/java/com/smcic/api/epg/service/impl/EpgDisableConfigService.java

@@ -0,0 +1,55 @@
+package com.smcic.api.epg.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.smcic.api.epg.dto.DisableDTO;
+import com.smcic.api.epg.entity.Channel;
+import com.smcic.api.epg.entity.EpgDisableConfig;
+import com.smcic.api.epg.entity.Program;
+import com.smcic.api.epg.mapper.EpgDisableConfigMapper;
+import com.smcic.api.epg.service.IEpgDisableConfigService;
+import com.smcic.core.advice.APIException;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class EpgDisableConfigService extends ServiceImpl<EpgDisableConfigMapper, EpgDisableConfig> implements IEpgDisableConfigService {
+
+    @Resource
+    private ChannelService channelService;
+
+    @Resource
+    private ProgramService programService;
+
+    public Map<LocalDateTime, EpgDisableConfig> cfMap(Integer channelId, LocalDateTime start, LocalDateTime end){
+        Map<LocalDateTime, EpgDisableConfig> map = new HashMap<>();
+        lambdaQuery().eq(EpgDisableConfig::getChannelId, channelId).ge(EpgDisableConfig::getStartTime, start)
+                .le(EpgDisableConfig::getStartTime, end).eq(EpgDisableConfig::getStatus, 1).list()
+                .forEach(sspDisableConfig -> map.put(sspDisableConfig.getStartTime(), sspDisableConfig));
+        return map;
+    }
+
+    public void disable(DisableDTO disableDTO){
+        Channel channel = channelService.getBaseMapper().channelById(disableDTO.getChannelId());
+        if(null == channel){
+            throw new APIException("不存在的频率频道");
+        }
+        Program program = programService.getBaseMapper().byStartAndChannel(disableDTO.getChannelId(), disableDTO.getStartTime());
+
+        if(null == program){
+            throw new APIException("不存在的节目");
+        }
+
+        EpgDisableConfig epgDisableConfig = new EpgDisableConfig();
+        epgDisableConfig.setChannelId(disableDTO.getChannelId());
+        epgDisableConfig.setChannelName(channel.getTitle());
+        epgDisableConfig.setStartTime(disableDTO.getStartTime());
+        epgDisableConfig.setProgram(program.getTitle());
+        epgDisableConfig.setStatus(1);
+        save(epgDisableConfig);
+        programService.setCache(disableDTO.getChannelId());
+    }
+}

+ 71 - 0
src/main/java/com/smcic/api/epg/service/impl/ProgramService.java

@@ -0,0 +1,71 @@
+package com.smcic.api.epg.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.google.common.collect.ImmutableMap;
+import com.smcic.api.epg.entity.Program;
+import com.smcic.api.epg.entity.EpgDisableConfig;
+import com.smcic.api.epg.mapper.ProgramMapper;
+import com.smcic.api.epg.service.IProgramService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Service
+public class ProgramService extends ServiceImpl<ProgramMapper, Program> implements IProgramService {
+
+    @Resource
+    private EpgDisableConfigService sspDisableConfigService;
+
+    private final Cache<Integer, Object> cache = Caffeine.newBuilder().expireAfterWrite(15, TimeUnit.MINUTES).build();
+
+    public List<Map<String, Object>> getProgramList(Integer channelId) {
+        System.out.println("-------------------获取epg-----------------------");
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime end = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 23, 59, 59);
+        LocalDateTime start = end.minusDays(7).plusSeconds(1);
+        List<Map<String, Object>> rs = new ArrayList<>();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        Map<LocalDateTime, EpgDisableConfig> sspDisableConfigMap = sspDisableConfigService.cfMap(channelId, start, end);
+
+        baseMapper.listByChannel(channelId, start, end).stream().peek(program -> {
+            if(sspDisableConfigMap.containsKey(program.getStartTime())){
+                program.setStatus(1);
+            }else{
+                program.setStatus(0);
+            }
+        }).collect(Collectors.groupingBy(Program::getBroadcastDate)).forEach((k, v) -> {
+            int status = 0;
+            for(Program program : v){
+                if (program.getStatus() == 1) {
+                    status = 1;
+                    break;
+                }
+            }
+
+            rs.add(ImmutableMap.of("date", k.format(formatter), "epg", v, "status", status));
+        });
+        rs.sort(Comparator.comparing((Map<String, Object> o) -> o.get("date").toString()));
+        return rs;
+    }
+
+    public List<Map<String, Object>> cacheEpg(Integer channelId) {
+        return (List<Map<String, Object>>)cache.get(channelId, key -> getProgramList(channelId));
+    }
+
+    public void setCache(Integer channelId){
+        System.out.println("更新缓存" + channelId);
+        cache.put(channelId, getProgramList(channelId));
+    }
+}

+ 31 - 0
src/main/java/com/smcic/core/advice/APIException.java

@@ -0,0 +1,31 @@
+package com.smcic.core.advice;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class APIException extends RuntimeException {
+
+    private int errorCode;
+
+    private String errorMessage;
+
+    public APIException(String errorMessage) {
+        super(errorMessage);
+        this.errorCode = -1;
+        this.errorMessage = errorMessage;
+    }
+
+    public APIException(int errorCode, String errorMessage) {
+        super(errorMessage);
+        this.errorCode = errorCode;
+        this.errorMessage = errorMessage;
+    }
+
+    public APIException(Throwable cause, int errorCode, String errorMessage) {
+        super(errorMessage, cause);
+        this.errorCode = errorCode;
+        this.errorMessage = errorMessage;
+    }
+}

+ 13 - 0
src/main/java/com/smcic/core/advice/APINoDataResponse.java

@@ -0,0 +1,13 @@
+package com.smcic.core.advice;
+
+import lombok.Data;
+
+@Data
+public class APINoDataResponse  {
+
+    private String message;
+
+    private Integer code;
+
+
+}

+ 13 - 0
src/main/java/com/smcic/core/advice/APIResponse.java

@@ -0,0 +1,13 @@
+package com.smcic.core.advice;
+
+import lombok.Data;
+
+@Data
+public class APIResponse {
+
+    private String message;
+
+    private Integer code;
+
+    private Object data;
+}

+ 121 - 0
src/main/java/com/smcic/core/advice/APIResponseAdvice.java

@@ -0,0 +1,121 @@
+package com.smcic.core.advice;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.MethodParameter;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+@RestControllerAdvice
+@Slf4j
+public class APIResponseAdvice implements ResponseBodyAdvice<Object> {
+
+    //自动处理APINoDataResponse,包装为APINoDataResponse
+    @ExceptionHandler(APIException.class)
+    public APINoDataResponse handleApiException(HttpServletRequest request, APIException ex, HttpServletResponse response) {
+        log.error("process url {} failed", request.getRequestURL().toString(), ex);
+        APINoDataResponse apiNoDataResponse = new APINoDataResponse();
+        apiNoDataResponse.setCode(ex.getErrorCode());
+        apiNoDataResponse.setMessage(ex.getErrorMessage());
+
+        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+        return apiNoDataResponse;
+    }
+
+    /**
+     * 拦截未知的运行时异常
+     *
+     * @author fengshuonan
+     * @date 2020/12/16 15:12
+     */
+    @ExceptionHandler(Throwable.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public APINoDataResponse serverError(Throwable ex) {
+        log.error("服务器运行异常", ex);
+        APINoDataResponse apiResponse = new APINoDataResponse();
+        apiResponse.setCode(-1);
+        apiResponse.setMessage("服务器运行异常");
+        return apiResponse;
+    }
+
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public APINoDataResponse validationBodyException(MethodArgumentNotValidException exception) {
+
+        BindingResult result = exception.getBindingResult();
+        if (result.hasErrors()) {
+
+            List<ObjectError> errors = result.getAllErrors();
+
+            errors.forEach(p -> {
+
+                FieldError fieldError = (FieldError) p;
+                log.error("Data check failure : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() +
+                        "},errorMessage{" + fieldError.getDefaultMessage() + "}");
+
+            });
+
+        }
+        APINoDataResponse apiResponse = new APINoDataResponse();
+        apiResponse.setCode(-1);
+        apiResponse.setMessage("请填写正确信息");
+        return apiResponse;
+    }
+
+
+    //仅当方法或类没有标记@NoAPIResponse才自动包装
+    @Override
+    public boolean supports(MethodParameter returnType, Class converterType) {
+        return returnType.getParameterType() != APIResponse.class && returnType.getParameterType() != APINoDataResponse.class
+                && AnnotationUtils.findAnnotation(returnType.getDeclaringClass(), NoAPIResponse.class) == null;
+    }
+
+    //自动包装外层APIResposne响应
+    @Override
+    public Object beforeBodyWrite(Object body,
+                                  MethodParameter returnType,
+                                  MediaType selectedContentType,
+                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
+                                  ServerHttpRequest request, ServerHttpResponse response) {
+
+
+        ResponseMsg responseMsg = returnType.getMethodAnnotation(ResponseMsg.class);
+        String msg = "OK";
+
+        if (null != responseMsg) {
+            msg = responseMsg.value();
+        }
+
+        if (null == body) {
+            APINoDataResponse apiResponse = new APINoDataResponse();
+            apiResponse.setCode(0);
+
+            apiResponse.setMessage(msg);
+            return apiResponse;
+        } else {
+            APIResponse apiResponse = new APIResponse();
+
+            apiResponse.setCode(0);
+            apiResponse.setMessage(msg);
+            apiResponse.setData(body);
+            return apiResponse;
+        }
+
+    }
+
+}

+ 11 - 0
src/main/java/com/smcic/core/advice/NoAPIResponse.java

@@ -0,0 +1,11 @@
+package com.smcic.core.advice;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NoAPIResponse {
+}

+ 13 - 0
src/main/java/com/smcic/core/advice/ResponseMsg.java

@@ -0,0 +1,13 @@
+package com.smcic.core.advice;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ResponseMsg {
+    String value() default "OK";
+}

+ 79 - 0
src/main/java/com/smcic/core/auth/AESUtil.java

@@ -0,0 +1,79 @@
+package com.smcic.core.auth;
+
+
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.symmetric.AES;
+import com.smcic.core.advice.APIException;
+import com.smcic.core.conf.Constant;
+
+import java.nio.charset.StandardCharsets;
+
+public class AESUtil {
+    private static final AES aes = SecureUtil.aes(Constant.AES_KEY.getBytes(StandardCharsets.UTF_8));
+
+    public static String encryptHex(String data, long addSecond) {
+        //加入了随机旋转和时间戳 避免加密后得到的是同样的数据 得到的token比传统的jwt要小很多
+        int randomInt = RandomUtil.randomInt(data.length());
+        data = shift(data, randomInt);
+        return aes.encryptHex(randomInt + "," + data + "," + (getCurrentTime() + addSecond));
+    }
+
+    public static String encryptHex(String data){
+        return encryptHex(data,Constant.ACCESS_TOKEN_EXPIRE_TIME);
+    }
+
+    public static String decryptStr(String token) {
+        String[] dataArray;
+        long time;
+        try {
+            token = aes.decryptStr(token, CharsetUtil.CHARSET_UTF_8);
+            dataArray = token.split(",");
+            time = Long.parseLong(dataArray[2]);
+        } catch (Exception e) {
+            throw new APIException(Constant.TOKEN_PARSE_ERROR, "token 异常");
+        }
+        if (time < getCurrentTime()) {
+            throw new APIException(Constant.TOKEN_EXPIRE, "token 已过期");
+        }
+        int i = Integer.parseInt(dataArray[0]);
+        return shift(dataArray[1], i * -1);
+    }
+
+    public static boolean isOk(String token){
+        try {
+            decryptStr(token);
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+
+
+    private static long getCurrentTime() {
+        return System.currentTimeMillis() / 1000 - Constant.SUB_TIME;
+    }
+
+    private static String shift(String str, int n) {
+        if (n == 0) {
+            return str;
+        }
+        int len = str.length();
+        char[] oldStr = str.toCharArray();
+        char[] newStr = new char[len];
+        n = n % len;
+        if (n < 0) {
+            n = len + n;
+        }
+        for (int i = 0; i < len; i++) {
+            newStr[(i + n) % len] = oldStr[i];
+        }
+        return new String(newStr);
+    }
+
+
+
+}

+ 38 - 0
src/main/java/com/smcic/core/auth/LoginInterceptor.java

@@ -0,0 +1,38 @@
+package com.smcic.core.auth;
+
+
+import cn.hutool.core.util.StrUtil;
+import com.smcic.core.advice.APIException;
+import com.smcic.core.conf.Constant;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.AsyncHandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+
+public class LoginInterceptor implements AsyncHandlerInterceptor {
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        if (!(handler instanceof HandlerMethod)) {
+            return true;
+        }
+
+        HandlerMethod handlerMethod = (HandlerMethod) handler;
+        Method method = handlerMethod.getMethod();
+
+        LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);
+        if (methodAnnotation == null) {
+            return true;
+        }
+
+        // 这写你拦截需要干的事儿,比如取缓存,SESSION,权限判断等
+        String token = request.getHeader(Constant.TOKEN_HEADER_NAME);
+
+        if (!AESUtil.isOk(token)) {
+            throw new APIException("没有登录");
+        }
+
+        return true;
+    }
+}

+ 11 - 0
src/main/java/com/smcic/core/auth/LoginRequired.java

@@ -0,0 +1,11 @@
+package com.smcic.core.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LoginRequired {
+}

+ 88 - 0
src/main/java/com/smcic/core/conf/CacheConfig.java

@@ -0,0 +1,88 @@
+package com.smcic.core.conf;
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.caffeine.CaffeineCache;
+import org.springframework.cache.support.SimpleCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 缓存全局配置
+ * <p>
+ * Created by zyx on 2017/8/2.
+ */
+@EnableCaching
+@Configuration
+public class CacheConfig {
+
+    private static final int DEFAULT_MAXSIZE = 50000;
+
+    private static final int DEFAULT_TTL = 60 * 30;//缓存过期时间为半个小时
+
+
+    public enum Caches {
+
+        WJWAPI_REQUEST,
+        SINAAPI_CHINAREQUEST;
+
+        Caches() {
+        }
+
+        Caches(int ttl) {
+            this.ttl = ttl;
+        }
+
+        Caches(int ttl, int maxSize) {
+            this.ttl = ttl;
+            this.maxSize = maxSize;
+        }
+
+        /**
+         * 最大数量
+         */
+        private int maxSize = DEFAULT_MAXSIZE;
+        /**
+         * 过期时间 秒
+         */
+        private int ttl = DEFAULT_TTL;
+
+        public int getMaxSize() {
+            return maxSize;
+        }
+
+        public int getTtl() {
+            return ttl;
+        }
+
+    }
+
+    /**
+     * 创建基于Caffeine的Cache Manager
+     * spring boot 默认推荐使用缓存库
+     */
+    @Bean
+    @Primary
+    public CacheManager caffeineCacheManager() {
+        SimpleCacheManager cacheManager = new SimpleCacheManager();
+        ArrayList<CaffeineCache> caches = new ArrayList<>();
+        for (Caches c : Caches.values()) {
+            caches.add(new CaffeineCache(c.name(),
+                    Caffeine.newBuilder().recordStats()
+                            .expireAfterWrite(c.getTtl(), TimeUnit.SECONDS)
+                            .maximumSize(c.getMaxSize())
+                            .build())
+            );
+        }
+
+        cacheManager.setCaches(caches);
+
+        return cacheManager;
+    }
+
+}

+ 24 - 0
src/main/java/com/smcic/core/conf/Constant.java

@@ -0,0 +1,24 @@
+package com.smcic.core.conf;
+
+public class Constant {
+    public static final String AES_KEY = "1234657890123456";
+
+    public static final int TOKEN_PARSE_ERROR = 1000;
+
+    public static final int TOKEN_EXPIRE = 1001;
+
+    //access_token 过期时间为7天 单位是秒
+    public static final long ACCESS_TOKEN_EXPIRE_TIME = 730 * 24 * 60 * 60 ;
+
+    //refresh_token 过期时间为30天 单位是秒
+    public static final long REFRESH_TOKEN_EXPIRE_TIME = 30 * 24 * 60 * 60 ;
+
+    //生成的时间戳减去这个时间 不容易被破解
+    public static final long SUB_TIME = 1600000000;
+
+    public static final String TOKEN_HEADER_NAME = "Authorization";
+
+    public static final String USER_ID = "USER_ID";
+
+    public static final String UPDATE_ACTIVITY = "UPDATE_ACTIVITY";
+}

+ 17 - 0
src/main/java/com/smcic/core/conf/MybatisConf.java

@@ -0,0 +1,17 @@
+package com.smcic.core.conf;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MybatisConf {
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        return interceptor;
+    }
+}

+ 37 - 0
src/main/java/com/smcic/core/conf/WebConfig.java

@@ -0,0 +1,37 @@
+package com.smcic.core.conf;
+
+import cn.hutool.http.GlobalHeaders;
+import cn.hutool.http.Header;
+import com.smcic.core.auth.LoginInterceptor;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer{
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedMethods("*")
+                .allowedOrigins("*")
+                .allowedHeaders("*");
+        GlobalHeaders.INSTANCE.header(Header.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36", true);
+    }
+
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
+        registry.addInterceptor(LoginInterceptor()).addPathPatterns("/**");
+    }
+
+    @Bean
+    public LoginInterceptor LoginInterceptor() {
+        return new LoginInterceptor();
+    }
+
+
+}

+ 24 - 0
src/main/java/com/smcic/core/page/PageResponse.java

@@ -0,0 +1,24 @@
+package com.smcic.core.page;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageResponse<T> {
+    private List<T> data;
+    private long total;
+
+    public static <T> PageResponse<T> load(Page<T> page){
+        return new PageResponse<>(page.getRecords(),page.getTotal());
+    }
+
+    public static <T> PageResponse<T> load(List<T> data,long total){
+        return new PageResponse<>(data,total);
+    }
+}

+ 41 - 0
src/main/java/com/smcic/core/util/HttpReqRespUtils.java

@@ -0,0 +1,41 @@
+package com.smcic.core.util;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class HttpReqRespUtils {
+    private static final String[] IP_HEADER_CANDIDATES = {
+            "X-Forwarded-For",
+            "X-Forwarded-Proto",
+            "Proxy-Client-IP",
+            "WL-Proxy-Client-IP",
+            "HTTP_X_FORWARDED_FOR",
+            "HTTP_X_FORWARDED",
+            "HTTP_X_CLUSTER_CLIENT_IP",
+            "HTTP_CLIENT_IP",
+            "HTTP_FORWARDED_FOR",
+            "HTTP_FORWARDED",
+            "HTTP_VIA",
+            "REMOTE_ADDR"
+    };
+
+    public static String getClientIpAddressIfServletRequestExist() {
+
+        if (RequestContextHolder.getRequestAttributes() == null) {
+            return "0.0.0.0";
+        }
+
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        for (String header: IP_HEADER_CANDIDATES) {
+            String ipList = request.getHeader(header);
+            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
+                String ip = ipList.split(",")[0];
+                return ip;
+            }
+        }
+
+        return request.getRemoteAddr();
+    }
+}

+ 61 - 0
src/main/resources/application.yml

@@ -0,0 +1,61 @@
+mybatis-plus:
+  mapper-locations: classpath*:com/smcic/**/*.xml
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: true
+    lazy-loading-enabled: true
+    multiple-result-sets-enabled: true
+  global-config:
+    banner: false
+    enable-sql-runner: true
+    db-config:
+      id-type: assign_id
+      table-underline: true
+
+
+spring:
+  application:
+    name: bigdata
+  servlet:
+    multipart:
+      max-request-size: 200MB
+      max-file-size: 200MB
+  datasource:
+    dynamic:
+      hikari:
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        max-lifetime: 180000
+        idle-timeout: 30000
+        max-pool-size: 100
+        min-idle: 5
+      primary: ssp
+      strict: false
+      datasource:
+        bigscreen:
+          url: jdbc:mysql://rm-2vc3039h858t9ab7sfo.mysql.cn-chengdu.rds.aliyuncs.com:3306/fanruan?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&nullCatalogMeansCurrent=true
+          username: cxzx
+          password: sxtvs53$68HD
+        ssp:
+          url: jdbc:mysql://rm-2vc3039h858t9ab7sfo.mysql.cn-chengdu.rds.aliyuncs.com:3306/ssp?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&nullCatalogMeansCurrent=true
+          username: cxzx
+          password: sxtvs53$68HD
+        tide:
+          url: jdbc:mysql://rm-2vcyu6uzd1n5m9f756o.mysql.cn-chengdu.rds.aliyuncs.com:3306/tidemedia_cms?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&nullCatalogMeansCurrent=true
+          username: sxsdst
+          password: xfWzxQ@4dfDv
+
+  jackson:
+    time-zone: GMT+8
+    date-format: "yyyy-MM-dd HH:mm:ss"
+server:
+  port: 9002
+  compression:
+    enabled: true
+    mime-types: "application/json,application/xml,text/html,text/xml,text/plain,text/javascript,application/javascript"
+
+  servlet:
+    session:
+      cookie:
+        max-age: 12h
+      timeout: 1m
+

+ 16 - 0
src/main/resources/com/smcic/ChannelMapper.xml

@@ -0,0 +1,16 @@
+<?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.smcic.api.epg.mapper.ChannelMapper">
+    <select id="tvList" resultType="com.smcic.api.epg.entity.Channel">
+        SELECT GlobalId channel_id, Title, epgchannelid  FROM channel_s76_a_a WHERE Category = 18475
+    </select>
+
+    <select id="fmList" resultType="com.smcic.api.epg.entity.Channel">
+        SELECT GlobalId channel_id, Title, epgchannelid  FROM channel_s76_a_a WHERE Category = 18473
+    </select>
+
+    <select id="channelById" resultType="com.smcic.api.epg.entity.Channel">
+        SELECT GlobalId channel_id, Title, epgchannelid  FROM channel_s76_a_a WHERE GlobalId = #{channelId}
+    </select>
+
+</mapper>

+ 15 - 0
src/main/resources/com/smcic/ProgramMapper.xml

@@ -0,0 +1,15 @@
+<?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.smcic.api.epg.mapper.ProgramMapper">
+    <select id="listByChannel" resultType="com.smcic.api.epg.entity.Program">
+        select p.id, p.Title, p.Category, p.start_time, p.end_time, p.Broadcast_Date, c.Title channelName from channel_s4_a_j p, channel_s76_a_a c
+        where c.GlobalId = #{channelId} and c.epgchannelid = p.Category and p.start_time >= #{startTime}
+        and p.start_time &lt;= #{endTime}
+        order by p.start_time
+    </select>
+
+    <select id="byStartAndChannel" resultType="com.smcic.api.epg.entity.Program">
+        select p.id, p.Title, p.Category, p.start_time, p.end_time, p.Broadcast_Date, c.Title channelName from channel_s4_a_j p, channel_s76_a_a c
+        where c.GlobalId = #{channelId} and c.epgchannelid = p.Category and p.start_time = #{startTime}
+    </select>
+</mapper>

+ 43 - 0
src/main/resources/logback.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <property name="logBase" value="./logs"/>
+    <!--控制台输出日志信息-->
+    <appender name="CONSOLE-LOG" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%class:%line] - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logBase}/server.log</file>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%class:%line] - %msg%n</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${logBase}/server.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <appender name="EPG-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logBase}/epg.log</file>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%class:%line] - %msg%n</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${logBase}/epg.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <logger name="com.smcic.api.dianshimao.controller.DianshimaoScheduleController" additivity="false">
+        <appender-ref ref="EPG-LOG"/>
+    </logger>
+
+
+    <logger name="org.apache.ibatis" level="debug" additivity="false"/>
+
+    <root level="error">
+        <appender-ref ref="CONSOLE-LOG"/>
+        <appender-ref ref="FILE-LOG"/>
+    </root>
+</configuration>