From dc4df86396b43c3102c87e5272274200a6f67c45 Mon Sep 17 00:00:00 2001 From: taohandong <2821744554@qq.com> Date: Wed, 26 Feb 2020 13:42:22 +0800 Subject: [PATCH] 优化定时服务和片网络图片映射 --- cloud/.gitignore | 3 +++ cloud/common/src/main/java/com/sincere/common/util/BaiduApiUtiols.java | 84 ------------------------------------------------------------------------------------ cloud/common/src/main/java/com/sincere/common/util/HttpClientUtils.java | 20 ++++++++++---------- cloud/fIle-center/pom.xml | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/FileApplication.java | 15 +++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/config/AliyunOSSConfig.java | 36 ++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/config/SwaggerConfig.java | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/control/FileControl.java | 42 ++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/model/FileInfo.java | 39 +++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/service/FileService.java | 24 ++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AbstractFileService.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AliyunOssServiceImpl.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/java/com/sincere/file/utils/FileUtil.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/resources/application.yml | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/fIle-center/src/main/resources/bootstrap.yml | 41 +++++++++++++++++++++++++++++++++++++++++ cloud/geteway/src/main/resources/application.yml | 7 +++++++ cloud/geteway/src/test/java/com/example/geteway/GetewayApplicationTests.java | 16 ---------------- cloud/haikangface/src/main/java/com/sincere/haikangface/control/UserControl.java | 5 +---- cloud/haikangface/src/main/java/com/sincere/haikangface/utils/BaiduApiUtiols.java | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/pom.xml | 29 +++++++++++++++++++++++++++-- cloud/server1/src/main/java/com/sincere/server1/listener/EurekaInstanceCanceledListener.java | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server1/src/main/resources/application.yaml | 22 ++++++++++++++-------- cloud/server1/src/main/view/templates/.keep | 0 cloud/server1/src/main/view/templates/eureka/.keep | 0 cloud/server1/src/main/view/templates/eureka/header.ftl | 26 ++++++++++++++++++++++++++ cloud/server1/src/main/view/templates/eureka/lastn.ftl | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server1/src/main/view/templates/eureka/navbar.ftl | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server1/src/main/view/templates/eureka/status.ftl | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server2/src/main/java/com/sincere/server2/listener/EurekaInstanceCanceledListener.java | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server2/src/main/resources/application.yaml | 23 +++++++++++++++-------- cloud/server2/src/main/view/templates/.keep | 0 cloud/server2/src/main/view/templates/eureka/.keep | 0 cloud/server2/src/main/view/templates/eureka/header.ftl | 26 ++++++++++++++++++++++++++ cloud/server2/src/main/view/templates/eureka/lastn.ftl | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server2/src/main/view/templates/eureka/navbar.ftl | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/server2/src/main/view/templates/eureka/status.ftl | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cloud/zkAttendance/src/main/java/com/sincere/att/AttApplication.java | 3 +++ 37 files changed, 1588 insertions(+), 132 deletions(-) delete mode 100644 cloud/common/src/main/java/com/sincere/common/util/BaiduApiUtiols.java create mode 100644 cloud/fIle-center/pom.xml create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/FileApplication.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/config/AliyunOSSConfig.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/config/SwaggerConfig.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/control/FileControl.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/model/FileInfo.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/service/FileService.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AbstractFileService.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AliyunOssServiceImpl.java create mode 100644 cloud/fIle-center/src/main/java/com/sincere/file/utils/FileUtil.java create mode 100644 cloud/fIle-center/src/main/resources/application.yml create mode 100644 cloud/fIle-center/src/main/resources/bootstrap.yml delete mode 100644 cloud/geteway/src/test/java/com/example/geteway/GetewayApplicationTests.java create mode 100644 cloud/haikangface/src/main/java/com/sincere/haikangface/utils/BaiduApiUtiols.java create mode 100644 cloud/server1/src/main/java/com/sincere/server1/listener/EurekaInstanceCanceledListener.java create mode 100644 cloud/server1/src/main/view/templates/.keep create mode 100644 cloud/server1/src/main/view/templates/eureka/.keep create mode 100644 cloud/server1/src/main/view/templates/eureka/header.ftl create mode 100644 cloud/server1/src/main/view/templates/eureka/lastn.ftl create mode 100644 cloud/server1/src/main/view/templates/eureka/navbar.ftl create mode 100644 cloud/server1/src/main/view/templates/eureka/status.ftl create mode 100644 cloud/server2/src/main/java/com/sincere/server2/listener/EurekaInstanceCanceledListener.java create mode 100644 cloud/server2/src/main/view/templates/.keep create mode 100644 cloud/server2/src/main/view/templates/eureka/.keep create mode 100644 cloud/server2/src/main/view/templates/eureka/header.ftl create mode 100644 cloud/server2/src/main/view/templates/eureka/lastn.ftl create mode 100644 cloud/server2/src/main/view/templates/eureka/navbar.ftl create mode 100644 cloud/server2/src/main/view/templates/eureka/status.ftl diff --git a/cloud/.gitignore b/cloud/.gitignore index a2a3040..738fbdd 100644 --- a/cloud/.gitignore +++ b/cloud/.gitignore @@ -29,3 +29,6 @@ build/ ### VS Code ### .vscode/ +/log/ +/out/ +/picPath/ \ No newline at end of file diff --git a/cloud/common/src/main/java/com/sincere/common/util/BaiduApiUtiols.java b/cloud/common/src/main/java/com/sincere/common/util/BaiduApiUtiols.java deleted file mode 100644 index 63a0785..0000000 --- a/cloud/common/src/main/java/com/sincere/common/util/BaiduApiUtiols.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.sincere.common.util; - -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -public class BaiduApiUtiols { - - public static BaiduApiUtiols baiduApiUtiols; - - public static BaiduApiUtiols getInstance() { - - if (null == baiduApiUtiols) { - synchronized (BaiduApiUtiols.class) { - baiduApiUtiols = new BaiduApiUtiols(); - } - } - return baiduApiUtiols; - } - - - /** - * @param imgPath 图片路径 - * @param group_id 学校id - * @param user_id 用户id - * @param user_info 用户名字 - * @return - */ - public String registerFace(String imgPath, String group_id, String user_id, String user_info) { - - String registUrl = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=" + AuthService.getFaceAuthToken(); - long time = System.currentTimeMillis(); - System.out.println("starttime:"+time); - RestTemplate restTemplate = new RestTemplate(); - MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); - multiValueMap.add("image", Base64Util.imageencode(imgPath)); - multiValueMap.add("image_type", "BASE64"); - multiValueMap.add("group_id", group_id); - multiValueMap.add("user_id", user_id); - multiValueMap.add("user_info", user_info); -// multiValueMap.add("quality_control", "NORMAL"); - System.out.println("multiValueMap:" + multiValueMap.toString()); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - HttpEntity requestEntity = new HttpEntity(multiValueMap, - headers); - System.out.println("midddle:"+(System.currentTimeMillis()-time)); - time = System.currentTimeMillis(); - ResponseEntity result = restTemplate.postForEntity(registUrl, requestEntity, String.class); - System.out.println("end:"+(System.currentTimeMillis()-time)); - System.out.println("result:" + result.getBody()); - return result.getBody(); - - } - - public String searchFace(String imgPath,String group_id, String user_id){ - String searchFace = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token="+AuthService.getFaceAuthToken(); - long time = System.currentTimeMillis(); - RestTemplate restTemplate = new RestTemplate(); - MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); - multiValueMap.add("image", Base64Util.imageencode(imgPath)); - multiValueMap.add("image_type", "BASE64"); - multiValueMap.add("group_id_list", group_id);//从指定的group中进行查找 用逗号分隔,上限10个 - multiValueMap.add("user_id", user_id);//当需要对特定用户进行比对时,指定user_id进行比对。即人脸认证功能。 -// multiValueMap.add("quality_control", "NORMAL"); - System.out.println("multiValueMap:" + multiValueMap.toString()); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - HttpEntity requestEntity = new HttpEntity(multiValueMap, - headers); - System.out.println("midddle:"+(System.currentTimeMillis()-time)); - time = System.currentTimeMillis(); - ResponseEntity result = restTemplate.postForEntity(searchFace, requestEntity, String.class); - System.out.println("end:"+(System.currentTimeMillis()-time)); - System.out.println("result:" + result.getBody()); - return result.getBody(); - - } - -} diff --git a/cloud/common/src/main/java/com/sincere/common/util/HttpClientUtils.java b/cloud/common/src/main/java/com/sincere/common/util/HttpClientUtils.java index 1167426..e8cde6b 100644 --- a/cloud/common/src/main/java/com/sincere/common/util/HttpClientUtils.java +++ b/cloud/common/src/main/java/com/sincere/common/util/HttpClientUtils.java @@ -40,17 +40,17 @@ public class HttpClientUtils { requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build(); } - public static void main(String[] args){ -// String url = "http://http://zhktest.114school.com.cn/szkjapi/toyxy/addTeacherOrg" ; -// String json = "{\"name\": \"子部门\",\"groupname\": \"父部门\",\"schoolid\": \"16\",\"token\": \"05719991\"}" ; -// JSONObject jsonObject = HttpClientUtils.httpPostJson(url,json); +// public static void main(String[] args){ +//// String url = "http://http://zhktest.114school.com.cn/szkjapi/toyxy/addTeacherOrg" ; +//// String json = "{\"name\": \"子部门\",\"groupname\": \"父部门\",\"schoolid\": \"16\",\"token\": \"05719991\"}" ; +//// JSONObject jsonObject = HttpClientUtils.httpPostJson(url,json); +//// System.out.println(jsonObject.toJSONString()); +// +// String url = "http://campus.myjxt.com/api/Room/GetListPageRoom" ; +// String json = "PageIndex=1&roomId=6583&pageSize=9999" ; +// JSONObject jsonObject = HttpClientUtils.httpPost(url,json); // System.out.println(jsonObject.toJSONString()); - - String url = "http://campus.myjxt.com/api/Room/GetListPageRoom" ; - String json = "PageIndex=1&roomId=6583&pageSize=9999" ; - JSONObject jsonObject = HttpClientUtils.httpPost(url,json); - System.out.println(jsonObject.toJSONString()); - } +// } /** * post请求传输json参数 diff --git a/cloud/fIle-center/pom.xml b/cloud/fIle-center/pom.xml new file mode 100644 index 0000000..b41f19a --- /dev/null +++ b/cloud/fIle-center/pom.xml @@ -0,0 +1,48 @@ + + + + cloud + com.sincere + 1.0.0 + + 4.0.0 + + fIle-center + + 文件中心 + + + 2.9.2 + + + + + + + io.springfox + springfox-swagger-ui + ${swagger-version} + + + io.springfox + springfox-swagger2 + ${swagger-version} + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.aliyun.oss + aliyun-sdk-oss + 2.8.3 + + + + + \ No newline at end of file diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/FileApplication.java b/cloud/fIle-center/src/main/java/com/sincere/file/FileApplication.java new file mode 100644 index 0000000..c4509f6 --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/FileApplication.java @@ -0,0 +1,15 @@ +package com.sincere.file; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +@EnableDiscoveryClient +@SpringBootApplication +public class FileApplication { + + public static void main(String[] args) { + SpringApplication.run(FileApplication.class,args); + } +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/config/AliyunOSSConfig.java b/cloud/fIle-center/src/main/java/com/sincere/file/config/AliyunOSSConfig.java new file mode 100644 index 0000000..6b151eb --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/config/AliyunOSSConfig.java @@ -0,0 +1,36 @@ +package com.sincere.file.config; + +import com.aliyun.oss.OSSClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +/** + * @author 作者 owen E-mail: 624191343@qq.com + * @version 创建时间:2018年1月31日 下午9:11:36 类说明 白名单 + * 阿里云配置 + */ +@Configuration +public class AliyunOSSConfig { + + @Value("${aliyun.oss.endpoint:xxxxx}") + private String endpoint; + @Value("${aliyun.oss.access-key:xxxxx}") + private String accessKeyId; + @Value("${aliyun.oss.accessKeySecret:xxxxx}") + private String accessKeySecret; + + /** + * 阿里云文件存储client + * 只有配置了aliyun.oss.access-key才可以使用 + */ + @Bean + @ConditionalOnProperty(name = "aliyun.oss.access-key", matchIfMissing = true) + public OSSClient ossClient() { + OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); + return ossClient; + } + +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/config/SwaggerConfig.java b/cloud/fIle-center/src/main/java/com/sincere/file/config/SwaggerConfig.java new file mode 100644 index 0000000..b1dd9af --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/config/SwaggerConfig.java @@ -0,0 +1,89 @@ +package com.sincere.file.config; + +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Parameter; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.ArrayList; +import java.util.List; + +@Component +@Configuration +@EnableSwagger2 +public class SwaggerConfig implements WebMvcConfigurer { + + @Bean + public Docket createRestApi() { + + + ParameterBuilder tokenPar = new ParameterBuilder(); + List pars = new ArrayList<>(); + tokenPar.name("ossPath").description("OSS存储路径,例如: YikeData"). + modelRef(new ModelRef("string")). + parameterType("header").required(false).build(); + + pars.add(tokenPar.build()); + + return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() + .apis(RequestHandlerSelectors.basePackage("com.sincere.file.control")) +// .apis(RequestHandlerSelectors.any()) +// .paths( input ->PathSelectors.regex("/file/*").apply(input) || PathSelectors.regex("/fileinfo.*").apply(input) +// ) + .paths(PathSelectors.any()) + .build().globalOperationParameters(pars); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder().title("文件中心api").description("文件中心api").version("1.0").build(); + } + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setViewClass(JstlView.class); + resolver.setPrefix("/"); + resolver.setSuffix(".html"); + return resolver; + + } + + @Bean + public MessageSource messageSource() { + ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("messages"); + return messageSource; + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { +// super.addResourceHandlers(registry); + registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + + +} \ No newline at end of file diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/control/FileControl.java b/cloud/fIle-center/src/main/java/com/sincere/file/control/FileControl.java new file mode 100644 index 0000000..5348595 --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/control/FileControl.java @@ -0,0 +1,42 @@ +package com.sincere.file.control; + +import com.sincere.file.model.FileInfo; +import com.sincere.file.service.FileService; +import com.sincere.file.utils.FileUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; + +@RestController +@Api(tags = "文件管理") +@RequestMapping(value = "file/*") +public class FileControl { + + @Autowired + FileService fileService; + + @PostMapping("fileUpload") + @ApiOperation("上传文件") + public String fileUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception { + + String ossPath = request.getHeader("ossPath");//oss的二级目录 + + FileInfo fileInfo = fileService.upload(file, ossPath); + + return fileInfo.getUrl(); + + } + + + @DeleteMapping("deleteFile/{fileName}") + @ApiOperation("删除文件") + public boolean deleteFile(@PathVariable String fileName,HttpServletRequest request){ + String ossPath = request.getHeader("ossPath");//oss的二级目录 + fileService.delete(fileName,ossPath); + return true; + } +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/model/FileInfo.java b/cloud/fIle-center/src/main/java/com/sincere/file/model/FileInfo.java new file mode 100644 index 0000000..66df809 --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/model/FileInfo.java @@ -0,0 +1,39 @@ +package com.sincere.file.model; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author 作者 owen E-mail: 624191343@qq.com + * @version 创建时间:2017年11月12日 上午22:57:51 + * file实体类 +*/ +@Data +public class FileInfo implements Serializable { + + private static final long serialVersionUID = -1438078028040922174L; +// md5字段 + private String id; +// 原始文件名 + private String name; +// 是否图片 + private Boolean isImg; +// 上传文件类型 + private String contentType; +// 文件大小 + private long size; +// 冗余字段 + private String path; +// oss访问路径 oss需要设置公共读 + private String url; +// FileType字段 + private String source; + private Date createTime; + /** + * 目录磁盘地址 + */ +// @TableField(exist = false) +// private String pathDir; +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/service/FileService.java b/cloud/fIle-center/src/main/java/com/sincere/file/service/FileService.java new file mode 100644 index 0000000..c78b92e --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/service/FileService.java @@ -0,0 +1,24 @@ +package com.sincere.file.service; + +import com.sincere.file.model.FileInfo; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; + +/** + * @author 作者 owen E-mail: 624191343@qq.com + * @version 创建时间:2017年11月12日 上午22:57:51 + * 文件service 目前仅支持阿里云oss,七牛云 +*/ +public interface FileService { + + FileInfo upload(MultipartFile file,String filePath) throws Exception; + + void delete(String fileName,String filePath); + + FileInfo getById(String id); + +// PageResult findList(Map params); + + void unZip(String filePath, String descDir) throws RuntimeException ; +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AbstractFileService.java b/cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AbstractFileService.java new file mode 100644 index 0000000..4cac6ca --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AbstractFileService.java @@ -0,0 +1,88 @@ +package com.sincere.file.service.impl; + +import com.sincere.file.model.FileInfo; +import com.sincere.file.service.FileService; +import com.sincere.file.utils.FileUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author 作者 owen E-mail: 624191343@qq.com + * @version 创建时间:2017年11月12日 上午22:57:51 + * AbstractFileService 抽取类 + * 根据filetype 实例化具体oss对象 +*/ +@Slf4j +public abstract class AbstractFileService implements FileService { + +// protected abstract FileDao getFileDao(); + protected static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + @Override + public FileInfo upload(MultipartFile file,String filePath) throws Exception { + FileInfo fileInfo = FileUtil.getFileInfo(file); +// FileInfo oldFileInfo = getFileDao().getById(fileInfo.getId()); +// if (oldFileInfo != null) { +// return oldFileInfo; +// } +// +// if (!fileInfo.getName().contains(".")) { +// throw new IllegalArgumentException("缺少后缀名"); +// } + + uploadFile(file, fileInfo,filePath); + +// fileInfo.setSource(fileType().name());// 设置文件来源 +// getFileDao().save(fileInfo);// 将文件信息保存到数据库 +// // 本地保存文件 +// FileUtil.saveFile(file,fileInfo.getPath()); +// log.info("上传文件:{}", fileInfo); + + return fileInfo; + } + + /** + * 上传文件 + * + * @param file + * @param fileInfo + */ + protected abstract void uploadFile(MultipartFile file, FileInfo fileInfo,String filePath) throws Exception; + + @Override + public void delete(String fileName,String filePath) { + deleteFile(fileName,filePath); +// getFileDao().delete(fileInfo.getId()); + log.info("删除文件:{}", fileName); + } + + /** + * 删除文件资源 + * +// * @param fileInfo + * @return + */ + protected abstract boolean deleteFile(String fileName,String filePath); + + @Override + public FileInfo getById(String id){ +// return getFileDao().getById(id); + return null; + } + +// public PageResult findList(Map params){ +// //设置分页信息,分别是当前页数和每页显示的总记录数【记住:必须在mapper接口中的方法执行之前设置该分页信息】 +// PageHelper.startPage(MapUtils.getInteger(params, "page"),MapUtils.getInteger(params, "limit"),true); +// +// List list = getFileDao().findList(params); +// PageInfo pageInfo = new PageInfo<>(list); +// return PageResult.builder().data(pageInfo.getList()).code(0).count(pageInfo.getTotal()).build(); +// } + + @Override + public void unZip(String filePath, String descDir) throws RuntimeException { + + } +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AliyunOssServiceImpl.java b/cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AliyunOssServiceImpl.java new file mode 100644 index 0000000..cb3863b --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/service/impl/AliyunOssServiceImpl.java @@ -0,0 +1,51 @@ +package com.sincere.file.service.impl; + +import com.aliyun.oss.OSSClient; +import com.sincere.file.model.FileInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author 作者 owen E-mail: 624191343@qq.com + * @version 创建时间:2017年11月12日 上午22:57:51 +* 阿里云oss存储文件 +*/ +@Service("aliyunOssServiceImpl") +public class AliyunOssServiceImpl extends AbstractFileService { + +// @Autowired +// private FileDao fileDao; + +// @Override +// protected FileDao getFileDao() { +// return fileDao; +// } + +// @Override +// protected FileType fileType() { +// return FileType.ALIYUN; +// } + + @Autowired + private OSSClient ossClient; + + @Value("${aliyun.oss.bucketName:xxxxx}") + private String bucketName; + @Value("${aliyun.oss.domain:xxxxx}") + private String domain; + + @Override + protected void uploadFile(MultipartFile file, FileInfo fileInfo,String filePath) throws Exception { + ossClient.putObject(bucketName, filePath+"/"+fileInfo.getName(), file.getInputStream()); + fileInfo.setUrl(domain + "/" + fileInfo.getName()); + } + + @Override + protected boolean deleteFile(String fileName,String filePath) { + ossClient.deleteObject(bucketName,filePath+"/"+ fileName); + return true; + } + +} diff --git a/cloud/fIle-center/src/main/java/com/sincere/file/utils/FileUtil.java b/cloud/fIle-center/src/main/java/com/sincere/file/utils/FileUtil.java new file mode 100644 index 0000000..18e238c --- /dev/null +++ b/cloud/fIle-center/src/main/java/com/sincere/file/utils/FileUtil.java @@ -0,0 +1,88 @@ +package com.sincere.file.utils; + +import com.sincere.file.model.FileInfo; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; + +/** + * @author 作者 owen E-mail: 624191343@qq.com + * @version 创建时间:2017年11月12日 上午22:57:51 + * 文件工具类 +*/ +@Slf4j +public class FileUtil { + + public static FileInfo getFileInfo(MultipartFile file) throws Exception { + String md5 = fileMd5(file.getInputStream()); + + FileInfo fileInfo = new FileInfo(); + fileInfo.setId(md5);// 将文件的md5设置为文件表的id + fileInfo.setName(file.getOriginalFilename()); + fileInfo.setContentType(file.getContentType()); + fileInfo.setIsImg(fileInfo.getContentType().startsWith("image/")); + fileInfo.setSize(file.getSize()); + fileInfo.setCreateTime(new Date()); + + return fileInfo; + } + + /** + * 文件的md5 + * + * @param inputStream + * @return + */ + public static String fileMd5(InputStream inputStream) { + try { + return DigestUtils.md5Hex(inputStream); + } catch (IOException e) { + log.error("FileUtil->fileMd5:{}" ,e.getMessage()); + } + + return null; + } + + public static String saveFile(MultipartFile file, String path) { + try { + File targetFile = new File(path); + if (targetFile.exists()) { + return path; + } + + if (!targetFile.getParentFile().exists()) { + targetFile.getParentFile().mkdirs(); + } + file.transferTo(targetFile); + + return path; + } catch (Exception e) { + log.error("FileUtil->saveFile:{}" ,e.getMessage()); + } + + return null; + } + + public static boolean deleteFile(String pathname) { + File file = new File(pathname); + if (file.exists()) { + boolean flag = file.delete(); + + if (flag) { + File[] files = file.getParentFile().listFiles(); + if (files == null || files.length == 0) { + file.getParentFile().delete(); + } + } + + return flag; + } + + return false; + } +} diff --git a/cloud/fIle-center/src/main/resources/application.yml b/cloud/fIle-center/src/main/resources/application.yml new file mode 100644 index 0000000..c54fb4a --- /dev/null +++ b/cloud/fIle-center/src/main/resources/application.yml @@ -0,0 +1,181 @@ +#阿里云文件上传 +aliyun: + oss: + access-key: QiuM3PwHTnVotcGy + accessKeySecret: Yqs7RlaC1MioZu2YYJ6u0TdeO13VFC + endpoint: http://oss-cn-hangzhou.aliyuncs.com + bucketName: szyundisk + domain: https://szyundisk.oss-cn-hangzhou.aliyuncs.com +##七牛文件上传 +#qiniu: +# oss: +# access-key: owGiAWGn6DpU5zlrfLP4K9iQusahmspTW6PxRABW +# accessKeySecret: 5CBWKFd1pP-OSiusd1Bvhokp-ih4i3bs2QA2r-U2 +# endpoint: http://q4c5xw7eb.bkt.clouddn.com +# bucketName: ocpowenwangwen +## 本地文件上传 +#file: +# oss: +# domain: http://127.0.0.1:9200/api-file +# path: d:/uploadshp +# prefix: /statics + +#fastDFS配置 +#fdfs: +# oss : +# ##nginx需要安装fastdfs插件 +# domain: http://192.168.235.173/ +# soTimeout: 1500 +# connectTimeout: 600 +# pool: +# jmx-enabled: false +# trackerList: 192.168.235.173:22122 + + +#spring: +# datasource: +# dynamic: +# enable: true +# druid: +# # JDBC 配置(驱动类自动从url的mysql识别,数据源类型自动识别) +# core: +# url: jdbc:mysql://localhost:3306/file_center?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false +# username: root +# password: 123456 +# driver-class-name: com.mysql.cj.jdbc.Driver +# log: +# url: jdbc:mysql://localhost:3306/log_center?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false +# username: root +# password: 123456 +# driver-class-name: com.mysql.cj.jdbc.Driver +# #连接池配置(通常来说,只需要修改initialSize、minIdle、maxActive +# initial-size: 1 +# max-active: 20 +# min-idle: 1 +# # 配置获取连接等待超时的时间 +# max-wait: 60000 +# #打开PSCache,并且指定每个连接上PSCache的大小 +# pool-prepared-statements: true +# max-pool-prepared-statement-per-connection-size: 20 +# validation-query: SELECT 'x' +# test-on-borrow: false +# test-on-return: false +# test-while-idle: true +# #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 +# time-between-eviction-runs-millis: 60000 +# #配置一个连接在池中最小生存的时间,单位是毫秒 +# min-evictable-idle-time-millis: 300000 +# filters: stat,wall +# # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter +# #是否启用StatFilter默认值true +# web-stat-filter.enabled: true +# web-stat-filter.url-pattern: /* +# web-stat-filter.exclusions: "*.js , *.gif ,*.jpg ,*.png ,*.css ,*.ico , /druid/*" +# web-stat-filter.session-stat-max-count: 1000 +# web-stat-filter.profile-enable: true +# # StatViewServlet配置 +# #展示Druid的统计信息,StatViewServlet的用途包括:1.提供监控信息展示的html页面2.提供监控信息的JSON API +# #是否启用StatViewServlet默认值true +# stat-view-servlet.enabled: true +# #根据配置中的url-pattern来访问内置监控页面,如果是上面的配置,内置监控页面的首页是/druid/index.html例如: +# #http://110.76.43.235:9000/druid/index.html +# #http://110.76.43.235:8080/mini-web/druid/index.html +# stat-view-servlet.url-pattern: /druid/* +# #允许清空统计数据 +# stat-view-servlet.reset-enable: true +# stat-view-servlet.login-username: admin +# stat-view-servlet.login-password: admin +# #StatViewSerlvet展示出来的监控信息比较敏感,是系统运行的内部情况,如果你需要做访问控制,可以配置allow和deny这两个参数 +# #deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝。如果allow没有配置或者为空,则允许所有访问 +# #配置的格式 +# # +# #或者/其中128.242.127.1/24 +# #24表示,前面24位是子网掩码,比对的时候,前面24位相同就匹配,不支持IPV6。 +# #stat-view-servlet.allow= +# #stat-view-servlet.deny=128.242.127.1/24,128.242.128.1 +# # Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置 +# #aop-patterns= # Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔 +#################### mysq end ########################## +## zipkin: +## base-url: http://127.0.0.1:11008 +# redis: +#################### redis 单机版 start ########################## +# host: 127.0.0.1 +# port: 6379 +# timeout: 6000 +# database: 1 +# lettuce: +# pool: +# max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) +# max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8 +# max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException +# min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0 +# shutdown-timeout: 100ms +#################### redis 单机版 end ########################## +## cluster: +## nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 +## #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 +## #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 +## timeout: 1000 # 连接超时时间(毫秒) +## lettuce: +## pool: +## max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) +## max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8 +## max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException +## min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0 +## shutdown-timeout: 100ms +# +##mybatis: +#mybatis-plus: +# configuration: +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +# config-location: classpath:mybatis.cfg.xml +# mapper-locations: classpath*:com/open/**/dao/*.xml +# +# +#security: +# oauth2: +# ignored: /files-anon/** , /doc.html ,/upload.html , /uploads.html ,/js/** ,/document.html +# token: +# store: +# type: redis + + +#设置最大超时时间 +ribbon: + httpclient: + enabled: false + okhttp: + enabled: true + ReadTimeout: 90000 + ConnectTimeout: 90000 + OkToRetryOnAllOperations: true + MaxAutoRetries: 1 + MaxAutoRetriesNextServer: 1 + + +#设置最大容错超时时间 +hystrix: + command: + default: + execution: + timeout: + enabled: true + isolation: + thread: + timeoutInMilliseconds: 90000 + + + +#logging: +# level: +# com.open.capacity: INFO +# org.hibernate: INFO +# org.hibernate.type.descriptor.sql.BasicBinder: TRACE +# org.hibernate.type.descriptor.sql.BasicExtractor: TRACE +# com.neusoft: DEBUG +# com.netflix: DEBUG #用于心跳检测输出的日志 + + + + \ No newline at end of file diff --git a/cloud/fIle-center/src/main/resources/bootstrap.yml b/cloud/fIle-center/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..0365757 --- /dev/null +++ b/cloud/fIle-center/src/main/resources/bootstrap.yml @@ -0,0 +1,41 @@ +#端口 +server: + port: 5000 #固定端口 +# port: ${randomServerPort.value[5000,5005]} #随机端口 + +#服务名称 +spring: + application: + name: file-center + servlet: + multipart: + max-request-size: 400MB + max-file-size: 400MB + +management: + endpoints: + web: + exposure: + include: "*" + endpoint: + health: + show-details: always + +#eureka client配置 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ + #http://134.224.249.33:1111/eureka/ 正式库 + #http://134.224.249.33:1111/eureka/ 测试库 + #http://127.0.0.1:8761/eureka,http://127.0.0.1:8762/eureka + registry-fetch-interval-seconds: 5 + instance-info-replication-interval-seconds: 10 + instance: + prefer-ip-address: true + instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} #固定端口 +# instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${randomServerPort.value[5000,5005]}} #随机端口 + lease-renewal-interval-in-seconds: 10 #每隔几秒告诉eureka服务器我还存活,用于心跳检测 + lease-expiration-duration-in-seconds: 10 #如果心跳检测一直没有发送,10秒后会从eureka服务器中将此服务剔除 + status-page-url: http://${spring.cloud.client.ip-address}:${server.port}/doc.html # ${server.port}为该服务的端口号 +# status-page-url: http://${spring.cloud.client.ip-address}:${randomServerPort.value[5000,5005]}/document.html # ${server.port}为该服务的端口号 \ No newline at end of file diff --git a/cloud/geteway/src/main/resources/application.yml b/cloud/geteway/src/main/resources/application.yml index cdf80c1..526d4b4 100644 --- a/cloud/geteway/src/main/resources/application.yml +++ b/cloud/geteway/src/main/resources/application.yml @@ -10,6 +10,7 @@ eureka: lease-expiration-duration-in-seconds: 90 lease-renewal-interval-in-seconds: 10 prefer-ip-address: true + instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} #固定端口 spring: cloud: @@ -21,3 +22,9 @@ spring: - Path=/haikangserver/** filters: - StripPrefix=1 + - id: file-center + uri: lb://file-center + predicates: + - Path=/file-center/** + filters: + - StripPrefix=1 \ No newline at end of file diff --git a/cloud/geteway/src/test/java/com/example/geteway/GetewayApplicationTests.java b/cloud/geteway/src/test/java/com/example/geteway/GetewayApplicationTests.java deleted file mode 100644 index 178a5a1..0000000 --- a/cloud/geteway/src/test/java/com/example/geteway/GetewayApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.geteway; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class GetewayApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/cloud/haikangface/src/main/java/com/sincere/haikangface/control/UserControl.java b/cloud/haikangface/src/main/java/com/sincere/haikangface/control/UserControl.java index 1084b8a..e46d019 100644 --- a/cloud/haikangface/src/main/java/com/sincere/haikangface/control/UserControl.java +++ b/cloud/haikangface/src/main/java/com/sincere/haikangface/control/UserControl.java @@ -1,8 +1,7 @@ package com.sincere.haikangface.control; -import com.netflix.ribbon.proxy.annotation.Http; import com.sincere.common.dto.smartCampus.SZ_AttendanceDto; -import com.sincere.common.util.BaiduApiUtiols; +import com.sincere.haikangface.utils.BaiduApiUtiols; import com.sincere.haikangface.CMSServer; import com.sincere.haikangface.async.SendUserAsync; import com.sincere.haikangface.bean.StudentBean; @@ -23,10 +22,8 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import sun.rmi.runtime.Log; import java.io.*; -import java.math.BigInteger; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; diff --git a/cloud/haikangface/src/main/java/com/sincere/haikangface/utils/BaiduApiUtiols.java b/cloud/haikangface/src/main/java/com/sincere/haikangface/utils/BaiduApiUtiols.java new file mode 100644 index 0000000..9316495 --- /dev/null +++ b/cloud/haikangface/src/main/java/com/sincere/haikangface/utils/BaiduApiUtiols.java @@ -0,0 +1,86 @@ +package com.sincere.haikangface.utils; + +import com.sincere.common.util.AuthService; +import com.sincere.common.util.Base64Util; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +public class BaiduApiUtiols { + + public static BaiduApiUtiols baiduApiUtiols; + + public static BaiduApiUtiols getInstance() { + + if (null == baiduApiUtiols) { + synchronized (BaiduApiUtiols.class) { + baiduApiUtiols = new BaiduApiUtiols(); + } + } + return baiduApiUtiols; + } + + + /** + * @param imgPath 图片路径 + * @param group_id 学校id + * @param user_id 用户id + * @param user_info 用户名字 + * @return + */ + public String registerFace(String imgPath, String group_id, String user_id, String user_info) { + + String registUrl = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=" + AuthService.getFaceAuthToken(); + long time = System.currentTimeMillis(); + System.out.println("starttime:"+time); + RestTemplate restTemplate = new RestTemplate(); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.add("image", Base64Util.imageencode(imgPath)); + multiValueMap.add("image_type", "BASE64"); + multiValueMap.add("group_id", group_id); + multiValueMap.add("user_id", user_id); + multiValueMap.add("user_info", user_info); +// multiValueMap.add("quality_control", "NORMAL"); + System.out.println("multiValueMap:" + multiValueMap.toString()); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity requestEntity = new HttpEntity(multiValueMap, + headers); + System.out.println("midddle:"+(System.currentTimeMillis()-time)); + time = System.currentTimeMillis(); + ResponseEntity result = restTemplate.postForEntity(registUrl, requestEntity, String.class); + System.out.println("end:"+(System.currentTimeMillis()-time)); + System.out.println("result:" + result.getBody()); + return result.getBody(); + + } + + public String searchFace(String imgPath,String group_id, String user_id){ + String searchFace = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token="+AuthService.getFaceAuthToken(); + long time = System.currentTimeMillis(); + RestTemplate restTemplate = new RestTemplate(); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.add("image", Base64Util.imageencode(imgPath)); + multiValueMap.add("image_type", "BASE64"); + multiValueMap.add("group_id_list", group_id);//从指定的group中进行查找 用逗号分隔,上限10个 + multiValueMap.add("user_id", user_id);//当需要对特定用户进行比对时,指定user_id进行比对。即人脸认证功能。 +// multiValueMap.add("quality_control", "NORMAL"); + System.out.println("multiValueMap:" + multiValueMap.toString()); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity requestEntity = new HttpEntity(multiValueMap, + headers); + System.out.println("midddle:"+(System.currentTimeMillis()-time)); + time = System.currentTimeMillis(); + ResponseEntity result = restTemplate.postForEntity(searchFace, requestEntity, String.class); + System.out.println("end:"+(System.currentTimeMillis()-time)); + System.out.println("result:" + result.getBody()); + return result.getBody(); + + } + +} diff --git a/cloud/pom.xml b/cloud/pom.xml index e18b4eb..7d5c73d 100644 --- a/cloud/pom.xml +++ b/cloud/pom.xml @@ -41,7 +41,8 @@ - + zkAttendance + fIle-center @@ -90,7 +91,12 @@ commons-io 2.6 - + + org.springframework.boot + spring-boot-starter-test + test + 2.0.2.RELEASE + @@ -118,4 +124,23 @@ + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + ${project.artifactId} + diff --git a/cloud/server1/src/main/java/com/sincere/server1/listener/EurekaInstanceCanceledListener.java b/cloud/server1/src/main/java/com/sincere/server1/listener/EurekaInstanceCanceledListener.java new file mode 100644 index 0000000..32b9f5e --- /dev/null +++ b/cloud/server1/src/main/java/com/sincere/server1/listener/EurekaInstanceCanceledListener.java @@ -0,0 +1,59 @@ +package com.sincere.server1.listener; + + +import com.netflix.discovery.shared.Applications; +import com.netflix.eureka.EurekaServerContextHolder; +import com.netflix.eureka.registry.PeerAwareInstanceRegistry; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Configuration; + +/** + * 用于监听eureka服务停机通知 + * Created by ace on 2017/7/8. + */ +@Slf4j +@Configuration +public class EurekaInstanceCanceledListener implements ApplicationListener { + @Override + public void onApplicationEvent(ApplicationEvent applicationEvent) { + // 服务挂掉事件 + if (applicationEvent instanceof EurekaInstanceCanceledEvent) { + EurekaInstanceCanceledEvent event = (EurekaInstanceCanceledEvent) applicationEvent; + // 获取当前Eureka实例中的节点信息 + PeerAwareInstanceRegistry registry = EurekaServerContextHolder.getInstance().getServerContext().getRegistry(); + Applications applications = registry.getApplications(); + // 遍历获取已注册节点中与当前失效节点ID一致的节点信息 + applications.getRegisteredApplications().forEach((registeredApplication) -> { + registeredApplication.getInstances().forEach((instance) -> { + if (instance.getInstanceId().equals(event.getServerId())) { + log.debug("服务:" + instance.getAppName() + " 挂啦。。。"); + // // TODO: 2017/9/3 扩展消息提醒 邮件、手机短信、微信等 + } + }); + }); + + + } + if (applicationEvent instanceof EurekaInstanceRegisteredEvent) { + EurekaInstanceRegisteredEvent event = (EurekaInstanceRegisteredEvent) applicationEvent; + log.debug("服务:" + event.getInstanceInfo().getAppName() + " 注册成功啦。。。"); + } + if (applicationEvent instanceof EurekaInstanceRenewedEvent) { + EurekaInstanceRenewedEvent event = (EurekaInstanceRenewedEvent) applicationEvent; + log.debug("心跳检测服务:" + event.getInstanceInfo().getAppName() + "。。"); + } + if (applicationEvent instanceof EurekaRegistryAvailableEvent) { + log.debug("服务 Aualiable。。"); + } + + } + + +} + diff --git a/cloud/server1/src/main/resources/application.yaml b/cloud/server1/src/main/resources/application.yaml index c66ed43..0cfd351 100644 --- a/cloud/server1/src/main/resources/application.yaml +++ b/cloud/server1/src/main/resources/application.yaml @@ -9,22 +9,28 @@ spring: eureka: instance: - preferIpAddress: true # 注册周期心跳 默认30s 这里改成5s 建议生成环境使用默认值30 lease-renewal-interval-in-seconds: 10 lease-expiration-duration-in-seconds: 60 - hostname: localhost + prefer-ip-address: true server: #是否开启保护模式 - enable-self-preservation: true - eviction-interval-timer-in-ms: 4000 + enable-self-preservation: false #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 + eviction-interval-timer-in-ms: 4000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除# #当进入保护模式的情况下,注册中心不会注销服务,以兼容分区故障 - renewal-percent-threshold: 0.5 + renewal-percent-threshold: 0.5 # 指定每分钟需要收到的续约次数的阈值,默认值就是:0.85 + response-cache-update-interval-ms: 3000 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s + response-cache-auto-expiration-in-seconds: 180 #eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。 client: #是否注册eureka,高可用的清况下使用 - register-with-eureka: true + register-with-eureka: true #false:不作为一个客户端注册到注册中心,是否将自身的实例信息注册到eureka服务器 #是否启用获取服务注册信息 - fetch-registry: true + fetch-registry: false #为true时,可以启动,但报异常:Cannot execute request on any known server ,是否从eureka服务端获取注册信息,消费者需要配置true + instance-info-replication-interval-seconds: 10 + registry-fetch-interval-seconds: 30 #从eureka服务端获取注册信息的间隔时间 service-url: - defaultZone: http://localhost:8762/eureka/ \ No newline at end of file + defaultZone: http://localhost:8762/eureka/ + +ribbon: + ServerListRefreshInterval: 1000 #刷新服务列表源的间隔时间 diff --git a/cloud/server1/src/main/view/templates/.keep b/cloud/server1/src/main/view/templates/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cloud/server1/src/main/view/templates/.keep diff --git a/cloud/server1/src/main/view/templates/eureka/.keep b/cloud/server1/src/main/view/templates/eureka/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cloud/server1/src/main/view/templates/eureka/.keep diff --git a/cloud/server1/src/main/view/templates/eureka/header.ftl b/cloud/server1/src/main/view/templates/eureka/header.ftl new file mode 100644 index 0000000..d6584bd --- /dev/null +++ b/cloud/server1/src/main/view/templates/eureka/header.ftl @@ -0,0 +1,26 @@ +<#import "/spring.ftl" as spring /> + + + diff --git a/cloud/server1/src/main/view/templates/eureka/lastn.ftl b/cloud/server1/src/main/view/templates/eureka/lastn.ftl new file mode 100644 index 0000000..8ee23d1 --- /dev/null +++ b/cloud/server1/src/main/view/templates/eureka/lastn.ftl @@ -0,0 +1,71 @@ +<#import "/spring.ftl" as spring /> + + + + + + + + 注册中心-事件 + + + + + + + <#include "header.ftl"> + +
+ <#include "navbar.ftl"> + +
+ +
+
+ + + + + + <#if lastNCanceled?has_content> + <#list lastNCanceled as entry> + + + <#else> + + + +
租约时间戳
${entry.date?datetime}${entry.id}
没有可用的资源
+
+
+ + + + + + <#if lastNRegistered?has_content> + <#list lastNRegistered as entry> + + + <#else> + + + +
租约时间戳
${entry.date?datetime}${entry.id}
没有可用的资源
+
+
+
+
+ + + + diff --git a/cloud/server1/src/main/view/templates/eureka/navbar.ftl b/cloud/server1/src/main/view/templates/eureka/navbar.ftl new file mode 100644 index 0000000..a4f7eb2 --- /dev/null +++ b/cloud/server1/src/main/view/templates/eureka/navbar.ftl @@ -0,0 +1,71 @@ +

系统状态

+
+
+ + <#if amazonInfo??> + + + + + + + + + + + + + + + + + + + + + +
服务注册和发现AMI: ${amiId!}
空间${availabilityZone!}
示例Id${instanceId!}
环境${environment!}
数据中心${datacenter!}
+
+
+ + + + + + + + + + + + + + + + + + + + + +
当前时间${currentTime}
运行${upTime}
启用租约到期时间${registry.leaseExpirationEnabled?c}
续订阈值${registry.numOfRenewsPerMinThreshold}
续订 (最后一分钟)${registry.numOfRenewsInLastMin}
+
+
+ +<#if isBelowRenewThresold> + <#if !registry.selfPreservationModeEnabled> +

续订小于阈值。自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。

+ <#else> +

紧急!注册中心可能不正确地验证身份, 当他们没有的情况下。续订小于阈值, 因此实例不会过期, 只是为了安全起见。

+ +<#elseif !registry.selfPreservationModeEnabled> +

自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。

+ + +

服务副本

+ + diff --git a/cloud/server1/src/main/view/templates/eureka/status.ftl b/cloud/server1/src/main/view/templates/eureka/status.ftl new file mode 100644 index 0000000..41027eb --- /dev/null +++ b/cloud/server1/src/main/view/templates/eureka/status.ftl @@ -0,0 +1,113 @@ +<#import "/spring.ftl" as spring /> + + + + + + + + + + 服务注册和发现 + + + + + + + + + <#include "header.ftl"> +
+ <#include "navbar.ftl"> +

当前注册的服务实例

+ + + + + + <#if apps?has_content> + <#list apps as app> + + + + + + + + <#else> + + + + +
应用申请可用性区域状态
${app.name} + <#list app.amiCounts as amiCount> + ${amiCount.key} (${amiCount.value})<#if amiCount_has_next>, + + + <#list app.zoneCounts as zoneCount> + ${zoneCount.key} (${zoneCount.value})<#if zoneCount_has_next>, + + + <#list app.instanceInfos as instanceInfo> + <#if instanceInfo.isNotUp> + + + ${instanceInfo.status} (${instanceInfo.instances?size}) - + <#if instanceInfo.isNotUp> + + + <#list instanceInfo.instances as instance> + <#if instance.isHref> + ${instance.id} + <#else> + ${instance.id} + <#if instance_has_next>, + + +
没有可用的实例
+ +

一般信息

+ + + + + + + <#list statusInfo.generalStats?keys as stat> + + + + + <#list statusInfo.applicationStats?keys as stat> + + + + + +
名称
${stat}${statusInfo.generalStats[stat]!""}
${stat}${statusInfo.applicationStats[stat]!""}
+ +

示例信息

+ + + + + + + <#list instanceInfo?keys as key> + + + + + +
名称
${key}${instanceInfo[key]!""}
+
+ + + + diff --git a/cloud/server2/src/main/java/com/sincere/server2/listener/EurekaInstanceCanceledListener.java b/cloud/server2/src/main/java/com/sincere/server2/listener/EurekaInstanceCanceledListener.java new file mode 100644 index 0000000..9455d0e --- /dev/null +++ b/cloud/server2/src/main/java/com/sincere/server2/listener/EurekaInstanceCanceledListener.java @@ -0,0 +1,59 @@ +package com.sincere.server2.listener; + + +import com.netflix.discovery.shared.Applications; +import com.netflix.eureka.EurekaServerContextHolder; +import com.netflix.eureka.registry.PeerAwareInstanceRegistry; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent; +import org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Configuration; + +/** + * 用于监听eureka服务停机通知 + * Created by ace on 2017/7/8. + */ +@Slf4j +@Configuration +public class EurekaInstanceCanceledListener implements ApplicationListener { + @Override + public void onApplicationEvent(ApplicationEvent applicationEvent) { + // 服务挂掉事件 + if (applicationEvent instanceof EurekaInstanceCanceledEvent) { + EurekaInstanceCanceledEvent event = (EurekaInstanceCanceledEvent) applicationEvent; + // 获取当前Eureka实例中的节点信息 + PeerAwareInstanceRegistry registry = EurekaServerContextHolder.getInstance().getServerContext().getRegistry(); + Applications applications = registry.getApplications(); + // 遍历获取已注册节点中与当前失效节点ID一致的节点信息 + applications.getRegisteredApplications().forEach((registeredApplication) -> { + registeredApplication.getInstances().forEach((instance) -> { + if (instance.getInstanceId().equals(event.getServerId())) { + log.debug("服务:" + instance.getAppName() + " 挂啦。。。"); + // // TODO: 2017/9/3 扩展消息提醒 邮件、手机短信、微信等 + } + }); + }); + + + } + if (applicationEvent instanceof EurekaInstanceRegisteredEvent) { + EurekaInstanceRegisteredEvent event = (EurekaInstanceRegisteredEvent) applicationEvent; + log.debug("服务:" + event.getInstanceInfo().getAppName() + " 注册成功啦。。。"); + } + if (applicationEvent instanceof EurekaInstanceRenewedEvent) { + EurekaInstanceRenewedEvent event = (EurekaInstanceRenewedEvent) applicationEvent; + log.debug("心跳检测服务:" + event.getInstanceInfo().getAppName() + "。。"); + } + if (applicationEvent instanceof EurekaRegistryAvailableEvent) { + log.debug("服务 Aualiable。。"); + } + + } + + +} + diff --git a/cloud/server2/src/main/resources/application.yaml b/cloud/server2/src/main/resources/application.yaml index f4f3a71..8ba69d0 100644 --- a/cloud/server2/src/main/resources/application.yaml +++ b/cloud/server2/src/main/resources/application.yaml @@ -9,22 +9,29 @@ spring: eureka: instance: - preferIpAddress: true # 注册周期心跳 默认30s 这里改成5s 建议生成环境使用默认值30 lease-renewal-interval-in-seconds: 10 lease-expiration-duration-in-seconds: 60 - hostname: localhost + prefer-ip-address: true server: #是否开启保护模式 - enable-self-preservation: true - eviction-interval-timer-in-ms: 4000 + enable-self-preservation: false #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务 + eviction-interval-timer-in-ms: 4000 #清理间隔(单位毫秒,默认是60*1000)5秒将客户端剔除的服务在服务注册列表中剔除# #当进入保护模式的情况下,注册中心不会注销服务,以兼容分区故障 - renewal-percent-threshold: 0.5 + renewal-percent-threshold: 0.5 # 指定每分钟需要收到的续约次数的阈值,默认值就是:0.85 + response-cache-update-interval-ms: 3000 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上 #eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上默认30s + response-cache-auto-expiration-in-seconds: 180 #eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。 client: #是否注册eureka,高可用的清况下使用 - register-with-eureka: true + register-with-eureka: true #false:不作为一个客户端注册到注册中心,是否将自身的实例信息注册到eureka服务器 #是否启用获取服务注册信息 - fetch-registry: true + fetch-registry: false #为true时,可以启动,但报异常:Cannot execute request on any known server ,是否从eureka服务端获取注册信息,消费者需要配置true + instance-info-replication-interval-seconds: 10 + registry-fetch-interval-seconds: 30 #从eureka服务端获取注册信息的间隔时间 service-url: - defaultZone: http://localhost:8761/eureka/ \ No newline at end of file + defaultZone: http://localhost:8761/eureka/ + + +ribbon: + ServerListRefreshInterval: 1000 #刷新服务列表源的间隔时间 \ No newline at end of file diff --git a/cloud/server2/src/main/view/templates/.keep b/cloud/server2/src/main/view/templates/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cloud/server2/src/main/view/templates/.keep diff --git a/cloud/server2/src/main/view/templates/eureka/.keep b/cloud/server2/src/main/view/templates/eureka/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cloud/server2/src/main/view/templates/eureka/.keep diff --git a/cloud/server2/src/main/view/templates/eureka/header.ftl b/cloud/server2/src/main/view/templates/eureka/header.ftl new file mode 100644 index 0000000..d6584bd --- /dev/null +++ b/cloud/server2/src/main/view/templates/eureka/header.ftl @@ -0,0 +1,26 @@ +<#import "/spring.ftl" as spring /> + + + diff --git a/cloud/server2/src/main/view/templates/eureka/lastn.ftl b/cloud/server2/src/main/view/templates/eureka/lastn.ftl new file mode 100644 index 0000000..8ee23d1 --- /dev/null +++ b/cloud/server2/src/main/view/templates/eureka/lastn.ftl @@ -0,0 +1,71 @@ +<#import "/spring.ftl" as spring /> + + + + + + + + 注册中心-事件 + + + + + + + <#include "header.ftl"> + +
+ <#include "navbar.ftl"> + +
+ +
+
+ + + + + + <#if lastNCanceled?has_content> + <#list lastNCanceled as entry> + + + <#else> + + + +
租约时间戳
${entry.date?datetime}${entry.id}
没有可用的资源
+
+
+ + + + + + <#if lastNRegistered?has_content> + <#list lastNRegistered as entry> + + + <#else> + + + +
租约时间戳
${entry.date?datetime}${entry.id}
没有可用的资源
+
+
+
+
+ + + + diff --git a/cloud/server2/src/main/view/templates/eureka/navbar.ftl b/cloud/server2/src/main/view/templates/eureka/navbar.ftl new file mode 100644 index 0000000..a4f7eb2 --- /dev/null +++ b/cloud/server2/src/main/view/templates/eureka/navbar.ftl @@ -0,0 +1,71 @@ +

系统状态

+
+
+ + <#if amazonInfo??> + + + + + + + + + + + + + + + + + + + + + +
服务注册和发现AMI: ${amiId!}
空间${availabilityZone!}
示例Id${instanceId!}
环境${environment!}
数据中心${datacenter!}
+
+
+ + + + + + + + + + + + + + + + + + + + + +
当前时间${currentTime}
运行${upTime}
启用租约到期时间${registry.leaseExpirationEnabled?c}
续订阈值${registry.numOfRenewsPerMinThreshold}
续订 (最后一分钟)${registry.numOfRenewsInLastMin}
+
+
+ +<#if isBelowRenewThresold> + <#if !registry.selfPreservationModeEnabled> +

续订小于阈值。自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。

+ <#else> +

紧急!注册中心可能不正确地验证身份, 当他们没有的情况下。续订小于阈值, 因此实例不会过期, 只是为了安全起见。

+ +<#elseif !registry.selfPreservationModeEnabled> +

自保存模式已关闭。如果出现网络/其他问题, 这可能不会保护实例过期。

+ + +

服务副本

+ + diff --git a/cloud/server2/src/main/view/templates/eureka/status.ftl b/cloud/server2/src/main/view/templates/eureka/status.ftl new file mode 100644 index 0000000..41027eb --- /dev/null +++ b/cloud/server2/src/main/view/templates/eureka/status.ftl @@ -0,0 +1,113 @@ +<#import "/spring.ftl" as spring /> + + + + + + + + + + 服务注册和发现 + + + + + + + + + <#include "header.ftl"> +
+ <#include "navbar.ftl"> +

当前注册的服务实例

+ + + + + + <#if apps?has_content> + <#list apps as app> + + + + + + + + <#else> + + + + +
应用申请可用性区域状态
${app.name} + <#list app.amiCounts as amiCount> + ${amiCount.key} (${amiCount.value})<#if amiCount_has_next>, + + + <#list app.zoneCounts as zoneCount> + ${zoneCount.key} (${zoneCount.value})<#if zoneCount_has_next>, + + + <#list app.instanceInfos as instanceInfo> + <#if instanceInfo.isNotUp> + + + ${instanceInfo.status} (${instanceInfo.instances?size}) - + <#if instanceInfo.isNotUp> + + + <#list instanceInfo.instances as instance> + <#if instance.isHref> + ${instance.id} + <#else> + ${instance.id} + <#if instance_has_next>, + + +
没有可用的实例
+ +

一般信息

+ + + + + + + <#list statusInfo.generalStats?keys as stat> + + + + + <#list statusInfo.applicationStats?keys as stat> + + + + + +
名称
${stat}${statusInfo.generalStats[stat]!""}
${stat}${statusInfo.applicationStats[stat]!""}
+ +

示例信息

+ + + + + + + <#list instanceInfo?keys as key> + + + + + +
名称
${key}${instanceInfo[key]!""}
+
+ + + + diff --git a/cloud/zkAttendance/src/main/java/com/sincere/att/AttApplication.java b/cloud/zkAttendance/src/main/java/com/sincere/att/AttApplication.java index 692e434..5018fff 100644 --- a/cloud/zkAttendance/src/main/java/com/sincere/att/AttApplication.java +++ b/cloud/zkAttendance/src/main/java/com/sincere/att/AttApplication.java @@ -15,6 +15,9 @@ import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication public class AttApplication { +// public static void main(String[] args) { +// SpringApplication.run(AttApplication.class, args); +// } public static void main(String[] args) { SpringApplication.run(AttApplication.class, args); } -- libgit2 0.21.0