X723595506 1 week ago
parent
commit
15638b8191
20 changed files with 529 additions and 116 deletions
  1. 14 1
      src/main/java/com/example/demo/common/config/CorsConfig.java
  2. 190 0
      src/main/java/com/example/demo/common/config/IntercepterConfig.java
  3. 49 0
      src/main/java/com/example/demo/common/interceptor/TokenInterceptor.java
  4. 10 0
      src/main/java/com/example/demo/common/utils/RedisUtil.java
  5. 48 2
      src/main/java/com/example/demo/common/utils/TokenUtils.java
  6. 3 0
      src/main/java/com/example/demo/coupon/controller/UserCouponController.java
  7. 5 0
      src/main/java/com/example/demo/order/controller/OrderController.java
  8. 16 12
      src/main/java/com/example/demo/product/controller/ProductController.java
  9. 1 1
      src/main/java/com/example/demo/product/service/ProductTrainService.java
  10. 10 15
      src/main/java/com/example/demo/product/service/impl/ProductFlightServiceImpl.java
  11. 15 43
      src/main/java/com/example/demo/product/service/impl/ProductTrainServiceImpl.java
  12. 5 2
      src/main/java/com/example/demo/scenic_spot/controller/ScenicSpotController.java
  13. 1 1
      src/main/java/com/example/demo/scenic_spot/service/ScenicSpotService.java
  14. 7 14
      src/main/java/com/example/demo/scenic_spot/service/impl/ScenicSpotServiceImpl.java
  15. 29 9
      src/main/java/com/example/demo/user/controller/UserController.java
  16. 10 0
      src/main/java/com/example/demo/user/dto/PerfectDto.java
  17. 3 1
      src/main/java/com/example/demo/user/dto/RegisterDto.java
  18. 9 2
      src/main/java/com/example/demo/user/service/UserService.java
  19. 102 11
      src/main/java/com/example/demo/user/service/impl/UserServiceImpl.java
  20. 2 2
      src/main/java/com/example/demo/user/service/impl/ValidateCodeServiceImpl.java

+ 14 - 1
src/main/java/com/example/demo/common/config/CorsConfig.java

@@ -1,12 +1,18 @@
 package com.example.demo.common.config;
 
+import com.example.demo.common.interceptor.TokenInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
 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 CorsConfig implements WebMvcConfigurer {
 
+    @Autowired
+    private TokenInterceptor tokenInterceptor;
+
     @Override
     public void addCorsMappings(CorsRegistry registry) {
         registry.addMapping("/**")
@@ -14,5 +20,12 @@ public class CorsConfig implements WebMvcConfigurer {
             .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
             .maxAge(3600);
     }
-
+    
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 注册Token拦截器,拦截所有请求
+        registry.addInterceptor(tokenInterceptor)
+                .addPathPatterns("/**")
+                .excludePathPatterns("/user/login", "/user/register", "/user/phoneLogin", "/user/send4Order", "/user/forget","/user/logout");
+    }
 }

+ 190 - 0
src/main/java/com/example/demo/common/config/IntercepterConfig.java

@@ -0,0 +1,190 @@
+package com.example.demo.common.config;
+
+import com.example.demo.common.interceptor.TokenInterceptor;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
+import org.springframework.web.filter.HttpPutFormContentFilter;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import java.io.IOException;
+import java.util.List;
+
+@Configuration
+@Slf4j
+//@EnableWebMvc
+public class IntercepterConfig extends WebMvcConfigurationSupport {
+
+//    @Override
+//    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
+//        log.info("IntercepterConfig--------------------");
+//        resolvers.add(new CurrentUserHandler());
+//    }
+//    @Autowired
+//    AuthIntercepter authIntercepter;
+//    @Autowired
+//    protected RedisTemplate redisTemplate;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
+        registry.addInterceptor(authenticationInterceptor()).excludePathPatterns("**.html").excludePathPatterns("**.txt")
+                .excludePathPatterns("/webjars/**")
+                .excludePathPatterns("/dashboard/list")
+                .excludePathPatterns("/swagger-ui.html")
+                .excludePathPatterns("/swagger-resources/**").excludePathPatterns("/error").addPathPatterns("/**");
+        super.addInterceptors(registry);
+    }
+
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        super.addResourceHandlers(registry);
+        registry.addResourceHandler("/**")
+                .addResourceLocations("classpath:/static/")
+                .addResourceLocations("classpath:/templates/")
+                .addResourceLocations("classpath:/resources/");
+        registry.addResourceHandler("swagger-ui.html")
+                .addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**")
+                .addResourceLocations("classpath:/META-INF/resources/webjars/");
+        registry.addResourceHandler("SFLMPwcUTv.txt")
+                .addResourceLocations("classpath:/resources/");
+
+    }
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        super.addCorsMappings(registry);
+        registry
+                .addMapping("/**")
+                .allowedHeaders("*")
+                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+                .allowedOrigins("*");
+    }
+    
+    @Bean
+    public TokenInterceptor authenticationInterceptor() {
+        return new TokenInterceptor();
+    }
+    
+//    @Bean
+//    public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
+//        return new CurrentUserMethodArgumentResolver();
+//    }
+//    @Override
+////    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
+////        argumentResolvers.add(currentUserMethodArgumentResolver());
+////        super.addArgumentResolvers(argumentResolvers);
+////    }
+
+    /**
+     * @Description 解决使用put请求   服务器接收不到参数
+     * @author DengKaiTao
+     * @date 2018/12/4 16:35
+     * @return org.springframework.web.filter.HttpPutFormContentFilter
+     * @version v1.0
+     **/
+    @Bean
+    public HttpPutFormContentFilter httpPutFormContentFilter() {
+        return new HttpPutFormContentFilter();
+    }
+    
+//    @Override
+//    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
+//
+////        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
+////        FastJsonConfig config = new FastJsonConfig();
+////        config.setSerializerFeatures(
+////                //保留map空的字段
+////                SerializerFeature.WriteMapNullValue,
+////                // 将String类型的NULL转化为""
+////                SerializerFeature.WriteNullStringAsEmpty,
+////                // 将Number类型的NULL转化为0
+////                SerializerFeature.WriteNullNumberAsZero,
+////                // 将List类型的NULL转成[]
+////                SerializerFeature.WriteNullListAsEmpty,
+////                // 将Boolean类型的NULL转化为false
+////                SerializerFeature.WriteNullBooleanAsFalse,
+////                SerializerFeature.PrettyFormat,
+////                // 避免循环引用
+////                SerializerFeature.DisableCircularReferenceDetect);
+////
+////        converter.setFastJsonConfig(config);
+////        converter.setDefaultCharset(Charset.forName("UTF-8"));
+////
+////        List<MediaType> mediaTypeList = new ArrayList<>();
+////        // 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"
+////        mediaTypeList.add(MediaType.APPLICATION_JSON);
+////        converter.setSupportedMediaTypes(mediaTypeList);
+////        converters.add(converter);
+//        //定义Json转换器
+//        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
+//        ObjectMapper objectMapper = new ObjectMapper();
+//        //定义对象模型
+//        SimpleModule simpleModule = new SimpleModule();
+//        //添加对长整型的转换关系
+//        simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
+////        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
+////        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
+////        simpleModule.addSerializer(Date.class,ToStringSerializer.instance);
+//        //将对象模型添加至对象映射器
+//        objectMapper.registerModule(simpleModule);
+//        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
+//        //在转换器列表中添加自定义的Json转换器
+//        converters.add(jackson2HttpMessageConverter);
+//        //添加utf-8的默认String转换器
+//        converters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
+//    }
+
+    @Bean
+    @Primary
+    @ConditionalOnMissingBean(ObjectMapper.class)
+    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
+    {
+        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
+
+        // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
+        // Include.Include.ALWAYS 默认
+        // Include.NON_DEFAULT 属性为默认值不序列化
+        // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
+        // Include.NON_NULL 属性为NULL 不序列化
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        // 允许出现特殊字符和转义符
+        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
+        // 允许出现单引号
+        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+        // 字段保留,将null值转为""
+        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>()
+        {
+            @Override
+            public void serialize(Object o, JsonGenerator jsonGenerator,
+                                  SerializerProvider serializerProvider)
+                    throws IOException
+            {
+                jsonGenerator.writeString("");
+            }
+        });
+        return objectMapper;
+    }
+
+
+
+}

+ 49 - 0
src/main/java/com/example/demo/common/interceptor/TokenInterceptor.java

@@ -0,0 +1,49 @@
+package com.example.demo.common.interceptor;
+
+import com.example.demo.annotation.NonLoginRequired;
+import com.example.demo.common.utils.TokenUtils;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+@Component
+public class TokenInterceptor implements HandlerInterceptor {
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        // 如果不是映射到方法直接通过
+        if (!(handler instanceof HandlerMethod)) {
+            return true;
+        }
+
+        HandlerMethod handlerMethod = (HandlerMethod) handler;
+        // 检查是否有NonLoginRequired注解,有则不需要验证token
+        NonLoginRequired nonLoginRequired = handlerMethod.getMethodAnnotation(NonLoginRequired.class);
+        if (nonLoginRequired != null) {
+            return true;
+        }
+
+        // 从请求头中获取token
+        String token = request.getHeader("Authorization");
+        if (token != null && token.startsWith("Bearer ")) {
+            token = token.substring(7);
+        }
+
+        // 验证token
+        if (TokenUtils.isTokenValid(token, redisTemplate)) {
+            return true;
+        } else {
+            // token无效
+            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+            response.getWriter().write("{\"code\": 401, \"message\": \"未授权或token已过期\"}");
+            return false;
+        }
+    }
+} 

+ 10 - 0
src/main/java/com/example/demo/common/utils/RedisUtil.java

@@ -147,6 +147,16 @@ public class RedisUtil {
         }
     }
 
+    public boolean set(String key,Object value, long expiration) {
+        try {
+            redisTemplate.opsForValue().set(key,value, expiration);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
     /**
      * 普通缓存放入并设置时间
      *

+ 48 - 2
src/main/java/com/example/demo/common/utils/TokenUtils.java

@@ -5,17 +5,18 @@ import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.JwtBuilder;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import javax.crypto.spec.SecretKeySpec;
 import javax.xml.bind.DatatypeConverter;
 import java.security.Key;
 import java.util.Date;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 生成Token工具类
  */
 public class TokenUtils {
-
     /**
      * 签名秘钥
      */
@@ -29,7 +30,7 @@ public class TokenUtils {
     public static String createJwtToken(String id){
         String issuer = "www.futureading.com";
         String subject = "65532781@qq.com";
-        long ttlMillis = System.currentTimeMillis();
+        long ttlMillis = 24 * 60 * 60 * 1000; // 过期时间设置为24小时
         return createJwtToken(id, issuer, subject, ttlMillis);
     }
 
@@ -106,6 +107,51 @@ public class TokenUtils {
 
     }
 
+     /**
+     * 检查token是否在黑名单中(已被注销)
+     * @param token 待检查的token
+     * @param redisTemplate Redis模板
+     * @return true表示token在黑名单中(已被注销),false表示token不在黑名单中
+     */
+    public static boolean isTokenBlacklisted(String token, org.springframework.data.redis.core.RedisTemplate<String, Object> redisTemplate) {
+        String blacklistKey = "token:blacklist:" + token;
+        Object value = redisTemplate.opsForValue().get(blacklistKey);
+        return value != null;
+    }
+
+    /**
+     * 检查token是否有效(未过期且未被注销)
+     * @param token 待检查的token
+     * @param redisTemplate Redis模板
+     * @return true表示token有效,false表示token无效
+     */
+    public static boolean isTokenValid(String token, org.springframework.data.redis.core.RedisTemplate<String, Object> redisTemplate) {
+        if (token == null || token.isEmpty()) {
+            return false;
+        }
+        
+        try {
+            // 1. 验证JWT签名和格式
+            Claims claims = parseJWT(token);
+            if (claims == null) {
+                return false;
+            }
+            
+            // 2. 检查是否在黑名单中
+            if (isTokenBlacklisted(token, redisTemplate)) {
+                return false;
+            }
+            
+            // 3. 验证用户ID和Redis中存储的token是否匹配
+            String userId = claims.getId();
+            String storedToken = (String) redisTemplate.opsForValue().get("userToken:" + userId);
+            
+            return token.equals(storedToken);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
     public static void main(String[] args) {
         System.out.println(TokenUtils.createJwtToken("admin"));
     }

+ 3 - 0
src/main/java/com/example/demo/coupon/controller/UserCouponController.java

@@ -1,5 +1,6 @@
 package com.example.demo.coupon.controller;
 
+import com.example.demo.annotation.NonLoginRequired;
 import com.example.demo.coupon.dto.PageDto;
 import com.example.demo.coupon.dto.UserCouponDto;
 import com.example.demo.coupon.service.impl.CouponServiceImpl;
@@ -18,11 +19,13 @@ public class UserCouponController {
     private CouponServiceImpl couponService;
     @Autowired
     private UserCouponServiceImpl userCouponService;
+    @NonLoginRequired
     @RequestMapping("/getCouponList")
     public ResultVo getCouponList(@RequestBody PageDto dto, @RequestHeader("token") String token) {
         return couponService.getCouponList(dto,token);
     }
 
+    @NonLoginRequired
     @RequestMapping("/userGetCoupon")
     public ResultVo userGetCoupon(@RequestBody UserCouponDto dto, @RequestHeader("token")String token){
         return userCouponService.userGetCoupon(dto,token);

+ 5 - 0
src/main/java/com/example/demo/order/controller/OrderController.java

@@ -1,5 +1,6 @@
 package com.example.demo.order.controller;
 
+import com.example.demo.annotation.NonLoginRequired;
 import com.example.demo.order.dto.OrderInfoDto;
 import com.example.demo.order.dto.OrderInfoUpDto;
 import com.example.demo.order.service.impl.OrderInfoServiceImpl;
@@ -14,18 +15,22 @@ import javax.servlet.http.HttpServletRequest;
 public class OrderController {
     @Autowired
     private OrderInfoServiceImpl orderInfoService;
+    @NonLoginRequired
     @RequestMapping("/orderAdd")
     public ResultVo orderAdd(@RequestBody OrderInfoDto dto,@RequestHeader("token") String token){
         return orderInfoService.orderAdd(dto,token);
     }
+    @NonLoginRequired
     @RequestMapping("/orderUp")
     public ResultVo orderUp(@RequestBody OrderInfoUpDto dto, @RequestHeader("token") String token){
         return orderInfoService.orderUp(dto,token);
     }
+    @NonLoginRequired
     @RequestMapping("/orderGetList")
     public ResultVo orderGetList(@RequestHeader("token") String token){
         return orderInfoService.orderGetList(token);
     }
+    @NonLoginRequired
     @RequestMapping("/pay/{orderId}")
     public ResultVo orderPay(@PathVariable("orderId") Long orderId,
                             @RequestParam("paymentMethod") Integer paymentMethod,

+ 16 - 12
src/main/java/com/example/demo/product/controller/ProductController.java

@@ -1,5 +1,6 @@
 package com.example.demo.product.controller;
 
+import com.example.demo.annotation.NonLoginRequired;
 import com.example.demo.product.dto.TrainDto;
 import com.example.demo.product.service.impl.*;
 import com.example.demo.user.vo.ResultVo;
@@ -23,62 +24,65 @@ public class ProductController {
     private ProductTicketServiceImpl productTicketService;
     @Autowired
     private ProductTrainServiceImpl productTrainService;
-
+//    @NonLoginRequired
 //    @RequestMapping("/syncDataToEs")
 //    public ResultVo syncDataToEs() {
 //        return productService.syncDataToEs();
 //    }
-//
+
+//    @NonLoginRequired
 //    @RequestMapping("/getProductList")
 //    public ResultVo getProductList(@RequestHeader("token") String token) {
 //        return productService.getProductList(token);
 //    }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/flightSyncDataToEs")
 //    public ResultVo FlightSyncDataToEs(){
 //        return productFlightService.flightSyncDataToEs();
 //    }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/getFlightList")
 //    public ResultVo getFlightList(@RequestHeader("token") String token) {
 //        return productFlightService.getFlightList(token);
 //    }
+    @NonLoginRequired
     @RequestMapping("/getFlight")
     public ResultVo getFlight(@RequestHeader("token") String token,  String endCity, String endDate,String startCity, String startDate){
         return productFlightService.getFlight(token, endCity, endDate,startCity, startDate);
     }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/hotelSyncDataToEs")
 //    public ResultVo hotelSyncDataToEs(){
 //        return productHotelService.hotelSyncDataToEs();
 //    }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/getHotelList")
 //    public ResultVo getHotelList(@RequestHeader("token") String token) {
 //        return productHotelService.getHotelList(token);
 //    }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/ticketSyncDataToEs")
 //    public ResultVo ticketSyncDataToEs(){
 //        return productTicketService.ticketSyncDataToEs();
 //    }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/getTicketList")
 //    public ResultVo getTicketList(@RequestHeader("token") String token) {
 //        return productTicketService.getTicketList(token);
 //    }
 
     //查询火车票
+    @NonLoginRequired
     @RequestMapping("/getTrain")
-    public ResultVo getTrain(@RequestHeader("token") String token, HttpResponse response, @RequestBody TrainDto dto){
-        return productTrainService.getTrain(token,response,dto);
+    public ResultVo getTrain(@RequestHeader("token") String token, String start, String end, String date){
+        return productTrainService.getTrain(token, start, end, date);
     }
-
+//    @NonLoginRequired
 //    @RequestMapping("/trainSyncDataToEs")
 //    public ResultVo trainSyncDataToEs(){
 //        return productTrainService.trainSyncDataToEs();
 //    }
-//
+//    @NonLoginRequired
 //    @RequestMapping("/getTrainList")
 //    public ResultVo getTrainList(@RequestHeader("token") String token) {
 //        return productTrainService.getTrainList(token);

+ 1 - 1
src/main/java/com/example/demo/product/service/ProductTrainService.java

@@ -16,5 +16,5 @@ public interface ProductTrainService extends IService<ProductTrain> {
 //
 //    ResultVo getTrainList(String token);
 
-    ResultVo getTrain(String token, HttpResponse response, TrainDto dto);
+    ResultVo getTrain(String token,String start,String end,String date);
 }

+ 10 - 15
src/main/java/com/example/demo/product/service/impl/ProductFlightServiceImpl.java

@@ -1,5 +1,7 @@
 package com.example.demo.product.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.example.demo.common.utils.HttpUtils;
 import com.example.demo.product.domain.ProductFlight;
@@ -7,6 +9,7 @@ import com.example.demo.product.esmapper.ProductFlightEsMapper;
 import com.example.demo.product.service.ProductFlightService;
 import com.example.demo.product.dao.ProductFlightMapper;
 import com.example.demo.user.vo.ResultVo;
+import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.util.EntityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -92,23 +95,15 @@ public class ProductFlightServiceImpl extends ServiceImpl<ProductFlightMapper, P
              * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
              */
             HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
-            int statusCode = response.getStatusLine().getStatusCode();
-
-            // 检查HTTP状态码
-            if (statusCode != 200) {
-                return ResultVo.error("API请求失败,状态码:" + statusCode);
-            }
-
-            // 解析响应体
-            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
-            System.out.println("API原始响应:" + responseBody);
-
-            // 直接返回API的原始JSON数据(或按需解析后返回)
-            return ResultVo.success(responseBody);
-
+            System.out.println(response.toString());
+            HttpEntity entity = response.getEntity();
+            JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity, "utf-8"));
+            //获取response的body
+            //System.out.println(EntityUtils.toString(response.getEntity()));
+            return ResultVo.success(jsonObject);
         } catch (Exception e) {
             e.printStackTrace();
-            return ResultVo.error("调用航班API时出错:" + e.getMessage());
+            return ResultVo.error();
         }
     }
 }

+ 15 - 43
src/main/java/com/example/demo/product/service/impl/ProductTrainServiceImpl.java

@@ -2,7 +2,10 @@ package com.example.demo.product.service.impl;
 
 import cn.easyes.core.biz.EsPageInfo;
 import cn.easyes.core.conditions.LambdaEsQueryWrapper;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.common.utils.HttpUtils;
 import com.example.demo.common.utils.TokenUtils;
 import com.example.demo.product.domain.ProductTrain;
 import com.example.demo.product.dto.TrainDto;
@@ -11,6 +14,7 @@ import com.example.demo.product.esmapper.ProductTrainEsMapper;
 import com.example.demo.product.service.ProductTrainService;
 import com.example.demo.product.dao.ProductTrainMapper;
 import com.example.demo.user.vo.ResultVo;
+import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpPost;
@@ -20,10 +24,7 @@ import org.apache.http.util.EntityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
 * @author 徐乐
@@ -69,7 +70,7 @@ public class ProductTrainServiceImpl extends ServiceImpl<ProductTrainMapper, Pro
 //    }
 
     @Override
-    public ResultVo getTrain(String token, HttpResponse response, TrainDto dto) {
+    public ResultVo getTrain(String token,String start,String end,String date) {
         Long userId = TokenUtils.getUserId(token);
         if (userId==null){
             return ResultVo.error(101,"请先登录");
@@ -84,9 +85,9 @@ public class ProductTrainServiceImpl extends ServiceImpl<ProductTrainMapper, Pro
         //根据API的要求,定义相对应的Content-Type
         headers.put("Content-Type", "application/json; charset=UTF-8");
         Map<String, String> querys = new HashMap<String, String>();
-        querys.put("date", dto.getDate());
-        querys.put("end", dto.getEnd());
-        querys.put("start", dto.getStart());
+        querys.put("date", date);
+        querys.put("end", end);
+        querys.put("start", start);
 
 
         try {
@@ -99,46 +100,17 @@ public class ProductTrainServiceImpl extends ServiceImpl<ProductTrainMapper, Pro
              * 相应的依赖请参照
              * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
              */
-
+            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
             System.out.println(response.toString());
-            // 构建请求URI
-            URIBuilder uriBuilder = new URIBuilder(host + path);
-            for (Map.Entry<String, String> entry : querys.entrySet()) {
-                uriBuilder.addParameter(entry.getKey(), entry.getValue());
-            }
-
-            // 创建HTTP客户端和请求
-            HttpClient httpClient = HttpClients.createDefault();
-            HttpPost httpPost = new HttpPost(uriBuilder.build());
-
-            // 设置请求头
-            for (Map.Entry<String, String> entry : headers.entrySet()) {
-                httpPost.setHeader(entry.getKey(), entry.getValue());
-            }
-
-            // 执行请求
-            HttpResponse response1 = httpClient.execute(httpPost);
-
-            // 处理响应
-            if (response1.getStatusLine().getStatusCode() == 200) {
-                String responseBody = EntityUtils.toString(response1.getEntity(), "UTF-8");
-                System.out.println("API返回结果:");
-                System.out.println(responseBody);
-                return ResultVo.success(responseBody);
-            } else {
-                System.out.println("请求失败,状态码: " + response1.getStatusLine().getStatusCode());
-                System.out.println(EntityUtils.toString(response1.getEntity(), "UTF-8"));
-                return ResultVo.error(response1.getStatusLine().getStatusCode(),"请求失败");
-            }
+            //获取response的body
+            //System.out.println(EntityUtils.toString(response.getEntity(),"utf-8"));
+            HttpEntity entity = response.getEntity();
+            JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity, "utf-8"));
+            return ResultVo.success(jsonObject);
         } catch (Exception e) {
             e.printStackTrace();
             return ResultVo.error();
         }
-//            //获取response的body
-////            System.out.println(EntityUtils.toString(response.getEntity(),"utf-8"));
-//        } catch (Exception e) {
-//            e.printStackTrace();
-//        }
     }
 }
 

+ 5 - 2
src/main/java/com/example/demo/scenic_spot/controller/ScenicSpotController.java

@@ -1,5 +1,6 @@
 package com.example.demo.scenic_spot.controller;
 
+import com.example.demo.annotation.NonLoginRequired;
 import com.example.demo.scenic_spot.dto.ScenicSpotDto;
 import com.example.demo.scenic_spot.service.impl.ScenicSpotServiceImpl;
 import com.example.demo.user.vo.ResultVo;
@@ -16,13 +17,15 @@ public class ScenicSpotController {
     private ScenicSpotServiceImpl scenicSpotService;
     private static final Logger logger = LoggerFactory.getLogger(ScenicSpotController.class);
 
+    @NonLoginRequired
     @RequestMapping("/syncDataToEs")
     public ResultVo syncDataToEs() {
         return scenicSpotService.syncDataToEs();
     }
+    @NonLoginRequired
     @RequestMapping("/getScenicSpotList")
-    public ResultVo getScenicSpotList(@RequestHeader("token") String token, HttpResponse response, String keyword) {
+    public ResultVo getScenicSpotList(@RequestHeader("token") String token, String keyword) {
         logger.info("获取景点信息列表");
-        return scenicSpotService.getScenicSpotList(token,response,keyword);
+        return scenicSpotService.getScenicSpotList(token,keyword);
     }
 }

+ 1 - 1
src/main/java/com/example/demo/scenic_spot/service/ScenicSpotService.java

@@ -15,5 +15,5 @@ public interface ScenicSpotService extends IService<ScenicSpot> {
 
     ResultVo syncDataToEs();
 
-    ResultVo getScenicSpotList(String token, HttpResponse response, String keyword);
+    ResultVo getScenicSpotList(String token, String keyword);
 }

+ 7 - 14
src/main/java/com/example/demo/scenic_spot/service/impl/ScenicSpotServiceImpl.java

@@ -84,7 +84,7 @@ public class ScenicSpotServiceImpl extends ServiceImpl<ScenicSpotMapper, ScenicS
     }
 
     @Override
-    public ResultVo getScenicSpotList(String token, HttpResponse response, String keyword) {
+    public ResultVo getScenicSpotList(String token, String keyword) {
         Long userId = TokenUtils.getUserId(token);
         if (userId==null){
             return ResultVo.error(101,"请先登录");
@@ -114,20 +114,13 @@ public class ScenicSpotServiceImpl extends ServiceImpl<ScenicSpotMapper, ScenicS
              * 相应的依赖请参照
              * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
              */
-            HttpResponse response1 = HttpUtils.doGet(host, path, method, headers, querys);
-            System.out.println(response1.toString());
+            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
+            System.out.println(response.toString());
+            HttpEntity entity = response.getEntity();
+            JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity, "utf-8"));
             //获取response的body
-//            System.out.println(EntityUtils.toString(response.getEntity()));
-            // 获取响应体内容,注意处理异常
-            String responseBody = EntityUtils.toString(response1.getEntity(), "UTF-8");
-            // 打印响应体,方便调试查看
-            System.out.println("接口返回数据:" + responseBody);
-
-            // 解析响应体(这里假设返回的是 JSON 格式,根据实际情况调整解析逻辑)
-            // 如果是 JSON 字符串,转成 JSONObject 或者 Java 实体类
-            JSONObject resultJson = JSON.parseObject(responseBody);
-            // 假设你的 ResultVo 的 obj 字段可以接收解析后的 JSON 数据或者 Map 等
-            return ResultVo.success(resultJson);
+            //System.out.println(EntityUtils.toString(response.getEntity()));
+            return ResultVo.success(jsonObject);
         } catch (Exception e) {
             e.printStackTrace();
             return ResultVo.error();

+ 29 - 9
src/main/java/com/example/demo/user/controller/UserController.java

@@ -1,11 +1,8 @@
 package com.example.demo.user.controller;
 
+import com.example.demo.annotation.NonLoginRequired;
 import com.example.demo.common.utils.RedisClient;
-import com.example.demo.user.dto.CollectDto;
-import com.example.demo.user.dto.LoginDto;
-import com.example.demo.user.dto.PhoneDto;
-import com.example.demo.user.dto.UserDto;
-import com.example.demo.user.service.UserService;
+import com.example.demo.user.dto.*;
 import com.example.demo.user.service.ValidateCodeService;
 import com.example.demo.user.service.impl.UserFavoriteServiceImpl;
 import com.example.demo.user.service.impl.UserServiceImpl;
@@ -29,31 +26,34 @@ public class UserController {
     @Autowired
     private RedisClient redisClient;
 
+    @NonLoginRequired
     @RequestMapping("/register")
-    public ResultVo register(@RequestBody UserDto dto){
+    public ResultVo register(@RequestBody RegisterDto dto){
         return userService.register(dto);
     }
 
+    @NonLoginRequired
     @RequestMapping("/login")
     public ResultVo login(@RequestBody LoginDto dto){
         return userService.login(dto);
     }
-
+    @NonLoginRequired
     @RequestMapping("/collect")
     public ResultVo collect(@RequestBody CollectDto dto, @RequestHeader("token") String token){
         return userFavoriteService.collect(dto,token);
     }
-
+    @NonLoginRequired
     @RequestMapping("/delCollect")
     public ResultVo delCollect(Integer targetId, @RequestHeader("token") String token){
         return userFavoriteService.delCollect(targetId,token);
     }
-
+    @NonLoginRequired
     @RequestMapping("/selCollect")
     public ResultVo selCollect(@RequestHeader("token") String token){
         return userFavoriteService.selCollect(token);
     }
 
+    @NonLoginRequired
     @RequestMapping("/phoneLogin")
     public ResultVo phoneLogin(@RequestBody PhoneDto dto){
         return userService.phoneLogin(dto);
@@ -64,6 +64,7 @@ public class UserController {
      * @param phone
      * @return
      */
+    @NonLoginRequired
     @RequestMapping("/send4Order")
     public ResultVo send4Order(@RequestParam("phone") String phone) {
         Integer code = validateCodeService.send4Order(phone);
@@ -73,4 +74,23 @@ public class UserController {
         System.out.println("您的验证码为:------"+code);
         return ResultVo.success("验证码发送成功");
     }
+
+    @NonLoginRequired
+    @RequestMapping("/forget")
+    public ResultVo forget(@RequestBody RegisterDto dto){
+        return userService.forget(dto);
+    }
+
+    @NonLoginRequired
+    @RequestMapping("/logout")
+    public ResultVo logout(@RequestHeader("token") String token){
+        return userService.logout(token);
+    }
+
+    //完善用户信息
+    @NonLoginRequired
+    @RequestMapping("/perfect")
+    public ResultVo perfect(@RequestHeader("token") String token,@RequestBody PerfectDto dto){
+        return userService.perfect(token,dto);
+    }
 }

+ 10 - 0
src/main/java/com/example/demo/user/dto/PerfectDto.java

@@ -0,0 +1,10 @@
+package com.example.demo.user.dto;
+
+import lombok.Data;
+
+@Data
+public class PerfectDto {
+    private String username;
+    private String email;
+    private String avatar;
+}

+ 3 - 1
src/main/java/com/example/demo/user/dto/UserDto.java → src/main/java/com/example/demo/user/dto/RegisterDto.java

@@ -3,12 +3,14 @@ package com.example.demo.user.dto;
 import lombok.Data;
 
 @Data
-public class UserDto {
+public class RegisterDto {
     /**
      * 用户手机号
      */
     private String phone;
 
+    private String code;
+
     /**
      * 加密后的密码
      */

+ 9 - 2
src/main/java/com/example/demo/user/service/UserService.java

@@ -3,8 +3,9 @@ package com.example.demo.user.service;
 import com.example.demo.user.domain.User;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.example.demo.user.dto.LoginDto;
+import com.example.demo.user.dto.PerfectDto;
 import com.example.demo.user.dto.PhoneDto;
-import com.example.demo.user.dto.UserDto;
+import com.example.demo.user.dto.RegisterDto;
 import com.example.demo.user.vo.ResultVo;
 
 /**
@@ -14,9 +15,15 @@ import com.example.demo.user.vo.ResultVo;
 */
 public interface UserService extends IService<User> {
 
-    ResultVo register(UserDto dto);
+    ResultVo register(RegisterDto dto);
 
     ResultVo login(LoginDto dto);
 
     ResultVo phoneLogin(PhoneDto dto);
+
+    ResultVo forget(RegisterDto dto);
+
+    ResultVo logout(String token);
+
+    ResultVo perfect(String token,PerfectDto dto);
 }

+ 102 - 11
src/main/java/com/example/demo/user/service/impl/UserServiceImpl.java

@@ -8,8 +8,9 @@ import com.example.demo.common.utils.RedisClient;
 import com.example.demo.common.utils.TokenUtils;
 import com.example.demo.user.domain.User;
 import com.example.demo.user.dto.LoginDto;
+import com.example.demo.user.dto.PerfectDto;
 import com.example.demo.user.dto.PhoneDto;
-import com.example.demo.user.dto.UserDto;
+import com.example.demo.user.dto.RegisterDto;
 import com.example.demo.user.service.UserService;
 import com.example.demo.user.dao.UserMapper;
 import com.example.demo.user.vo.ResultVo;
@@ -20,8 +21,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
-import java.util.HashMap;
-import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
@@ -44,7 +43,19 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
     @Autowired
     private RedisClient redisClient;
     @Override
-    public ResultVo register(UserDto dto) {
+    public ResultVo register(RegisterDto dto) {
+        // 获取验证码
+        Object code = getVerificationCode(dto.getPhone());
+        if (code == null) {
+            return ResultVo.error(201, "验证码已过期");
+        }
+        String codeStr = String.valueOf(code);
+        String userCode = dto.getCode();
+        if (!codeStr.equals(userCode)) {
+            return ResultVo.error(202, "验证码错误");
+        }
+        // 删除已使用的验证码
+        deleteVerificationCode(dto.getPhone());
         QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
         userQueryWrapper.eq("phone", dto.getPhone());
         log.info("加锁");
@@ -71,6 +82,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
             String md5Password = Md5Util.MD5(uuid + password);
             u.setPassword(md5Password);
             u.setPhone(dto.getPhone());
+            u.setEmail(u.getPhone()+"@example.com");
             userMapper.insert(u);
             return ResultVo.success("注册成功");
         } catch (Exception e) {
@@ -119,7 +131,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
         String encryptedPassword = Md5Util.MD5(salt + password);
         if (encryptedPassword.equals(user.getPassword())){
             String token = TokenUtils.createJwtToken(user.getId().toString());
-            redisTemplate.opsForValue().set("userToken:",token);
+            // 使用用户ID作为键名的一部分
+            redisTemplate.opsForValue().set("userToken:" + user.getId(), token);
+            redisTemplate.expire("userToken:" + user.getId(), 24, TimeUnit.HOURS); // 设置24小时过期
             return ResultVo.success(token);
         }
         return ResultVo.error("用户名或密码有误");
@@ -133,24 +147,24 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
         }
 
         // 获取验证码
-        Integer collect = (Integer) getVerificationCode(dto.getPhone());
-        if (collect == null) {
+        Integer code = (Integer) getVerificationCode(dto.getPhone());
+        if (code == null) {
 //            logger.info("手机号 {} 验证码已过期", dto.getPhone());
             return ResultVo.error(201, "验证码已过期");
         }
 
         // 验证验证码
-        String codeStr = String.valueOf(collect);
+        String codeStr = String.valueOf(code);
         String userCode = dto.getCode();
         if (userCode == null ||!userCode.matches("\\d{6}")) {
 //            logger.info("手机号 {} 输入的验证码格式错误", dto.getPhone());
-            return ResultVo.error(201, "验证码格式错误");
+            return ResultVo.error(203, "验证码格式错误");
         }
 
         if (!codeStr.equals(userCode)) {
 //            logger.info("手机号 {} 验证码错误,Redis: {}, 用户输入: {}",
 //                    dto.getPhone(), codeStr, userCode);
-            return ResultVo.error(201, "验证码错误");
+            return ResultVo.error(202, "验证码错误");
         }
 
         // 验证通过后删除验证码
@@ -177,9 +191,86 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
 //        redisClient.set("uid",  user.getId());
 //        redisClient.expire("uid", 60*60);
         String token = TokenUtils.createJwtToken(user.getId().toString());
-        redisTemplate.opsForValue().set("userToken:",token);
+        // 使用用户ID作为键名的一部分
+        redisTemplate.opsForValue().set("userToken:" + user.getId(), token);
+        redisTemplate.expire("userToken:" + user.getId(), 24, TimeUnit.HOURS); // 设置24小时过期
         return ResultVo.success(token);
     }
+
+    @Override
+    public ResultVo forget(RegisterDto dto) {
+        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("phone",dto.getPhone());
+        User user = userMapper.selectOne(queryWrapper);
+        if (user==null){
+            return ResultVo.error("用户不存在");
+        }
+        // 获取验证码
+        Object code = getVerificationCode(dto.getPhone());
+        if (code == null) {
+            return ResultVo.error(201, "验证码已过期");
+        }
+        String codeStr = String.valueOf(code);
+        String userCode = dto.getCode();
+        if (!codeStr.equals(userCode)) {
+            return ResultVo.error(202, "验证码错误");
+        }
+        // 删除已使用的验证码
+        deleteVerificationCode(dto.getPhone());
+        //生成盐值
+        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+        user.setSalt(uuid);
+        //获取密码
+        String password = dto.getPassword();
+        //加密
+        String md5Password = Md5Util.MD5(uuid + password);
+        user.setPassword(md5Password);
+        userMapper.updateById(user);
+        return ResultVo.success("找回成功");
+    }
+
+    @Override
+    public ResultVo logout(String token) {
+        if (token == null || token.isEmpty()) {
+            return ResultVo.error("无效的token");
+        }
+        
+        try {
+            // 解析token获取用户ID
+            Long userId = TokenUtils.getUserId(token);
+            if (userId == null) {
+                return ResultVo.error("无效的token");
+            }
+            
+            // 从Redis删除token
+            redisTemplate.delete("userToken:" + userId);
+            
+            // 可以设置token黑名单,防止已注销的token被再次使用
+            String blacklistKey = "token:blacklist:" + token;
+            redisTemplate.opsForValue().set(blacklistKey, "1");
+            redisTemplate.expire(blacklistKey, 24, TimeUnit.HOURS); // 设置黑名单24小时过期
+            
+            log.info("用户{}已成功退出登录", userId);
+            return ResultVo.success("退出成功");
+        } catch (Exception e) {
+            log.error("注销失败", e);
+            return ResultVo.error("注销失败,请稍后再试");
+        }
+    }
+
+    @Override
+    public ResultVo perfect(String token,PerfectDto dto) {
+        Long userId = TokenUtils.getUserId(token);
+        if (userId==null){
+            return ResultVo.error("用户不存在");
+        }
+        User user = userMapper.selectById(userId);
+        user.setUsername(dto.getUsername());
+        user.setEmail(dto.getEmail());
+        user.setAvatar(dto.getAvatar());
+        userMapper.updateById(user);
+        return ResultVo.success("完善用户信息成功");
+    }
 }
 
 

+ 2 - 2
src/main/java/com/example/demo/user/service/impl/ValidateCodeServiceImpl.java

@@ -13,8 +13,8 @@ public class ValidateCodeServiceImpl implements ValidateCodeService {
         String substring = phone.substring(2, 8);
         Random random = new Random();
         int j = random.nextInt(Integer.valueOf(substring));
-        if (j < 1000) {
-            j += 1000;
+        if (j < 100000) {
+            j += 100000;
         }
         return j;
     }