Browse Source

"项目构建"

yu_u66 1 month ago
parent
commit
b85ae01321

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 109 - 0
pom.xml

@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.futu</groupId>
+    <artifactId>travel</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>travel</name>
+    <description>travel</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <spring-boot.version>2.7.6</spring-boot.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-data-27</artifactId>
+            <version>3.23.5</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <mainClass>com.futu.TravelApplication</mainClass>
+                    <skip>true</skip>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>repackage</id>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 13 - 0
src/main/java/com/futu/TravelApplication.java

@@ -0,0 +1,13 @@
+package com.futu;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class TravelApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TravelApplication.class, args);
+    }
+
+}

+ 11 - 0
src/main/java/com/futu/common/annotation/NoLoginRequired.java

@@ -0,0 +1,11 @@
+package com.futu.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface NoLoginRequired {
+}

+ 24 - 0
src/main/java/com/futu/common/config/IntercepterConfig.java

@@ -0,0 +1,24 @@
+package com.futu.common.config;
+
+
+
+import com.futu.common.intercepters.AuthIntercepter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class IntercepterConfig implements WebMvcConfigurer {
+
+    @Autowired
+    private AuthIntercepter authIntercepter;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(authIntercepter)
+                .addPathPatterns("/**") ; // 拦截所有请求
+                // 排除不需要拦截的路径
+    }
+
+}

+ 41 - 0
src/main/java/com/futu/common/config/KafkaConsumerConfig.java

@@ -0,0 +1,41 @@
+package com.futu.common.config;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class KafkaConsumerConfig {
+
+    @Value("${spring.kafka.bootstrap-servers}")
+    private String bootstrapServers;
+
+    // 消费者工厂配置
+    @Bean
+    public ConsumerFactory<String, String> consumerFactory() {
+        Map<String, Object> configProps = new HashMap<>();
+        configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
+        configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "my_group");
+        configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+        configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+        return new DefaultKafkaConsumerFactory<>(configProps);
+    }
+
+    // 消费者容器工厂配置(支持并发消费)
+    @Bean
+    public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
+        ConcurrentKafkaListenerContainerFactory<String, String> factory =
+            new ConcurrentKafkaListenerContainerFactory<>();
+        factory.setConsumerFactory(consumerFactory());
+        factory.setConcurrency(3);  // 并发线程数
+        return factory;
+    }
+}

+ 33 - 0
src/main/java/com/futu/common/config/ProductProperties.java

@@ -0,0 +1,33 @@
+package com.futu.common.config;
+
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.core.DefaultKafkaProducerFactory;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.core.ProducerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class ProductProperties {
+    @Value("${spring.kafka.bootstrap-servers}")
+    private String bootstrapServers;
+
+    @Bean
+    public ProducerFactory<String,String>producerFactory(){
+        Map<String, Object>map=new HashMap<>();
+        map.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
+        map.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+        map.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+        return new DefaultKafkaProducerFactory<>(map);
+    }
+    @Bean
+    public KafkaTemplate kafkaTemplate()
+    {
+        return new KafkaTemplate<>(producerFactory());
+    }
+}

+ 51 - 0
src/main/java/com/futu/common/config/RedisConfig.java

@@ -0,0 +1,51 @@
+package com.futu.common.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+
+@Configuration
+public class RedisConfig {
+
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
+
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+
+        template.setConnectionFactory(factory);
+
+
+        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
+
+        ObjectMapper om = new ObjectMapper();
+
+        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+
+        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
+
+        serializer.setObjectMapper(om);
+
+
+        template.setKeySerializer(new StringRedisSerializer());
+
+        template.setHashKeySerializer(new StringRedisSerializer());
+
+        template.setValueSerializer(serializer);
+
+        template.setHashValueSerializer(serializer);
+
+        template.afterPropertiesSet();
+
+
+        return template;
+    }
+}

+ 25 - 0
src/main/java/com/futu/common/config/RedissionConfig.java

@@ -0,0 +1,25 @@
+package com.futu.common.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class RedissionConfig {
+    @Value("${spring.redis.host}")
+    private String host;
+    @Value("${spring.redis.port}")
+    private Integer port;
+    @Value("${spring.redis.database}")
+    private Integer database;
+
+    @Bean
+    public RedissonClient RedissionClient() {
+        Config config = new Config();
+        config.useSingleServer().setAddress("redis://" + host + ":" + port).setDatabase(database);
+        return Redisson.create(config);
+    }
+}

+ 6 - 0
src/main/java/com/futu/common/contans/CommonContants.java

@@ -0,0 +1,6 @@
+package com.futu.common.contans;
+
+public class CommonContants {
+    public static final String PREFIX_TOKEN="token:";
+    public static final ThreadLocal<String> local=new ThreadLocal<>();
+}

+ 42 - 0
src/main/java/com/futu/common/enums/ApiServiceExceptionEnum.java

@@ -0,0 +1,42 @@
+package com.futu.common.enums;
+
+public enum ApiServiceExceptionEnum implements BaseExceptionEnum{
+	SUCCESS(1, "成功"),
+	RESULT_SUCCES(1,"成功"),
+   RESULT_ERROR(0,"失败"),
+   Login_SUCCESS(1,"登录成功"),
+   Login_ERROR(0,"登录失败"),
+   REG_SUCCESS(1,"注册成功"),
+   REG_ERROR(0,"注册失败"),
+   ISEXISTS_ERROR(0,"已存在"),
+   ISADD_ERROR(0,"已创建过"),
+   APPLY_ERROR(0,"已报过名"),
+   APPLY_TIME_ERROR(0,"已超时"),
+   APPLY_NUM_ERROR(0,"报名已满"),
+   USER_NOT_EXISTS(401,"用户不存在");
+
+
+
+
+     ApiServiceExceptionEnum(Integer code , String message) {
+
+    	 this.code=code;
+    	 this.message=message;
+    }
+     private Integer code;
+
+     private String message;
+
+    @Override
+	public Integer getCode() {
+		// TODO Auto-generated method stub
+		return code;
+	}
+
+	@Override
+	public String getMessage() {
+		// TODO Auto-generated method stub
+		return message;
+	}
+
+}

+ 18 - 0
src/main/java/com/futu/common/enums/BaseExceptionEnum.java

@@ -0,0 +1,18 @@
+package com.futu.common.enums;
+
+/**
+ * 抽象接口
+ *
+ */
+public interface BaseExceptionEnum {
+
+    /**
+     * 获取异常编码
+     */
+    Integer getCode();
+
+    /**
+     * 获取异常信息
+     */
+    String getMessage();
+}

+ 31 - 0
src/main/java/com/futu/common/exceptions/ApiException.java

@@ -0,0 +1,31 @@
+package com.futu.common.exceptions;
+
+
+
+
+
+import com.futu.common.enums.BaseExceptionEnum;
+import lombok.Data;
+
+@Data
+public class ApiException extends RuntimeException{
+
+	public Integer code;
+	public String msg;
+	public ApiException(BaseExceptionEnum baseExceptionEnum) {
+		super(baseExceptionEnum.getMessage());
+		this.code = baseExceptionEnum.getCode();
+		this.msg = baseExceptionEnum.getMessage();
+	}
+	public ApiException(String message) {
+		super(message);
+		this.code=101;
+		this.msg=message;
+	}
+	public ApiException(Integer code, String message) {
+		super(message);
+		this.code=code;
+		this.msg=message;
+	}
+
+}

+ 67 - 0
src/main/java/com/futu/common/exceptions/GlobalExceptionHandler.java

@@ -0,0 +1,67 @@
+package com.futu.common.exceptions;
+
+
+
+
+import com.futu.common.vo.ResultVo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MultipartException;
+
+import javax.servlet.http.HttpServletRequest;
+
+@ControllerAdvice
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+    // private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    /**
+     * 系统异常处理,比如:404,500
+     *
+     * @param req
+     * @param e
+     * @return
+     * @throws Exception
+     */
+//    @ExceptionHandler(value = Exception.class)
+    @ResponseBody
+    public ResultVo defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
+        // log.error("", e);
+        log.error(e.getMessage());
+        //判断是否属于自定义异常
+
+
+        if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
+        	return ResultVo.error(404,"不存在页面请求");
+       }
+
+        if (e instanceof ApiException) {
+
+            ApiException customException = (ApiException) e;
+
+            return ResultVo.error(customException.getCode(), customException.getMessage());
+        } else if (e instanceof MultipartException){
+            log.error("系统异常{}", e);
+            return ResultVo.error(1000, "上传文件异常");
+        } else if(e instanceof MethodArgumentNotValidException) {
+            MethodArgumentNotValidException methodArgumentNotValidException=(MethodArgumentNotValidException)e;
+            return ResultVo.error(1002,methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());
+        }else{
+            log.error("系统异常{}", e);
+            return ResultVo.error(1001, "系统参数异常");
+        }
+    }
+
+
+
+//    @ExceptionHandler(value = InsufficientAuthenticationException.class)
+//    @ResponseBody
+//    public ResultVo jsonErrorHandle(HttpServletRequest req, InsufficientAuthenticationException e) {
+//        return ResultVo.error(0, e.getMessage());
+//    }
+
+}

+ 74 - 0
src/main/java/com/futu/common/intercepters/AuthIntercepter.java

@@ -0,0 +1,74 @@
+package com.futu.common.intercepters;
+
+
+import com.futu.common.annotation.NoLoginRequired;
+import com.futu.common.contans.CommonContants;
+import com.futu.common.exceptions.ApiException;
+import com.futu.common.utils.TokenUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+
+@Component
+@Slf4j
+public class AuthIntercepter implements HandlerInterceptor {
+
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+
+
+    public final static  String Token="token";
+
+    public AuthIntercepter() {
+    }
+
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handle)
+    {
+
+        String token  = request.getHeader(Token);
+        log.info(request.getRequestURI());
+        try {
+            if (!(handle instanceof HandlerMethod))
+            {
+                return true;
+            }
+            HandlerMethod handlerMethod=(HandlerMethod)handle;
+            Method method = handlerMethod.getMethod();
+            NoLoginRequired loginRequired = method.getAnnotation(NoLoginRequired.class);
+            if (loginRequired!=null)
+            {
+                return true;
+            }
+            if (StringUtils.isEmpty(token))
+            {
+                log.info("token为空");
+                throw new Exception("token错误,请重新登录");
+            }
+            Long userId = TokenUtils.getUserId(token);
+            log.info("userId",userId);
+            Object user = redisTemplate.opsForValue().get("user");
+            if (user==null)
+            {
+                log.info("*************用户不存在");
+                throw new ApiException(101,"token错误");
+            }
+            CommonContants.local.set(userId.toString());
+
+
+        } catch (Exception e) {
+            log.info("调用了异常通知",e.getMessage());
+            throw new RuntimeException(e);
+        }
+        return true;
+    }
+}

+ 73 - 0
src/main/java/com/futu/common/utils/SnowflakeIdWorker.java

@@ -0,0 +1,73 @@
+package com.futu.common.utils;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class SnowflakeIdWorker {
+    // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
+    private final long twepoch = 1288834974657L;
+    // 机器标识位数
+    private final long workerIdBits = 5L;
+    // 数据标识位数
+    private final long datacenterIdBits = 5L;
+    // 支持的最大机器标识数
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+    // 支持的最大数据标识数
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+    // 序列在id中占的位数
+    private final long sequenceBits = 12L;
+    // 机器ID向左移12位
+    private final long workerIdShift = sequenceBits;
+    // 数据标识符向左移17位(12+5)
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+    // 时间戳向左移22位(5+5+12)
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+    private long workerId;
+    private long datacenterId;
+    private long sequence = 0L;
+    private long lastTimestamp = -1L;
+    private final AtomicLong sequenceGenerator = new AtomicLong(0L);
+
+    public SnowflakeIdWorker(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            if (sequence == 0) {
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        } else {
+            sequence = 0L;
+        }
+        lastTimestamp = timestamp;
+        return ((timestamp - twepoch) << timestampLeftShift) |
+                (datacenterId << datacenterIdShift) |
+                (workerId << workerIdShift) |
+                sequence;
+    }
+
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+}

+ 111 - 0
src/main/java/com/futu/common/utils/TokenUtils.java

@@ -0,0 +1,111 @@
+package com.futu.common.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+import java.security.Key;
+import java.util.Date;
+
+/**
+ * 生成Token工具类
+ */
+public class TokenUtils {
+
+    /**
+     * 签名秘钥
+     */
+    public static final String SECRET = "cjyfutu1688";
+
+    /**
+     * 生成token
+     * @param id 一般传入userName
+     * @return
+     */
+    public static String createJwtToken(String id){
+        String issuer = "www.futureading.com";
+        String subject = "65532781@qq.com";
+        long ttlMillis = System.currentTimeMillis();
+        return createJwtToken(id, issuer, subject, ttlMillis);
+    }
+
+    /**
+     * 生成Token
+     *
+     * @param id
+     *            编号
+     * @param issuer
+     *            该JWT的签发者,是否使用是可选的
+     * @param subject
+     *            该JWT所面向的用户,是否使用是可选的;
+     * @param ttlMillis
+     *            签发时间
+     * @return token String
+     */
+    public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {
+
+        // 签名算法 ,将对token进行签名
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+
+        // 生成签发时间
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        // 通过秘钥签名JWT
+        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
+        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
+
+        // Let's set the JWT Claims
+        JwtBuilder builder = Jwts.builder().setId(id)
+                .setIssuedAt(now)
+                .setSubject(subject)
+                .setIssuer(issuer)
+                .signWith(signatureAlgorithm, signingKey);
+
+        // if it has been specified, let's add the expiration
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            builder.setExpiration(exp);
+        }
+
+        // Builds the JWT and serializes it to a compact, URL-safe string
+        return builder.compact();
+
+    }
+
+    // Sample method to validate and read the JWT
+    public static Claims parseJWT(String jwt) {
+        // This line will throw an exception if it is not a signed JWS (as expected)
+        Claims claims = Jwts.parser()
+                .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET))
+                .parseClaimsJws(jwt).getBody();
+        return claims;
+    }
+
+    public static Long getUserId(String token){
+        Claims claims = null;
+        try {
+            claims = TokenUtils.parseJWT(token);
+        } catch (Exception e) {
+//            throw new RRException("token错误,请重新登录",101);
+        }
+
+        if(null==claims) {
+//            throw new RRException("token错误,请重新登录",101);
+        }
+        String id = claims.getId();
+        Long userId=Long.valueOf(id);
+
+        return userId;
+
+
+    }
+
+    public static void main(String[] args) {
+        System.out.println(TokenUtils.createJwtToken("admin"));
+    }
+}

+ 43 - 0
src/main/java/com/futu/common/vo/ResultVo.java

@@ -0,0 +1,43 @@
+package com.futu.common.vo;
+
+import lombok.Data;
+
+@Data
+public class ResultVo<T> {
+    private Integer code;
+    private String msg;
+    private  T obj;
+    public ResultVo(Integer code, String msg) {
+        this.code=code;
+        this.msg=msg;
+    }
+    public ResultVo() {}
+    public static ResultVo success(Object object) {
+        ResultVo resultVO = new ResultVo(200,"成功");
+        resultVO.setObj(object);
+        return resultVO;
+    }
+
+    public static ResultVo success() {
+        return success(null);
+    }
+    public static ResultVo error(Integer code, String msg) {
+        ResultVo resultVO = new ResultVo();
+        resultVO.setCode(code);
+        resultVO.setMsg(msg);
+        return resultVO;
+    }
+    public static ResultVo error(){
+        ResultVo resultVO=new ResultVo();
+        resultVO.setCode(0);
+        resultVO.setMsg("失败");
+        return resultVO;
+    }
+    public static ResultVo error(Integer code,String msg,Object obj){
+        ResultVo resultVO=new ResultVo();
+        resultVO.setCode(0);
+        resultVO.setMsg(msg);
+        resultVO.setObj(obj);
+        return resultVO;
+    }
+}

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

@@ -0,0 +1,33 @@
+server:
+  port: 8003
+
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://localhost:3306/month?characterEncoding=utf8&serverTimezone=GMT%2B8
+    username: root
+    password: root
+  redis:
+    port: 6379
+    host: localhost
+    password:
+    database: 0
+
+  kafka:
+    bootstrap-servers: 192.168.88.88:9092
+    producer:
+      key-serializer: org.apache.kafka.common.serialization.StringSerializer
+      value-serializer: org.apache.kafka.common.serialization.StringSerializer
+      acks: all
+      retries: 3
+    consumer:
+      group-id: my_group1
+      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
+      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
+      auto-offset-reset: earliest
+      enable-auto-commit: false
+mybatis-plus:
+  type-aliases-package: com.futu.course*.domain
+  mapper-locations: classpath:mapper/*.xml
+  configuration:
+    map-underscore-to-camel-case: true

+ 13 - 0
src/test/java/com/futu/TravelApplicationTests.java

@@ -0,0 +1,13 @@
+package com.futu;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TravelApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}