Browse Source

Merge remote-tracking branch 'origin/main' into main

# Conflicts:
#	edu-travel-service/edu-travel-service-commodity/src/main/java/edu/travel/commodity/constant/BaseConstant.java
zhangwei 4 days ago
parent
commit
8f889410b4
46 changed files with 1394 additions and 39 deletions
  1. 21 1
      edu-travel-adapter/edu-travel-adapter-upload/src/main/java/edu/travel/adapter/service/upload/UploadAdapter.java
  2. 5 0
      edu-travel-common/edu-travel-common-core/pom.xml
  3. 40 0
      edu-travel-remote/edu-travel-remote-tenant/src/main/java/edu/travel/remote/feign/mode/dto/tenant/BannerDto.java
  4. 18 0
      edu-travel-remote/edu-travel-remote-tenant/src/main/java/edu/travel/remote/feign/mode/romote/ShopBannerRemoteController.java
  5. 6 0
      edu-travel-remote/edu-travel-remote-upload/pom.xml
  6. 9 1
      edu-travel-remote/edu-travel-remote-upload/src/main/java/edu/travel/remote/upload/UploadRemoteController.java
  7. 56 0
      edu-travel-remote/edu-travel-remote-upload/src/main/java/edu/travel/remote/upload/vo/EduFileBlobVo.java
  8. 50 0
      edu-travel-remote/edu-travel-remote-upload/src/main/java/edu/travel/remote/upload/vo/EduFileVo.java
  9. 6 0
      edu-travel-service/edu-travel-service-commodity/src/main/java/edu/travel/commodity/constant/BaseConstant.java
  10. 1 2
      edu-travel-service/edu-travel-service-commodity/src/main/java/edu/travel/commodity/service/impl/ShopOpinionServiceImpl.java
  11. 4 4
      edu-travel-service/edu-travel-service-country/src/main/java/edu/travel/country/web/BaseCountryController.java
  12. 4 4
      edu-travel-service/edu-travel-service-country/src/main/java/edu/travel/country/web/BaseCountryServeController.java
  13. 7 2
      edu-travel-service/edu-travel-service-education/src/main/java/edu/travel/education/web/HappyEntryController.java
  14. 22 11
      edu-travel-service/edu-travel-service-education/src/main/resources/mapper/HappyEntryMapper.xml
  15. 6 0
      edu-travel-service/edu-travel-service-tenement/pom.xml
  16. 43 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/constant/BaseConstant.java
  17. 19 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/constant/RedisKey.java
  18. 5 1
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/service/ShopBannerService.java
  19. 57 2
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/service/impl/ShopBannerServiceImpl.java
  20. 17 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/FIleUtil.java
  21. 13 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/IdUtils.java
  22. 19 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/ObjectUtils.java
  23. 28 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/PageUtil.java
  24. 36 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/RedisUtil.java
  25. 26 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/StringUtil.java
  26. 16 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/TokenData.java
  27. 161 0
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/TreeUtils.java
  28. 63 5
      edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/web/ShopBannerController.java
  29. 31 0
      edu-travel-service/edu-travel-service-tomcat/pom.xml
  30. 17 0
      edu-travel-service/edu-travel-service-tomcat/src/main/java/edu/travel/App.java
  31. 75 1
      edu-travel-service/edu-travel-service-upload/src/main/java/edu/travel/upload/web/UploadController.java
  32. 4 4
      edu-travel-service/edu-travel-service-upload/src/main/resources/bootstrap-dev.yml
  33. 1 1
      edu-travel-service/edu-travel-service-upload/src/main/resources/bootstrap.yml
  34. 135 0
      edu-travel-service/edu-travel-service-ws/pom.xml
  35. 17 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/WsApplication.java
  36. 32 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/MyAccessDeniedHandler.java
  37. 31 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/MyAuthenticationEntryPoint.java
  38. 39 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/ResourceServerConfig.java
  39. 48 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/TokenConfig.java
  40. 21 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/WebSecurityConfig.java
  41. 23 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/WebServerFactoryConfigs.java
  42. 25 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/WebSocketAutoConfig.java
  43. 61 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/filter/TokenAuthenticationFilter.java
  44. 12 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/handle/TravelMessageHandler.java
  45. 62 0
      edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/interceptor/SystemMessageInterceptor.java
  46. 2 0
      edu-travel-service/pom.xml

+ 21 - 1
edu-travel-adapter/edu-travel-adapter-upload/src/main/java/edu/travel/adapter/service/upload/UploadAdapter.java

@@ -5,10 +5,10 @@ import edu.travel.adapter.annotation.AdapterAnnotation;
 import edu.travel.remote.upload.UploadRemoteController;
 import edu.travel.remote.upload.dto.EduFileBlobDTO;
 import edu.travel.remote.upload.dto.EduFileDTO;
+import edu.travel.remote.upload.vo.EduFileVo;
 import edu.travel.rpc.RPCBaseResponse;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
@@ -48,4 +48,24 @@ public class UploadAdapter  {
         RPCBaseResponse rpcBaseResponse = uploadRemoteController.uploadFile(JSON.toJSONString(eduFileDTO),file);
         return rpcBaseResponse;
     }
+    @AdapterAnnotation
+    public RPCBaseResponse<EduFileVo> getFormId(String id) {
+        return uploadRemoteController.getFormId(id);
+    }
+    @AdapterAnnotation
+    public RPCBaseResponse<EduFileVo> updateTargetFormId(EduFileDTO entity) {
+        return uploadRemoteController.updateTargetFormId(entity);
+    }
+    @AdapterAnnotation
+    public RPCBaseResponse<EduFileVo> saveFormTarget(EduFileDTO entity) {
+        return uploadRemoteController.saveFormTarget(entity);
+    }
+    @AdapterAnnotation
+    public RPCBaseResponse<EduFileVo> deleteTargetFormId(List<String> ids) {
+        return uploadRemoteController.deleteTargetFormId(ids);
+    }
+    @AdapterAnnotation
+    public RPCBaseResponse<List<EduFileVo>> getAllForm() {
+        return uploadRemoteController.getAllForm();
+    }
 }

+ 5 - 0
edu-travel-common/edu-travel-common-core/pom.xml

@@ -19,6 +19,11 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
             <scope>provided</scope>

+ 40 - 0
edu-travel-remote/edu-travel-remote-tenant/src/main/java/edu/travel/remote/feign/mode/dto/tenant/BannerDto.java

@@ -0,0 +1,40 @@
+package edu.travel.remote.feign.mode.dto.tenant;
+
+import lombok.Data;
+
+@Data
+public class BannerDto {
+    /**
+     * 轮播图ID
+     */
+    private String id;
+
+    /**
+     * 图片/视频
+     */
+    private String url;
+
+    /**
+     * 判断图片/视频,默认0,0图片,1视频
+     */
+    private Integer urlType;
+
+    /**
+     * 名称
+     */
+    private String content;
+    /**
+     * 国家
+     */
+    private String countryId;
+
+    /**
+     * 链接地址
+     */
+    private String linkUrl;
+    /**
+     * mode 0 首页轮播图
+     */
+    private String mode;
+
+}

+ 18 - 0
edu-travel-remote/edu-travel-remote-tenant/src/main/java/edu/travel/remote/feign/mode/romote/ShopBannerRemoteController.java

@@ -0,0 +1,18 @@
+package edu.travel.remote.feign.mode.romote;
+
+import edu.travel.remote.base.RemoteBaseController;
+import edu.travel.remote.feign.mode.dto.tenant.BannerDto;
+import edu.travel.remote.feign.mode.vo.banner.BannerVo;
+import edu.travel.rpc.RPCBaseResponse;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.util.List;
+
+import static edu.travel.rpc.RPCBaseResponse.success;
+
+@FeignClient(path = "/shopBanner", name = "tenant-dev")
+public interface ShopBannerRemoteController extends RemoteBaseController<BannerVo, BannerDto> {
+    @GetMapping("/getBanner")
+    public RPCBaseResponse<List<BannerVo>> getBanner(BannerDto banner);
+}

+ 6 - 0
edu-travel-remote/edu-travel-remote-upload/pom.xml

@@ -28,5 +28,11 @@
             <artifactId>edu-travel-common-openfeign</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-remote-base</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 </project>

+ 9 - 1
edu-travel-remote/edu-travel-remote-upload/src/main/java/edu/travel/remote/upload/UploadRemoteController.java

@@ -1,7 +1,9 @@
 package edu.travel.remote.upload;
 
+import edu.travel.remote.base.RemoteBaseController;
 import edu.travel.remote.upload.dto.EduFileBlobDTO;
 import edu.travel.remote.upload.dto.EduFileDTO;
+import edu.travel.remote.upload.vo.EduFileVo;
 import edu.travel.rpc.RPCBaseResponse;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.http.MediaType;
@@ -13,7 +15,7 @@ import java.io.Serializable;
 import java.util.List;
 
 @FeignClient(name = "upload-dev",path = "/upload")
-public interface UploadRemoteController {
+public interface UploadRemoteController extends RemoteBaseController<EduFileVo, EduFileDTO> {
     @PostMapping("/init")
     public RPCBaseResponse<String> initializeUpload();
     /**
@@ -55,4 +57,10 @@ public interface UploadRemoteController {
      */
     @PostMapping(value = "/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     RPCBaseResponse uploadFile(@RequestParam("eduFileDTO") String dto,@RequestPart("file") MultipartFile file) throws IOException;
+
+    /**
+     * 通过id获取文件
+     */
+    @GetMapping("/getFormId")
+    RPCBaseResponse<EduFileVo> getFormId(String id);
 }

+ 56 - 0
edu-travel-remote/edu-travel-remote-upload/src/main/java/edu/travel/remote/upload/vo/EduFileBlobVo.java

@@ -0,0 +1,56 @@
+package edu.travel.remote.upload.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import edu.travel.entity.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName(value = "edu.edu_file_blob")
+public class EduFileBlobVo extends BaseEntity {
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    /**
+     * 分片名字
+     */
+    @TableField(value = "blob_name")
+    private String blobName;
+
+    /**
+     * 传了第几片
+     */
+    @TableField(value = "blob_num")
+    private Integer blobNum;
+
+    /**
+     * 分片地址
+     */
+    @TableField(value = "blob_path")
+    private String blobPath;
+
+    /**
+     * 分片md5
+     */
+    @TableField(value = "blob_md5")
+    private String blobMd5;
+
+    /**
+     * 文件md5
+     */
+    @TableField(value = "file_md5")
+    private String fileMd5;
+
+    /**
+     * 总共多少片
+     */
+    @TableField(value = "total_count")
+    private Integer totalCount;
+
+}

+ 50 - 0
edu-travel-remote/edu-travel-remote-upload/src/main/java/edu/travel/remote/upload/vo/EduFileVo.java

@@ -0,0 +1,50 @@
+package edu.travel.remote.upload.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import edu.travel.entity.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName(value = "edu.edu_file")
+public class EduFileVo extends BaseEntity {
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    /**
+     * 文件md5
+     */
+    @TableField(value = "file_md5")
+    private String fileMd5;
+
+    /**
+     * 文件名
+     */
+    @TableField(value = "file_name")
+    private String fileName;
+
+    /**
+     * 文件系统名
+     */
+    @TableField(value = "file_sys_name")
+    private String fileSysName;
+
+    /**
+     * 文件路径
+     */
+    @TableField(value = "file_path")
+    private String filePath;
+
+    /**
+     * 文件类型
+     */
+    @TableField(value = "file_type")
+    private String fileType;
+
+}

+ 6 - 0
edu-travel-service/edu-travel-service-commodity/src/main/java/edu/travel/commodity/constant/BaseConstant.java

@@ -39,6 +39,12 @@ public class BaseConstant {
     public static Set<String> getProductImageTypes() {
         return PRODUCT_IMAGE_TYPES;
     }
+    /**
+     * 获取banner 图片类型
+     */
+    public static Set<String> getBannerImageTypes() {
+        return PRODUCT_IMAGE_TYPES;
+    }
     public static Set<String> getOpinionFileTypes() {
         return OPINION_FILE_TYPES;
     }

+ 1 - 2
edu-travel-service/edu-travel-service-commodity/src/main/java/edu/travel/commodity/service/impl/ShopOpinionServiceImpl.java

@@ -30,7 +30,7 @@ public class ShopOpinionServiceImpl extends SysServiceImpl<ShopOpinionMapper, Sh
     @Override
     public RPCBaseResponse<IPage<ShopOpinionVo>> getAllFormPage(ShopOpinionDto dto) {
         // 创建分页对象
-        Page<ShopOpinionVo> shopOpinionPage = new Page<>(dto.getCurrentPage(), dto.getPageSize());
+//        Page<ShopOpinionVo> shopOpinionPage = new Page<>(dto.getCurrentPage(), dto.getPageSize());
 
         // 查询意见数据,确保返回类型正确
         List<ShopOpinionVo> shopOpinions = shopOpinionMapper.selectOpinionsWithCountry(
@@ -79,7 +79,6 @@ public class ShopOpinionServiceImpl extends SysServiceImpl<ShopOpinionMapper, Sh
         ShopOpinionVo vo = new ShopOpinionVo();
         vo.setId(shopOpinion.getId());
         vo.setCountryId(shopOpinion.getCountryId());
-        // 其他字段的设置...
         return vo;
     }
     //查询国家信息

+ 4 - 4
edu-travel-service/edu-travel-service-country/src/main/java/edu/travel/country/web/BaseCountryController.java

@@ -64,7 +64,7 @@ public class BaseCountryController extends BaseController<BaseCountry> implement
      * 更新国家信息
      */
     @Override
-    @PostMapping("/updateCountryFormId")
+    @PostMapping("/updateTargetFormId")
     public RPCBaseResponse<BaseCountryVo> updateTargetFormId(@RequestBody BaseCountryDto entity) {
         BaseCountry baseCountry = new BaseCountry();
         BeanUtils.copyProperties(entity, baseCountry);
@@ -78,7 +78,7 @@ public class BaseCountryController extends BaseController<BaseCountry> implement
      * 新增国家信息
      */
     @Override
-    @PostMapping("/saveCountryForm")
+    @PostMapping("/saveFormTarget")
     public RPCBaseResponse<BaseCountryVo> saveFormTarget(@RequestBody BaseCountryDto entity) {
         BaseCountry baseCountry = new BaseCountry();
         BeanUtils.copyProperties(entity, baseCountry);
@@ -92,7 +92,7 @@ public class BaseCountryController extends BaseController<BaseCountry> implement
      * 删除国家
      */
     @Override
-    @PostMapping("/deleteCountryFormId")
+    @PostMapping("/deleteTargetFormId")
     public RPCBaseResponse<BaseCountryVo> deleteTargetFormId(@RequestBody List<String> ids) {
         RPCBaseResponse<BaseCountry> baseCountryRPCBaseResponse = super.deleteTargetById(ids);
         RPCBaseResponse<BaseCountryVo> baseCountryVoRPCBaseResponse = new RPCBaseResponse<>();
@@ -104,7 +104,7 @@ public class BaseCountryController extends BaseController<BaseCountry> implement
      * 获取国家表
      */
     @Override
-    @GetMapping("/CountrylistForm")
+    @GetMapping("/getAllForm")
     public RPCBaseResponse<List<BaseCountryVo>> getAllForm() {
         RPCBaseResponse<List<BaseCountry>> listRPCBaseResponse = super.listAll();
         RPCBaseResponse<List<BaseCountryVo>> baseCountryVoRPCBaseResponse = new RPCBaseResponse<>();

+ 4 - 4
edu-travel-service/edu-travel-service-country/src/main/java/edu/travel/country/web/BaseCountryServeController.java

@@ -68,7 +68,7 @@ public class BaseCountryServeController extends BaseController<BaseCountryServe>
      * @return
      */
     @Override
-    @PostMapping("/updateFormId")
+    @PostMapping("/updateTargetFormId")
     public RPCBaseResponse<BaseCountryServeVo> updateTargetFormId(@RequestBody BaseCountryServeDto entity) {
         BaseCountryServe baseCountryServe = new BaseCountryServe();
         BeanUtils.copyProperties(entity, baseCountryServe);
@@ -85,7 +85,7 @@ public class BaseCountryServeController extends BaseController<BaseCountryServe>
      * @return
      */
     @Override
-    @PostMapping("/saveForm")
+    @PostMapping("/saveFormTarget")
     public RPCBaseResponse<BaseCountryServeVo> saveFormTarget(@RequestBody BaseCountryServeDto entity) {
         BaseCountryServe baseCountryServe = new BaseCountryServe();
         BeanUtils.copyProperties(entity, baseCountryServe);
@@ -102,7 +102,7 @@ public class BaseCountryServeController extends BaseController<BaseCountryServe>
      * @return
      */
     @Override
-    @PostMapping("/deleteFormId")
+    @PostMapping("/deleteTargetFormId")
     public RPCBaseResponse<BaseCountryServeVo> deleteTargetFormId(@RequestBody List<String> ids) {
         RPCBaseResponse<BaseCountryServe> baseCountryServeRPCBaseResponse = super.deleteTargetById(ids);
         RPCBaseResponse<BaseCountryServeVo> baseCountryServeVoRPCBaseResponse = new RPCBaseResponse<>();
@@ -116,7 +116,7 @@ public class BaseCountryServeController extends BaseController<BaseCountryServe>
      * @return
      */
     @Override
-    @GetMapping("/listForm")
+    @GetMapping("/getAllForm")
     public RPCBaseResponse<List<BaseCountryServeVo>> getAllForm() {
         RPCBaseResponse<List<BaseCountryServe>> listRPCBaseResponse = super.listAll();
         RPCBaseResponse<List<BaseCountryServeVo>> baseCountryServeVoRPCBaseResponse = new RPCBaseResponse<>();

+ 7 - 2
edu-travel-service/edu-travel-service-education/src/main/java/edu/travel/education/web/HappyEntryController.java

@@ -1,6 +1,7 @@
 package edu.travel.education.web;
 import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import edu.travel.education.dto.AddHappyEntryDto;
 import edu.travel.education.dto.HappyEntryDto;
 import edu.travel.education.entity.HappyEntry;
@@ -11,6 +12,7 @@ import edu.travel.resp.PageResponse;
 import edu.travel.rpc.RPCBaseResponse;
 import edu.travel.rpc.RPCPageResponse;
 import edu.travel.web.BaseController;
+import org.springframework.beans.BeanUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -100,10 +102,13 @@ public class HappyEntryController extends BaseController<HappyEntry> {
      */
     @GetMapping("/listPageHappyEntry")
     @PreAuthorize("hasRole('超级管理员')")
-    public RPCPageResponse<List<HappyEntryVo>> listPageHappyEntry(HappyEntryDto happyEntryDto){
+    public RPCBaseResponse<Page<HappyEntryVo>> listPageHappyEntry(HappyEntryDto happyEntryDto){
         IPage<HappyEntry> page = happyEntryService.listPageHappyEntry(happyEntryDto);
         List<HappyEntryVo> happyEntryVos = BeanUtil.copyToList(page.getRecords(), HappyEntryVo.class);
-        return  RPCPageResponse.success("200",happyEntryVos,(int) page.getTotal(),(int)page.getSize(),(int)page.getCurrent());
+        Page<HappyEntryVo> target = new Page<HappyEntryVo>();
+        BeanUtils.copyProperties(page, target);
+        target.setRecords(happyEntryVos);
+        return new RPCBaseResponse<>(200,"success",target);
     }
 
 }

+ 22 - 11
edu-travel-service/edu-travel-service-education/src/main/resources/mapper/HappyEntryMapper.xml

@@ -10,7 +10,8 @@
     <result column="phone" jdbcType="VARCHAR" property="phone" />
     <result column="area_code" jdbcType="VARCHAR" property="areaCode" />
     <result column="course_type" jdbcType="INTEGER" property="courseType" />
-    <result column="age" jdbcType="INTEGER" property="age" />
+    <result column="min_age" jdbcType="INTEGER" property="minAge" />
+    <result column="max_age" jdbcType="INTEGER" property="maxAge" />
     <result column="email" jdbcType="VARCHAR" property="email" />
     <result column="project" jdbcType="VARCHAR" property="project" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
@@ -21,7 +22,7 @@
   </resultMap>
   <sql id="Base_Column_List">
     <!--@mbg.generated-->
-    id, surname, `name`, phone, area_code, course_type, age, email, project, create_time, 
+    id, surname, `name`, phone, area_code, course_type, min_age,max_age, email, project, create_time,
     create_user_id, update_time, update_user_id, delete_flag
   </sql>
   <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
@@ -40,12 +41,12 @@
     <!--@mbg.generated-->
     insert into happy_entry (id, surname, `name`, 
       phone, area_code, course_type, 
-      age, email, project, 
+      min_age,max_age, email, project,
       create_time, create_user_id, update_time, 
       update_user_id, delete_flag)
     values (#{id,jdbcType=BIGINT}, #{surname,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, 
       #{phone,jdbcType=VARCHAR}, #{areaCode,jdbcType=VARCHAR}, #{courseType,jdbcType=INTEGER}, 
-      #{age,jdbcType=INTEGER}, #{email,jdbcType=VARCHAR}, #{project,jdbcType=VARCHAR}, 
+      #{minAge,jdbcType=INTEGER},#{maxAge,jdbcType=INTEGER}, #{email,jdbcType=VARCHAR}, #{project,jdbcType=VARCHAR},
       #{createTime,jdbcType=TIMESTAMP}, #{createUserId,jdbcType=BIGINT}, #{updateTime,jdbcType=TIMESTAMP}, 
       #{updateUserId,jdbcType=BIGINT}, #{deleteFlag,jdbcType=INTEGER})
   </insert>
@@ -71,8 +72,11 @@
       <if test="courseType != null">
         course_type,
       </if>
-      <if test="age != null">
-        age,
+      <if test="minAge != null">
+        min_age,
+      </if>
+      <if test="maxAge != null">
+        max_age,
       </if>
       <if test="email != null">
         email,
@@ -115,8 +119,11 @@
       <if test="courseType != null">
         #{courseType,jdbcType=INTEGER},
       </if>
-      <if test="age != null">
-        #{age,jdbcType=INTEGER},
+      <if test="minAge != null">
+        #{minAge,jdbcType=INTEGER},
+      </if>
+      <if test="maxAge != null">
+        #{maxAge,jdbcType=INTEGER},
       </if>
       <if test="email != null">
         #{email,jdbcType=VARCHAR},
@@ -160,8 +167,11 @@
       <if test="courseType != null">
         course_type = #{courseType,jdbcType=INTEGER},
       </if>
-      <if test="age != null">
-        age = #{age,jdbcType=INTEGER},
+      <if test="minAge != null">
+        min_age = #{minAge,jdbcType=INTEGER},
+      </if>
+      <if test="maxAge != null">
+        max_age = #{maxAge,jdbcType=INTEGER},
       </if>
       <if test="email != null">
         email = #{email,jdbcType=VARCHAR},
@@ -195,7 +205,8 @@
       phone = #{phone,jdbcType=VARCHAR},
       area_code = #{areaCode,jdbcType=VARCHAR},
       course_type = #{courseType,jdbcType=INTEGER},
-      age = #{age,jdbcType=INTEGER},
+      min_age = #{minAge,jdbcType=INTEGER},
+      max_age = #{maxAge,jdbcType=INTEGER},
       email = #{email,jdbcType=VARCHAR},
       project = #{project,jdbcType=VARCHAR},
       create_time = #{createTime,jdbcType=TIMESTAMP},

+ 6 - 0
edu-travel-service/edu-travel-service-tenement/pom.xml

@@ -133,6 +133,12 @@
             <artifactId>edu-travel-common-cache</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-adapter-upload</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
 
     </dependencies>
     <profiles>

+ 43 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/constant/BaseConstant.java

@@ -0,0 +1,43 @@
+package edu.travel.tenant.constant;
+
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class BaseConstant {
+    /**
+     * 删除标记 正常
+     */
+    public static final Integer BASIC_STATUS_NO_NUM = 0;
+    public static final String BASIC_STATUS_NO_STR = "0";
+
+    /**
+     * 删除标记 删除
+     */
+    public static final Integer BASIC_STATUS_YES_NUM = 1;
+    public static final String BASIC_STATUS_YES_STR = "1";
+
+    /**
+     * 删除标记 正常
+     */
+    public static final Integer BASIC_IS_DEFAULT_YES = 0;
+    public static final Integer BASIC_IS_DEFAULT_YES_NO = 1;
+
+    /**
+     * 商品文件上传图片类型
+     */
+    private static final Set<String> PRODUCT_IMAGE_TYPES = new HashSet<>(
+            Arrays.asList("jpg", "jpeg", "png")
+    );
+
+    public static Set<String> getProductImageTypes() {
+        return PRODUCT_IMAGE_TYPES;
+    }
+    /**
+     * 获取banner 图片类型
+     */
+    public static Set<String> getBannerImageTypes() {
+        return PRODUCT_IMAGE_TYPES;
+    }
+}

+ 19 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/constant/RedisKey.java

@@ -0,0 +1,19 @@
+package edu.travel.tenant.constant;
+
+public interface RedisKey {
+    /**商品类型*/
+    String BASH = "shop:";
+    /**商品类型*/
+   String PRODUCT_TYPE = BASH +"product:type";
+   /**热门商品类型*/
+   String PRODUCT_HOT_TYPE = BASH +"product:hot:type";
+    /**热门二级商品类型*/
+   String PRODUCT_TO_HOT_TYPE = BASH +"product:to:hot:type";
+    /**
+     * 加上国家
+     */
+
+
+    String PRODUCT_ORDER = BASH +"product:order";
+
+}

+ 5 - 1
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/service/ShopBannerService.java

@@ -1,9 +1,11 @@
 package edu.travel.tenant.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import edu.travel.remote.feign.mode.dto.tenant.BannerDto;
 import edu.travel.remote.feign.mode.vo.banner.BannerVo;
-import edu.travel.tenant.dto.BannerDto;
+import edu.travel.rpc.RPCBaseResponse;
 import edu.travel.tenant.entity.ShopBanner;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -12,4 +14,6 @@ public interface ShopBannerService extends IService<ShopBanner>{
 
 
     List<BannerVo> getBanner(BannerDto mode);
+
+    RPCBaseResponse<String> uploadBannerImage(MultipartFile file);
 }

+ 57 - 2
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/service/impl/ShopBannerServiceImpl.java

@@ -1,24 +1,38 @@
 package edu.travel.tenant.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.FileTypeUtil;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import edu.travel.adapter.service.upload.UploadAdapter;
+import edu.travel.remote.feign.mode.dto.tenant.BannerDto;
 import edu.travel.remote.feign.mode.vo.banner.BannerVo;
-import edu.travel.tenant.dto.BannerDto;
+import edu.travel.remote.upload.dto.EduFileDTO;
+import edu.travel.rpc.RPCBaseResponse;
+import edu.travel.tenant.constant.BaseConstant;
 import edu.travel.tenant.entity.ShopBanner;
 import edu.travel.tenant.mapper.ShopBannerMapper;
 import edu.travel.tenant.service.ShopBannerService;
+import edu.travel.tenant.utils.FIleUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
+import static edu.travel.rpc.RPCBaseResponse.error;
+import static edu.travel.rpc.RPCBaseResponse.success;
+
 @Service
 public class ShopBannerServiceImpl extends ServiceImpl<ShopBannerMapper, ShopBanner> implements ShopBannerService {
-
+    @Autowired
+    private UploadAdapter uploadAdapter;
     @Override
     public List<BannerVo> getBanner(BannerDto mode) {
        List<BannerVo> list = new ArrayList<>();
@@ -36,4 +50,45 @@ public class ShopBannerServiceImpl extends ServiceImpl<ShopBannerMapper, ShopBan
         }
         return list;
     }
+
+    @Override
+    public RPCBaseResponse<String> uploadBannerImage(MultipartFile file) {
+        // 判断上传的文件是否为空或未选择
+        if (file == null || file.isEmpty()) {
+            return error();
+        }
+        try {
+            // 获取文件类型(MIME 类型)
+            String fileType = FileTypeUtil.getType(file.getInputStream());
+
+            // 检查文件类型是否有效且是否在允许的横幅图片类型列表中
+            if (fileType != null && BaseConstant.getBannerImageTypes().contains(fileType.toLowerCase())) {
+                // 获取用户上传的文件名
+                String filename = file.getOriginalFilename();
+                // 检查文件名是否为空
+                if (ObjectUtil.isEmpty(filename)) {
+                    return error(); // 返回错误响应
+                }
+                // 初始化上传,获取上传 ID
+                RPCBaseResponse<String> stringRPCBaseResponse = uploadAdapter.initializeUpload();
+                // 创建文件 DTO 对象,用于存储文件相关信息
+                EduFileDTO eduFileDTO = new EduFileDTO();
+                eduFileDTO.setUploadId(stringRPCBaseResponse.getData()); // 设置上传 ID
+                eduFileDTO.setFileType(fileType); // 设置文件类型
+                eduFileDTO.setFileName(filename); // 设置文件原始名称
+                // 生成系统文件名,确保唯一性
+                eduFileDTO.setFileSysName(IdUtil.fastSimpleUUID() + DateUtil.format(new Date(), "yyyyMMddHHmmss") + "." + fileType);
+                // 计算文件的 MD5 值以便后续验证
+                eduFileDTO.setFileMd5(FIleUtil.calculateFileMd5(file.getBytes()));
+                // 调用上传适配器进行文件上传
+                RPCBaseResponse rpcBaseResponse = uploadAdapter.uploadFile(eduFileDTO, file);
+                // 返回成功响应,包含上传后的数据
+                return success(rpcBaseResponse.getData().toString());
+            }
+        } catch (Exception e) {
+            e.printStackTrace(); // 打印异常栈信息
+            return error("file upload fail"); // 返回表示文件上传失败的错误响应
+        }
+        return error(); // 如果文件类型不支持,返回错误响应
+    }
 }

+ 17 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/FIleUtil.java

@@ -0,0 +1,17 @@
+package edu.travel.tenant.utils;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class FIleUtil {
+
+    public static String calculateFileMd5(byte[] data) throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        byte[] digest = md.digest(data);
+        StringBuilder sb = new StringBuilder();
+        for (byte b : digest) {
+            sb.append(String.format("%02x", b));
+        }
+        return sb.toString();
+    }
+}

+ 13 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/IdUtils.java

@@ -0,0 +1,13 @@
+package edu.travel.tenant.utils;
+
+import cn.hutool.core.lang.Singleton;
+import cn.hutool.core.lang.Snowflake;
+import lombok.Data;
+
+@Data
+public class IdUtils {
+    public static long getSnowflakeId() {
+        Snowflake snowflake = Singleton.get(Snowflake.class, 1L, 1L, true);
+        return  snowflake.nextId();
+    }
+}

+ 19 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/ObjectUtils.java

@@ -0,0 +1,19 @@
+package edu.travel.tenant.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ObjectUtils {
+
+
+    public static <T> List<T> castList(Object obj, Class<T> clazz) {
+        List<T> result = new ArrayList<T>();
+        if (obj instanceof List<?>) {
+            for (Object o : (List<?>) obj) {
+                result.add(clazz.cast(o));
+            }
+            return result;
+        }
+        return null;
+    }
+}

+ 28 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/PageUtil.java

@@ -0,0 +1,28 @@
+package edu.travel.tenant.utils;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springframework.beans.BeanUtils;
+
+public class PageUtil{
+
+    /**
+     * Page类型entity转换
+     * @param source
+     * @param type
+     * @return
+     */
+    public static <T,E> Page<E> toPageEntity(Page<T> source, Class<E> type) {
+        Page<E> target = new Page<E>();
+        BeanUtils.copyProperties(source, target);
+        target.setRecords(BeanUtil.copyToList(source.getRecords(), type));
+        return target;
+    }
+    public static <T,E> Page<E> toPageEntity(IPage<T> source, Class<E> type) {
+        Page<E> target = new Page<E>();
+        BeanUtils.copyProperties(source, target);
+        target.setRecords(BeanUtil.copyToList(source.getRecords(), type));
+        return target;
+    }
+}

+ 36 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/RedisUtil.java

@@ -0,0 +1,36 @@
+package edu.travel.tenant.utils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisUtil {
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+    /**
+     *通过KEY 获取值
+     */
+    public String getString(String key) {
+        return stringRedisTemplate.opsForValue().get(key);
+    }
+    /**
+     * 设置KEY 和 VALUE
+     */
+    public void setString(String key, String value) {
+        stringRedisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * @param key KEY
+     * @param value 值
+     * @param expire 过期时间
+     * @param timeUnit 时间单位
+     */
+    public void setString(String key, String value,long expire,TimeUnit timeUnit) {
+        stringRedisTemplate.opsForValue().set(key, value,expire, timeUnit);
+    }
+
+}

+ 26 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/StringUtil.java

@@ -0,0 +1,26 @@
+package edu.travel.tenant.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Data
+public class StringUtil {
+
+    public static List<String> toList(String str){
+        if(!ObjectUtil.isEmpty(str)){
+            return Arrays.asList(str.split(","));
+        }
+        return new ArrayList<>();
+    }
+    public static String toListString(List<String> list){
+        String result="";
+        for (String s : list) {
+            result=s+",";
+        }
+        return result;
+    }
+}

+ 16 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/TokenData.java

@@ -0,0 +1,16 @@
+package edu.travel.tenant.utils;
+
+import edu.travel.entity.EduTenantPO;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+public class TokenData {
+
+    /**
+     *  获取用户ID
+     * @return {@link String }
+     */
+    public static String getUserId(){
+        EduTenantPO principal =(EduTenantPO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        return principal.getId().toString();
+    }
+}

+ 161 - 0
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/utils/TreeUtils.java

@@ -0,0 +1,161 @@
+package edu.travel.tenant.utils;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+/**
+ * 通用树形结构构建工具类
+ *
+ * <p><strong>功能特性:</strong></p>
+ * <ul>
+ *   <li>支持任意 Java 对象(实体类/DTO/VO)</li>
+ *   <li>自动检测循环依赖(死循环)</li>
+ *   <li>零依赖(无需继承接口或父类)</li>
+ *   <li>编译期类型安全检查</li>
+ * </ul>
+ *
+ * <p><strong>使用示例:</strong></p>
+ * <pre>{@code
+ * List<Department> tree = TreeUtils.buildTree(
+ *     departments,
+ *     Department::getId,
+ *     Department::getParentId,
+ *     Department::setChildren
+ * );
+ * }</pre>
+ */
+public class TreeUtils {
+
+    /**
+     * 构建树形结构的核心方法
+     *
+     * @param nodes          待处理的节点列表(必须包含所有节点)
+     * @param idGetter       节点ID的获取方法(方法引用,如:User::getId)
+     * @param pidGetter      父节点ID的获取方法(方法引用,如:User::getParentId)
+     * @param childrenSetter 子节点列表的设置方法(如:(node, children) -> node.setChildren(children))
+     * @param <T>            节点类型(如:User.class)
+     * @param <ID>           ID 的类型(需正确实现 equals 和 hashCode)
+     * @return 树形结构的根节点列表
+     *
+     * @throws IllegalArgumentException 如果存在以下情况:
+     *                                  <ul>
+     *                                    <li>节点列表为null</li>
+     *                                    <li>存在重复ID</li>
+     *                                    <li>ID字段为null</li>
+     *                                  </ul>
+     * @throws IllegalStateException    如果检测到循环依赖
+     */
+    public static <T, ID> List<T> buildTree(List<T> nodes,
+                                            Function<T, ID> idGetter,
+                                            Function<T, ID> pidGetter,
+                                            BiConsumer<T, List<T>> childrenSetter) {
+        // 防御性拷贝,避免修改原始数据
+        List<T> copyNodes = new ArrayList<>(Optional.ofNullable(nodes).orElseGet(ArrayList::new));
+
+        //========== 数据校验 ==========//
+        validateNodes(copyNodes, idGetter);
+
+        //========== 初始化数据结构 ==========//
+        Map<ID, T> nodeMap = new HashMap<>(copyNodes.size());
+        List<T> rootNodes = new ArrayList<>();
+
+        // 构建 id -> node 映射表
+        copyNodes.forEach(node -> nodeMap.put(idGetter.apply(node), node));
+
+        //========== 构建父子关系 ==========//
+        for (T node : copyNodes) {
+            ID currentId = idGetter.apply(node);
+            ID parentId = pidGetter.apply(node);
+
+            // 判断根节点条件(父ID为空/等于自身/不存在于Map中)
+            if (isRootNode(parentId, currentId, nodeMap)) {
+                rootNodes.add(node);
+                continue;
+            }
+
+            // 获取父节点并建立关联
+            T parent = nodeMap.get(parentId);
+            if (parent != null) {
+                linkParentAndChild(parent, node, childrenSetter);
+                checkCircularDependency(parent, currentId, idGetter, pidGetter, nodeMap);
+            }
+        }
+
+        return rootNodes;
+    }
+
+    //========== 私有方法 ==========//
+
+    /**
+     * 数据校验
+     */
+    private static <T, ID> void validateNodes(List<T> nodes, Function<T, ID> idGetter) {
+        if (nodes == null) {
+            throw new IllegalArgumentException("节点列表不能为null");
+        }
+
+        Set<ID> idSet = new HashSet<>();
+        for (T node : nodes) {
+            ID id = idGetter.apply(node);
+            if (id == null) {
+                throw new IllegalArgumentException("节点存在空ID: " + node);
+            }
+            if (idSet.contains(id)) {
+                throw new IllegalArgumentException("存在重复ID: " + id);
+            }
+            idSet.add(id);
+        }
+    }
+
+    /**
+     * 判断是否为根节点
+     */
+    private static <ID> boolean isRootNode(ID parentId, ID currentId, Map<ID, ?> nodeMap) {
+        return parentId == null
+                || parentId.equals(currentId)
+                || !nodeMap.containsKey(parentId);
+    }
+
+    /**
+     * 建立父子关联关系
+     */
+    private static <T> void linkParentAndChild(T parent,
+                                               T child,
+                                               BiConsumer<T, List<T>> childrenSetter) {
+        List<T> children = new ArrayList<>();
+        childrenSetter.accept(parent, children);
+        children.add(child);
+    }
+
+    /**
+     * 循环依赖检测(核心安全机制)
+     */
+    private static <T, ID> void checkCircularDependency(T parent,
+                                                        ID childId,
+                                                        Function<T, ID> idGetter,
+                                                        Function<T, ID> pidGetter,
+                                                        Map<ID, T> nodeMap) {
+        Set<ID> visited = new HashSet<>();
+        T current = parent;
+
+        while (current != null) {
+            ID currentParentId = pidGetter.apply(current);
+            if (currentParentId == null) break;
+
+            // 发现直接循环(A→B→A)
+            if (currentParentId.equals(childId)) {
+                throw new IllegalStateException("检测到循环依赖:节点 "
+                        + idGetter.apply(current) + " → " + childId);
+            }
+
+            // 发现间接循环(A→B→C→A)
+            if (visited.contains(currentParentId)) {
+                throw new IllegalStateException("检测到循环依赖路径:" + visited);
+            }
+
+            visited.add(currentParentId);
+            current = nodeMap.get(currentParentId);
+        }
+    }
+}

+ 63 - 5
edu-travel-service/edu-travel-service-tenement/src/main/java/edu/travel/tenant/web/ShopBannerController.java

@@ -1,16 +1,17 @@
 package edu.travel.tenant.web;
 
+import edu.travel.remote.feign.mode.dto.tenant.BannerDto;
+import edu.travel.remote.feign.mode.romote.ShopBannerRemoteController;
 import edu.travel.remote.feign.mode.vo.banner.BannerVo;
 import edu.travel.resp.BaseResponse;
 import edu.travel.rpc.RPCBaseResponse;
-import edu.travel.tenant.dto.BannerDto;
 import edu.travel.tenant.entity.ShopBanner;
 import edu.travel.tenant.service.ShopBannerService;
 import edu.travel.web.BaseController;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -23,7 +24,7 @@ import static edu.travel.rpc.RPCBaseResponse.success;
 */
 @RestController
 @RequestMapping("/shopBanner")
-public class ShopBannerController extends BaseController<ShopBanner>{
+public class ShopBannerController extends BaseController<ShopBanner> implements ShopBannerRemoteController {
 /**
 * 服务对象
 */
@@ -41,6 +42,63 @@ public class ShopBannerController extends BaseController<ShopBanner>{
         return success(shopBannerService.getBanner(banner));
     }
 
+    /**
+     * 上传banner图片
+     * @param
+     * @return
+     */
+    @PostMapping("/uploadBannerImage")
+    public RPCBaseResponse<String> uploadBannerImage(MultipartFile file){
+        return shopBannerService.uploadBannerImage(file);
+    }
+    @Override
+    @GetMapping("/getFormId")
+    public RPCBaseResponse<BannerVo> getFormId(String id) {
+        RPCBaseResponse<ShopBanner> shopBannerRPCBaseResponse = super.getId(id);
+        RPCBaseResponse<BannerVo> shopBannerVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(shopBannerRPCBaseResponse, shopBannerVoRPCBaseResponse);
+        return shopBannerVoRPCBaseResponse;
+    }
+
+    @Override
+    @GetMapping("/updateFormTarget")
+    public RPCBaseResponse<BannerVo> updateTargetFormId(@RequestBody BannerDto entity) {
+        ShopBanner shopBanner = new ShopBanner();
+        BeanUtils.copyProperties(entity, shopBanner);
+        RPCBaseResponse<ShopBanner> shopBannerRPCBaseResponse = super.updateTargetById(shopBanner);
+        RPCBaseResponse<BannerVo> shopBannerVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(shopBannerRPCBaseResponse, shopBannerVoRPCBaseResponse);
+        return shopBannerVoRPCBaseResponse;
+    }
 
+    @Override
+    @GetMapping("/saveFormTarget")
+    public RPCBaseResponse<BannerVo> saveFormTarget(BannerDto entity) {
+        ShopBanner shopBanner = new ShopBanner();
+        BeanUtils.copyProperties(entity, shopBanner);
+        RPCBaseResponse<ShopBanner> shopBannerRPCBaseResponse = super.saveTarget(shopBanner);
+        RPCBaseResponse<BannerVo> shopBannerVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(shopBannerRPCBaseResponse, shopBannerVoRPCBaseResponse);
+        return shopBannerVoRPCBaseResponse;
+    }
+
+
+    @Override
+    @GetMapping("/deleteFormTarget")
+    public RPCBaseResponse<BannerVo> deleteTargetFormId(List<String> ids) {
+        RPCBaseResponse<ShopBanner> shopBannerRPCBaseResponse = super.deleteTargetById(ids);
+        RPCBaseResponse<BannerVo> shopBannerVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(shopBannerRPCBaseResponse, shopBannerVoRPCBaseResponse);
+        return shopBannerVoRPCBaseResponse;
+    }
+
+    @Override
+    @GetMapping("/getAllForm")
+    public RPCBaseResponse<List<BannerVo>> getAllForm() {
+        RPCBaseResponse<List<ShopBanner>> countryRPCBaseResponse = super.listAll();
+        RPCBaseResponse<List<BannerVo>> baseCountryVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(countryRPCBaseResponse, baseCountryVoRPCBaseResponse);
+        return baseCountryVoRPCBaseResponse;
+    }
 
 }

+ 31 - 0
edu-travel-service/edu-travel-service-tomcat/pom.xml

@@ -0,0 +1,31 @@
+<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>edu.travel</groupId>
+        <artifactId>edu-travel-service</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>edu-travel-service-tomcat</artifactId>
+    <packaging>jar</packaging>
+
+    <name>edu-travel-service-tomcat</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-common-core</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+</project>

+ 17 - 0
edu-travel-service/edu-travel-service-tomcat/src/main/java/edu/travel/App.java

@@ -0,0 +1,17 @@
+package edu.travel;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Hello world!
+ *
+ */
+@SpringBootApplication
+public class App 
+{
+    public static void main( String[] args )
+    {
+       SpringApplication.run(App.class, args);
+    }
+}

+ 75 - 1
edu-travel-service/edu-travel-service-upload/src/main/java/edu/travel/upload/web/UploadController.java

@@ -7,6 +7,7 @@ import com.obs.services.model.*;
 import edu.travel.remote.upload.UploadRemoteController;
 import edu.travel.remote.upload.dto.EduFileBlobDTO;
 import edu.travel.remote.upload.dto.EduFileDTO;
+import edu.travel.remote.upload.vo.EduFileVo;
 import edu.travel.rpc.RPCBaseResponse;
 import edu.travel.upload.config.MD5Calculator;
 import edu.travel.upload.entity.EduFile;
@@ -14,6 +15,7 @@ import edu.travel.upload.entity.EduFileBlob;
 import edu.travel.upload.obs.property.ObsProperties;
 import edu.travel.upload.service.EduFileBlobService;
 import edu.travel.upload.service.EduFileService;
+import edu.travel.web.BaseController;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,7 +37,7 @@ import java.util.concurrent.ThreadPoolExecutor;
 
 @RestController
 @RequestMapping("/upload")
-public class UploadController implements UploadRemoteController {
+public class UploadController extends BaseController<EduFile> implements UploadRemoteController {
     @Autowired
     private EduFileService eduFileService;
     @Autowired
@@ -150,4 +152,76 @@ public class UploadController implements UploadRemoteController {
         }
         return RPCBaseResponse.error();
     }
+
+    /**
+     * 通过id上传文件
+     * @param id
+     * @return
+     */
+    @Override
+    @GetMapping("/getFormId")
+    public RPCBaseResponse<EduFileVo> getFormId(String id) {
+        RPCBaseResponse<EduFile> eduFileRPCBaseResponse = super.getId(id);
+        RPCBaseResponse<EduFileVo> eduFileVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(eduFileRPCBaseResponse, eduFileVoRPCBaseResponse);
+        return eduFileVoRPCBaseResponse;
+    }
+
+    /**
+     * 更新文件
+     * @param entity
+     * @return
+     */
+    @Override
+    @GetMapping("/updateTargetFormId")
+    public RPCBaseResponse<EduFileVo> updateTargetFormId(@RequestBody EduFileDTO entity) {
+        EduFile eduFile = new EduFile();
+        BeanUtils.copyProperties(entity, eduFile);
+        RPCBaseResponse<EduFile> eduFileRPCBaseResponse = super.updateTargetById(eduFile);
+        RPCBaseResponse<EduFileVo> eduFileVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(eduFileRPCBaseResponse, eduFileVoRPCBaseResponse);
+        return eduFileVoRPCBaseResponse;
+    }
+
+    /**
+     * 新增文件
+     * @param entity
+     * @return
+     */
+    @Override
+    @GetMapping("/saveFormTarget")
+    public RPCBaseResponse<EduFileVo> saveFormTarget(@RequestBody EduFileDTO entity) {
+        EduFile eduFile = new EduFile();
+        BeanUtils.copyProperties(entity, eduFile);
+        RPCBaseResponse<EduFile> eduFileRPCBaseResponse = super.saveTarget(eduFile);
+        RPCBaseResponse<EduFileVo> eduFileVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(eduFileRPCBaseResponse, eduFileVoRPCBaseResponse);
+        return eduFileVoRPCBaseResponse;
+    }
+
+    /**
+     * 删除文件
+     * @param ids
+     * @return
+     */
+    @Override
+    @GetMapping("/deleteTargetFormId")
+    public RPCBaseResponse<EduFileVo> deleteTargetFormId(@RequestBody List<String> ids) {
+        RPCBaseResponse<EduFile> eduFileRPCBaseResponse = super.deleteTargetById(ids);
+        RPCBaseResponse<EduFileVo> eduFileVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(eduFileRPCBaseResponse, eduFileVoRPCBaseResponse);
+        return eduFileVoRPCBaseResponse;
+    }
+
+    /**
+     * 获取全部文件
+     * @return
+     */
+    @Override
+    public RPCBaseResponse<List<EduFileVo>> getAllForm() {
+        RPCBaseResponse<List<EduFile>> eduFileRPCBaseResponse = super.listAll();
+        RPCBaseResponse<List<EduFileVo>> eduFileVoRPCBaseResponse = new RPCBaseResponse<>();
+        BeanUtils.copyProperties(eduFileRPCBaseResponse, eduFileVoRPCBaseResponse);
+        return eduFileVoRPCBaseResponse;
+    }
 }

+ 4 - 4
edu-travel-service/edu-travel-service-upload/src/main/resources/bootstrap-dev.yml

@@ -2,13 +2,13 @@ spring:
   cloud:
     nacos:
       discovery:
-        server-addr: localhost:8848,localhost:8849,localhost:8858
-        namespace: edu-@env@
+        server-addr: 192.168.1.44:8848,192.168.1.44:8849,192.168.1.44:8858
+        namespace: yangzheng-@env@
       config:
         file-extension: yaml
-        server-addr: localhost:8848,localhost:8849,localhost:8858
+        server-addr: 192.168.1.44:8848,192.168.1.44:8849,192.168.1.44:8858
         refresh-enabled: true
-        namespace: edu-@env@
+        namespace: yangzheng-@env@
         shared-configs:
           - data-id: mybatis-config-dev.yaml
             group: DEFAULT_GROUP

+ 1 - 1
edu-travel-service/edu-travel-service-upload/src/main/resources/bootstrap.yml

@@ -1,5 +1,5 @@
 server:
-  port: 10005
+  port: 10010
 spring:
   application:
     name: upload-@env@

+ 135 - 0
edu-travel-service/edu-travel-service-ws/pom.xml

@@ -0,0 +1,135 @@
+<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>edu.travel</groupId>
+        <artifactId>edu-travel-service</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>edu-travel-service-ws</artifactId>
+    <packaging>jar</packaging>
+
+    <name>edu-travel-service-ws</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-zipkin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-transport-simple-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-annotation-aspectj</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-datasource-nacos</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-web-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-model-base</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-common-cache</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-common-datasource</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>edu.travel</groupId>
+            <artifactId>edu-travel-common-constant</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+
+
+
+    </dependencies>
+</project>

+ 17 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/WsApplication.java

@@ -0,0 +1,17 @@
+package edu.travel;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+
+@SpringBootApplication
+@EnableDiscoveryClient
+@MapperScan
+public class WsApplication
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}

+ 32 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/MyAccessDeniedHandler.java

@@ -0,0 +1,32 @@
+package edu.travel.ws.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MyAccessDeniedHandler  implements AccessDeniedHandler {
+    @Override
+    public void handle(HttpServletRequest req, HttpServletResponse resp, AccessDeniedException e) throws IOException, ServletException {
+        resp.setContentType("application/json;charset=UTF-8");
+        Map map = new HashMap();
+        map.put("code", "450");
+        map.put("message", e.getMessage());
+        map.put("path", req.getServletPath());
+        map.put("timestamp", String.valueOf(System.currentTimeMillis()));
+        resp.setContentType("application/json");
+        resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.writeValue(resp.getOutputStream(), map);
+        } catch (Exception ex) {
+            throw new ServletException();
+        }
+    }
+}

+ 31 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/MyAuthenticationEntryPoint.java

@@ -0,0 +1,31 @@
+package edu.travel.ws.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
+    @Override
+    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
+        Map map = new HashMap();
+        map.put("code", "451");
+        map.put("message", "无权限访问");
+        map.put("path", httpServletRequest.getServletPath());
+        map.put("timestamp", String.valueOf(System.currentTimeMillis()));
+        httpServletResponse.setContentType("application/json");
+        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.writeValue(httpServletResponse.getOutputStream(), map);
+        } catch (Exception ex) {
+            throw new ServletException();
+        }
+    }
+}

+ 39 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/ResourceServerConfig.java

@@ -0,0 +1,39 @@
+package edu.travel.ws.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
+    private static  final String RESOURCE_ID = "admin";
+
+    @Autowired
+    private TokenStore tokenStore;
+
+    @Override
+    public void configure(ResourceServerSecurityConfigurer resources) {
+        resources.resourceId(RESOURCE_ID)//资源 id
+                .tokenStore(tokenStore)
+                .authenticationEntryPoint(new MyAuthenticationEntryPoint())
+                .accessDeniedHandler(new MyAccessDeniedHandler())
+//                .tokenServices(tokenService())//验证令牌的服务
+                .stateless(true);
+    }
+
+    @Override
+    public void configure(HttpSecurity http) throws Exception {
+
+        http
+                .authorizeRequests()
+                .antMatchers("/**").permitAll()
+                .and().csrf().disable()
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+    }
+}

+ 48 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/TokenConfig.java

@@ -0,0 +1,48 @@
+package edu.travel.ws.config;
+
+import edu.travel.RSAUtill;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
+import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
+
+import java.security.PrivateKey;
+
+@Configuration
+public class TokenConfig {
+    @Value("${OAUTH_KEY}")
+    private String key;
+    @Value("${PRIVATE_KEY}")
+    private String privateKey;
+    @Bean
+    public PasswordEncoder passwordEncoder(){
+        return NoOpPasswordEncoder.getInstance();
+    }
+    @Bean
+    public TokenStore tokenStore() {
+        //JWT令牌存储方案
+        return new JwtTokenStore(accessTokenConverter());
+    }
+
+    @Bean
+    public JwtAccessTokenConverter accessTokenConverter() {
+        try {
+            PrivateKey privateKeyFromString = RSAUtill.getPrivateKeyFromString(privateKey);
+            String decrypt = RSAUtill.decrypt(key, privateKeyFromString);
+            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
+            //对称秘钥,资源服务器使用该秘钥来验证
+//        converter.setKeyPair(keyPair());
+            converter.setSigningKey(decrypt);
+            return converter;
+
+        }catch (Exception e){
+            e.printStackTrace();
+            return null;
+        }
+
+    }
+}

+ 21 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/WebSecurityConfig.java

@@ -0,0 +1,21 @@
+package edu.travel.ws.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+    //安全拦截机制(最重要)
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http.csrf().disable()
+                .authorizeRequests()
+                .anyRequest().authenticated()
+        ;
+
+
+    }
+}

+ 23 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/WebServerFactoryConfigs.java

@@ -0,0 +1,23 @@
+package edu.travel.ws.config;
+
+import org.apache.catalina.connector.Connector;
+import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class WebServerFactoryConfigs {
+    @Bean
+    public ConfigurableServletWebServerFactory webServerFactory() {
+        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
+        factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
+            @Override
+            public void customize(Connector connector) {
+                connector.setProperty("relaxedQueryChars", "|{}[]");
+            }
+        });
+        return factory;
+    }
+}

+ 25 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/config/WebSocketAutoConfig.java

@@ -0,0 +1,25 @@
+package edu.travel.ws.config;
+
+import edu.travel.ws.handle.TravelMessageHandler;
+import edu.travel.ws.interceptor.SystemMessageInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+@Configuration
+@EnableWebSocket
+public class WebSocketAutoConfig implements WebSocketConfigurer {
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Override
+    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+        registry.addHandler(new TravelMessageHandler(applicationContext), "/system/message")
+                .addInterceptors(new SystemMessageInterceptor(applicationContext))
+                .setAllowedOrigins("*");
+    }
+}

+ 61 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/filter/TokenAuthenticationFilter.java

@@ -0,0 +1,61 @@
+package edu.travel.ws.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import edu.travel.EncryptUtil;
+import edu.travel.entity.EduTenantPO;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class TokenAuthenticationFilter extends OncePerRequestFilter {
+    @Autowired
+    private RedisTemplate redisTemplate;
+    @Override
+    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
+        String token = httpServletRequest.getHeader("token");
+//token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYWRtaW4iXSwiZXhwIjoxNzQwMjAyNTcyLCJ1c2VyX25hbWUiOiIxNTk5ODk1NzA3NCIsImp0aSI6IjM0M2JjNGUzLTk5ZjMtNGE4Zi1iMmIxLTI1ZjRkMzBmNmJmYyIsImNsaWVudF9pZCI6ImFkbWluIiwic2NvcGUiOlsic2VydmVyIl19.MYoFq8gg832DQMX-wVMLN0JlIaWeuQZvl1z1NUNFspQ";
+        if (StringUtils.isNotBlank(token)){
+            String json = EncryptUtil.decodeUTF8StringBase64(token);
+            //将token转成json对象
+            JSONObject jsonObject = JSON.parseObject(json);
+            //用户身份信息
+            String username  = jsonObject.getString("principal");
+            Object object = redisTemplate.opsForValue().get(username + "_info");
+            if (object == null){
+                JSONObject resultObject = new JSONObject();
+                resultObject.put("code",401);
+                resultObject.put("msg","not found user");
+                resultObject.put("data",null);
+                httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                httpServletResponse.setContentType("application/json;charset=utf-8");
+                httpServletResponse.getWriter().write(resultObject.toJSONString());
+                return;
+            }
+            EduTenantPO eduTenant = JSON.parseObject(object.toString(), EduTenantPO.class);
+            //用户权限
+            JSONArray authoritiesArray = jsonObject.getJSONArray("authorities");
+            String[] authorities = authoritiesArray.toArray(new String[authoritiesArray.size()]);
+            //将用户信息和权限填充 到用户身份token对象中
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(eduTenant, null, AuthorityUtils.createAuthorityList(authorities));
+            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
+            //将authenticationToken填充到安全上下文
+            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+        }
+        filterChain.doFilter(httpServletRequest,httpServletResponse);
+    }
+}

+ 12 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/handle/TravelMessageHandler.java

@@ -0,0 +1,12 @@
+package edu.travel.ws.handle;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.socket.handler.AbstractWebSocketHandler;
+
+public class TravelMessageHandler extends AbstractWebSocketHandler {
+    private ApplicationContext applicationContext;
+
+    public TravelMessageHandler(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+}

+ 62 - 0
edu-travel-service/edu-travel-service-ws/src/main/java/edu/travel/ws/interceptor/SystemMessageInterceptor.java

@@ -0,0 +1,62 @@
+package edu.travel.ws.interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import edu.travel.EncryptUtil;
+import edu.travel.entity.EduTenantPO;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.ApplicationContext;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+
+import java.util.Map;
+
+public class SystemMessageInterceptor implements HandshakeInterceptor {
+    private ApplicationContext applicationContext;
+    public SystemMessageInterceptor(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+    @Override
+    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
+        RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
+        if (request instanceof ServletServerHttpRequest){
+            ServletServerHttpRequest httpRequest = (ServletServerHttpRequest) request;
+            String token = httpRequest.getServletRequest().getParameter("token");
+            if (StringUtils.isBlank(token)){
+                return false;
+            }
+            String json = EncryptUtil.decodeUTF8StringBase64(token);
+            //将token转成json对象
+            JSONObject jsonObject = JSON.parseObject(json);
+            //用户身份信息
+            String username  = jsonObject.getString("principal");
+            Object object = redisTemplate.opsForValue().get(username + "_info");
+            EduTenantPO eduTenant = JSON.parseObject(object.toString(), EduTenantPO.class);
+            //用户权限
+            JSONArray authoritiesArray = jsonObject.getJSONArray("authorities");
+            String[] authorities = authoritiesArray.toArray(new String[authoritiesArray.size()]);
+            //将用户信息和权限填充 到用户身份token对象中
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(eduTenant, null, AuthorityUtils.createAuthorityList(authorities));
+            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest.getServletRequest()));
+            //将authenticationToken填充到安全上下文
+            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+            attributes.put("user", eduTenant);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
+
+    }
+}

+ 2 - 0
edu-travel-service/pom.xml

@@ -19,6 +19,8 @@
         <module>edu-travel-service-upload</module>
         <module>edu-travel-service-debezium</module>
         <module>edu-travel-service-education</module>
+        <module>edu-travel-service-tomcat</module>
+        <module>edu-travel-service-ws</module>
     </modules>
 
     <name>edu-travel-service</name>