Explorar el Código

系统运维:版本升级代码提交

xujie hace 1 año
padre
commit
57fee88c12

+ 7 - 0
pom.xml

@@ -43,6 +43,7 @@
         <freemarker.version>2.7.2</freemarker.version>
         <velocity.version>2.3</velocity.version>
         <knife4j.version>3.0.3</knife4j.version>
+        <zafarkhaja.version>0.9.0</zafarkhaja.version>
     </properties>
     <dependencyManagement>
         <dependencies>
@@ -242,6 +243,12 @@
                 <artifactId>lombok</artifactId>
                 <version>${lombok.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>com.github.zafarkhaja</groupId>
+                <artifactId>java-semver</artifactId>
+                <version>${zafarkhaja.version}</version>
+            </dependency>
 <!--                    <dependency>-->
 <!--                        <groupId>log4j</groupId>-->
 <!--                        <artifactId>log4j</artifactId>-->

+ 2 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/RemoteFileService.java

@@ -98,4 +98,6 @@ public interface RemoteFileService {
 
     @PostMapping(value = "/file/readFile")
     byte[] readFile(@RequestBody Map<String, String> data);
+    @PostMapping(value = "/file/downloadFile/realName", consumes = MediaType.APPLICATION_JSON_VALUE)
+    Response downloadFileRealName(@RequestBody SysFile sysFile);
 }

+ 44 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/domain/SysVersion.java

@@ -0,0 +1,44 @@
+package com.xunmei.system.api.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.xunmei.common.core.web.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 版本管理表 sys_version
+ *
+ * @author xunmei
+ */
+@Data
+@TableName("sys_version")
+@ApiModel(value = "SysVersion对象", description = "【请填写功能名称】")
+public class SysVersion extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    private Long id;
+
+    @ApiModelProperty(value = "版本号")
+    private String version;
+
+    @ApiModelProperty(value = "版本说明")
+    private String note;
+
+    @ApiModelProperty(value = "下载地址")
+    private String path;
+
+    @ApiModelProperty(value = "文件名称")
+    private String packageName;
+
+    @ApiModelProperty(value = "是否使用")
+    private Boolean isUse;
+
+    @ApiModelProperty(value = "是否强制更新")
+    private Boolean isForce;
+
+    @ApiModelProperty(value = "版本类型 0.安卓 1.PC 2.挂墙终端 3.IOS")
+    private Integer type;
+}

+ 46 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/enums/AppType.java

@@ -0,0 +1,46 @@
+package com.xunmei.system.api.enums;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xunmei.system.api.enums.serializer.EnumSerializer;
+import lombok.Getter;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 应用类型
+ */
+@JsonSerialize(using = EnumSerializer.class)
+@Getter
+public enum AppType {
+    APP(0,"安卓","APP"),
+    PC(1,"PC","PC"),
+    HANG_WALL(2,"挂墙终端","HANG_WALL"),
+    IOS(3,"IOS","IOS"),
+    ;
+
+    private final Integer index;
+    private final String text;
+    private final String typeDesc;
+
+    AppType(Integer index, String text, String typeDesc) {
+        this.index = index;
+        this.text = text;
+        this.typeDesc = typeDesc;
+    }
+
+    public static AppType getEnumByIndex(Integer index) {
+        return enumMap.get(index);
+    }
+
+    /**
+     * 所有枚举
+     */
+    private static final Map<Integer, AppType> enumMap = new LinkedHashMap<>();
+
+    static {
+        for (AppType typeEnum : AppType.values()) {
+            enumMap.put(typeEnum.index, typeEnum);
+        }
+    }
+}

+ 5 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/factory/RemoteFileFallbackFactory.java

@@ -96,6 +96,11 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
             public byte[] readFile(Map<String, String> data) {
                 throw new RuntimeException("读取文件超时,请稍后重试!");
             }
+
+            @Override
+            public Response downloadFileRealName(SysFile sysFile) {
+                return null;
+            }
         };
     }
 }

+ 14 - 2
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/controller/SysFileController.java

@@ -120,7 +120,19 @@ public class SysFileController {
     public void downloadFile(HttpServletResponse response, @RequestBody SysFile sysFile) {
         try {
             String filePath = DesUtil.decode(sysFile.getCode(), secretKey);
-            sysFileService.downloadFile(response, filePath);
+            sysFileService.downloadFile(response, filePath,null);
+        } catch (Exception e) {
+            log.error("下载文件失败", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    @PostMapping("/downloadFile/realName")
+    public void downloadFileRealName(HttpServletResponse response, @RequestBody SysFile sysFile) {
+        try {
+            //String filePath = DesUtil.decode(sysFile.getCode(), secretKey);
+            String filePath = sysFile.getUrl().replace(prefix,"");
+            sysFileService.downloadFile(response, filePath,sysFile.getRealName());
         } catch (Exception e) {
             log.error("下载文件失败", e);
             throw new RuntimeException(e);
@@ -137,7 +149,7 @@ public class SysFileController {
     public void getFile(HttpServletResponse response, @PathVariable String code) {
         try {
             String filePath = DesUtil.decode(code, secretKey);
-            sysFileService.downloadFile(response, filePath);
+            sysFileService.downloadFile(response, filePath,null);
         } catch (Exception e) {
             log.error("下载文件失败", e);
             throw new RuntimeException(e);

+ 1 - 1
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/ISysFileService.java

@@ -46,7 +46,7 @@ public interface ISysFileService
      * @return
      * @throws Exception
      */
-    void downloadFile(HttpServletResponse response, String filePath) throws Exception;
+    void downloadFile(HttpServletResponse response, String filePath, String realName) throws Exception;
 
     String generateEduTrainingPdf(Map<String, Object> data) throws Exception;
     String generateResumptionPdf(Map<String, Object> data) throws Exception;

+ 4 - 1
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/LocalSysFileServiceImpl.java

@@ -167,7 +167,7 @@ public class LocalSysFileServiceImpl implements ISysFileService {
     }
 
     @Override
-    public void downloadFile(HttpServletResponse response, String filePath) {
+    public void downloadFile(HttpServletResponse response, String filePath,String realName) {
         ByteArrayOutputStream out = null;
         try {
             filePath = localFilePath + filePath;
@@ -175,6 +175,9 @@ public class LocalSysFileServiceImpl implements ISysFileService {
             out = FileDownUtils.downloadFile(filePath);
             String fileSuffix = FileDownUtils.getFileSuffix(filePath);
             String formFileName = UUID.randomUUID().toString() + fileSuffix;
+            if (StringUtils.isNotEmpty(realName)){
+                formFileName = realName;
+            }
             String userAgent = request.getHeader("User-Agent");
 
             // 针对IE或者以IE为内核的浏览器:

+ 6 - 0
soc-modules/soc-modules-system/pom.xml

@@ -52,6 +52,12 @@
             <artifactId>mysql-connector-java</artifactId>
         </dependency>
 
+        <!-- 语义化规范2.0版本对比 -->
+        <dependency>
+            <groupId>com.github.zafarkhaja</groupId>
+            <artifactId>java-semver</artifactId>
+        </dependency>
+
         <!--soc datascope 数据权限-->
         <dependency>
             <groupId>com.xunmei</groupId>

+ 67 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/controller/SysVersionController.java

@@ -0,0 +1,67 @@
+package com.xunmei.system.controller;
+
+import com.xunmei.common.core.web.controller.BaseController;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.common.security.annotation.RequiresPermissions;
+import com.xunmei.common.security.utils.SecurityUtils;
+import com.xunmei.system.api.domain.SysVersion;
+import com.xunmei.system.api.model.LoginUser;
+import com.xunmei.system.dto.SysCheckUpdateDto;
+import com.xunmei.system.service.ISysVersionService;
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
+@Api(tags = {"SysVersion" })
+@RestController
+@RequestMapping("/version")
+public class SysVersionController extends BaseController {
+
+    @Resource
+    private ISysVersionService versionService;
+
+    @RequiresPermissions("system:version:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysVersion> list(SysVersion version) {
+        return versionService.selectPage(version);
+    }
+
+    @RequiresPermissions("system:version:add")
+    @PostMapping("/add")
+    public AjaxResult add(@RequestBody SysVersion version) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        version.setCreateBy(loginUser.getName());
+        return  versionService.insertVersion(version);
+    }
+
+    @RequiresPermissions("system:version:edit")
+    @PostMapping("/edit")
+    public AjaxResult edit(@RequestBody SysVersion version) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        version.setUpdateBy(loginUser.getName());
+        return  versionService.updateVersion(version);
+    }
+
+    //@RequiresPermissions("system:version:edit")
+    @GetMapping("/detail/{id}")
+    public AjaxResult detail(@PathVariable Long id) {
+
+        return  success(versionService.getDetailById(id));
+    }
+
+    //@RequiresPermissions("system:version:download")
+    @GetMapping("/download/{id}")
+    public void download(HttpServletResponse response ,@PathVariable Long id) {
+        versionService.downloadFile(response,id);
+    }
+
+    @PostMapping("/checkUpdate")
+    public AjaxResult checkUpdate(@RequestBody SysCheckUpdateDto updateDto) {
+        SysCheckUpdateDto dto = versionService.checkUpdate(updateDto);
+        return success(dto);
+    }
+
+}

+ 29 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/dto/SysCheckUpdateDto.java

@@ -0,0 +1,29 @@
+package com.xunmei.system.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class SysCheckUpdateDto {
+
+    @ApiModelProperty(value = "当前版本")
+    private String currentVersion;
+
+    @ApiModelProperty(value = "平台类型")
+    private String typeDesc;
+
+    @ApiModelProperty(value = "是否有新版本")
+    private boolean needUpdate;
+
+    @ApiModelProperty(value = "是否强制更新")
+    private boolean isForce;
+
+    @ApiModelProperty(value = "下载地址")
+    private String downloadUrl;
+
+    @ApiModelProperty(value = "新版本")
+    private String newVersion;
+
+    @ApiModelProperty(value = "版本说明")
+    private String note;
+}

+ 11 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/mapper/SysVersionMapper.java

@@ -0,0 +1,11 @@
+package com.xunmei.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xunmei.system.api.domain.SysVersion;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface SysVersionMapper extends BaseMapper<SysVersion> {
+    void disabledOthers(@Param("id") Long id, @Param("type") Integer type);
+}

+ 31 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/service/ISysVersionService.java

@@ -0,0 +1,31 @@
+package com.xunmei.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.system.api.domain.SysVersion;
+import com.xunmei.system.dto.SysCheckUpdateDto;
+
+import javax.servlet.http.HttpServletResponse;
+
+public interface ISysVersionService extends IService<SysVersion> {
+
+    TableDataInfo<SysVersion> selectPage(SysVersion sysVersion);
+
+    AjaxResult insertVersion(SysVersion sysVersion);
+
+    AjaxResult updateVersion(SysVersion sysVersion);
+
+    /**
+     * 修改当前类型的升级包,其他版本的为未使用
+     * @param id
+     * @param type
+     */
+    void disabledOthers(Long id,Integer type);
+
+    SysVersion getDetailById(Long id);
+
+    void downloadFile(HttpServletResponse response, Long id);
+
+    SysCheckUpdateDto checkUpdate(SysCheckUpdateDto checkUpdateDto);
+}

+ 201 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/service/impl/SysVersionServiceImpl.java

@@ -0,0 +1,201 @@
+package com.xunmei.system.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xunmei.common.core.utils.StringUtils;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.system.api.RemoteFileService;
+import com.xunmei.system.api.domain.SysFile;
+import com.xunmei.system.api.domain.SysVersion;
+import com.xunmei.system.api.enums.AppType;
+import com.xunmei.system.dto.SysCheckUpdateDto;
+import com.xunmei.system.mapper.SysVersionMapper;
+import com.xunmei.system.service.ISysVersionService;
+import feign.Response;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.github.zafarkhaja.semver.Version;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.Date;
+import java.util.Objects;
+
+@Service
+public class SysVersionServiceImpl extends ServiceImpl<SysVersionMapper, SysVersion> implements ISysVersionService {
+
+    @Resource
+    private SysVersionMapper versionMapper;
+
+
+    @Resource
+    private RemoteFileService fileService;
+
+    @Override
+    public TableDataInfo<SysVersion> selectPage(SysVersion sysVersion) {
+        Page<SysVersion> page;
+        if (sysVersion.getPageNum() != null && sysVersion.getPageSize() != null) {
+            page = new Page<>(sysVersion.getPageNum(), sysVersion.getPageSize());
+        } else {
+            page = new Page<>();
+        }
+        QueryWrapper<SysVersion> wrapper = new QueryWrapper<>();
+        if (sysVersion.getType() != null ){
+            wrapper.eq("type",sysVersion.getType());
+        }
+        if (StringUtils.isNotEmpty(sysVersion.getVersion())){
+            wrapper.like("version",sysVersion.getVersion());
+        }
+        page = versionMapper.selectPage(page, wrapper);
+        return TableDataInfo.build(page);
+    }
+
+    @Transactional
+    @Override
+    public AjaxResult insertVersion(SysVersion sysVersion) {
+        //查询当前类型是否有当前版本
+        String msg = checkSameVersion(sysVersion,false);
+        if (StringUtils.isNotEmpty(msg)){
+            return AjaxResult.error(msg);
+        }
+
+        sysVersion.setCreateTime(new Date());
+        this.save(sysVersion);
+        if (sysVersion.getIsUse()){
+            disabledOthers(sysVersion.getId(),sysVersion.getType());
+        }
+        return AjaxResult.success();
+    }
+
+    @Transactional
+    @Override
+    public AjaxResult updateVersion(SysVersion sysVersion) {
+        //查询当前类型是否有当前版本
+        String msg = checkSameVersion(sysVersion,true);
+        if (StringUtils.isNotEmpty(msg)){
+            return AjaxResult.error(msg);
+        }
+
+        if (sysVersion.getId() != null){
+            sysVersion.setUpdateTime(new Date());
+            this.updateById(sysVersion);
+            if (sysVersion.getIsUse()){
+                disabledOthers(sysVersion.getId(),sysVersion.getType());
+            }
+        }
+        return AjaxResult.success();
+    }
+
+    @Override
+    public void disabledOthers(Long id, Integer type) {
+        versionMapper.disabledOthers(id,type);
+    }
+
+    @Override
+    public SysVersion getDetailById(Long id) {
+        return getById(id);
+    }
+
+    @Override
+    public void downloadFile(HttpServletResponse response, Long id){
+        InputStream inputStream = null;
+        BufferedInputStream bufferedInputStream = null;
+        BufferedOutputStream bufferedOutputStream = null;
+        try {
+            SysVersion version = getById(id);
+            if (null != version){
+                SysFile sysFile = new SysFile();
+                sysFile.setRealName(version.getPackageName());
+                sysFile.setUrl(version.getPath());
+                //Feign远程调用获取文件流
+                Response result = fileService.downloadFileRealName(sysFile);
+                Response.Body body = result.body();
+                inputStream = body.asInputStream();
+                bufferedInputStream = new BufferedInputStream(inputStream);
+                response.setHeader("Content-Type","application/octet-stream");
+                response.setHeader("Content-Disposition", result.headers().get("Content-Disposition").toString().replace("[", "").replace("]", ""));
+                bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
+                int length = 0;
+                byte[] temp = new byte[1024 * 10];
+                while ((length = bufferedInputStream.read(temp)) != -1) {
+                    bufferedOutputStream.write(temp, 0, length);
+                }
+                bufferedOutputStream.flush();
+                bufferedOutputStream.close();
+                bufferedInputStream.close();
+                inputStream.close();
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public SysCheckUpdateDto checkUpdate(SysCheckUpdateDto checkUpdateDto) {
+        SysCheckUpdateDto dto = new SysCheckUpdateDto();
+        dto.setNeedUpdate(false);
+        dto.setCurrentVersion(checkUpdateDto.getCurrentVersion());
+        dto.setTypeDesc(checkUpdateDto.getTypeDesc());
+        int type = -1;
+        switch (checkUpdateDto.getTypeDesc()){
+            case "APP":
+                type = AppType.APP.getIndex();
+                break;
+            case "PC":
+                type = AppType.PC.getIndex();
+                break;
+            case "IOS":
+                type = AppType.IOS.getIndex();
+                break;
+            case "HANG_WALL":
+                type = AppType.HANG_WALL.getIndex();
+                break;
+        }
+        if (type == -1){
+            return dto;
+        }
+        //使用的版本只有一个
+        QueryWrapper<SysVersion> wrapper = new QueryWrapper<>();
+        wrapper.eq("type",type);
+        wrapper.eq("is_use",1);
+        SysVersion version = getOne(wrapper);
+        if (null != version){
+            //判断终端版本是否小于等于使用版本
+            Version currentVersion = Version.valueOf(checkUpdateDto.getCurrentVersion());
+            Version useVersion = Version.valueOf(version.getVersion());
+            if (useVersion.compareTo(currentVersion) > 0){
+                //使用版本大于终端版本,需要升级
+                dto.setNeedUpdate(true);
+                dto.setForce(version.getIsForce());
+                dto.setNewVersion(version.getVersion());
+                dto.setNote(version.getNote());
+                dto.setDownloadUrl("/system/version/download/"+version.getId());
+                return dto;
+            }
+        }
+        return dto;
+    }
+
+    private String checkSameVersion(SysVersion sysVersion,boolean isUpdate){
+        //查询当前类型是否有当前版本
+        QueryWrapper<SysVersion> wrapper = new QueryWrapper<>();
+        wrapper.eq("type",sysVersion.getType());
+        wrapper.eq("version",sysVersion.getVersion());
+        //同一类型同一版本只有一条数据
+        SysVersion one = getOne(wrapper);
+        if (isUpdate){
+            if (null != one && !Objects.equals(one.getId(), sysVersion.getId())){
+                AppType appType = AppType.getEnumByIndex(sysVersion.getType());
+                return appType.getText() + " 终端已存在 " + sysVersion.getVersion() + " 版本包,请重新输入!";
+            }
+        }else {
+            if (null != one){
+                AppType appType = AppType.getEnumByIndex(sysVersion.getType());
+                return appType.getText() + " 终端已存在 " + sysVersion.getVersion() + " 版本包,请重新输入!";
+            }
+        }
+        return null;
+    }
+}

+ 10 - 0
soc-modules/soc-modules-system/src/main/resources/mapper/system/SysVersionMapper.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.system.mapper.SysVersionMapper">
+
+    <update id="disabledOthers">
+        update sys_version set is_use = 0 where id != #{id} and `type` = #{type}
+    </update>
+</mapper>