diff --git a/pom.xml b/pom.xml index a8a57cd..2570047 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.1 + 2.4.6 com.example @@ -14,12 +14,35 @@ GuoYan GuoYan - 17 + 11 org.springframework.boot - spring-boot-starter-web + + + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-cache + + + + org.springframework.boot + spring-boot-starter-mail + 2.2.6.RELEASE + + + + org.springframework.boot + spring-boot-starter @@ -27,12 +50,23 @@ spring-boot-starter-test test + + + org.springframework.boot + spring-boot-starter-web + compile + com.baomidou mybatis-plus-boot-starter 3.4.0 + + com.alibaba + fastjson + 1.2.76 + org.projectlombok @@ -43,8 +77,39 @@ com.alibaba druid-spring-boot-starter - 1.2.3 + 1.2.5 + + + mysql + mysql-connector-java + runtime + + + + com.alibaba + druid-spring-boot-starter + 1.2.5 + + + org.springframework.boot + spring-boot-starter-jdbc + + + + com.github.xiaoymin + knife4j-spring-boot-starter + 3.0.2 + + org.projectlombok + lombok + + + org.apache.httpcomponents + httpclient + 4.5.13 + + @@ -52,6 +117,7 @@ org.springframework.boot spring-boot-maven-plugin + 2.4.5 diff --git a/src/main/java/com/example/guoyan/GuoYanApplication.java b/src/main/java/com/example/guoyan/GuoYanApplication.java index 794cb81..934e7fd 100644 --- a/src/main/java/com/example/guoyan/GuoYanApplication.java +++ b/src/main/java/com/example/guoyan/GuoYanApplication.java @@ -1,9 +1,13 @@ package com.example.guoyan; +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@Slf4j +@EnableScheduling public class GuoYanApplication { public static void main(String[] args) { diff --git a/src/main/java/com/example/guoyan/common/CustomerException.java b/src/main/java/com/example/guoyan/common/CustomerException.java new file mode 100644 index 0000000..714e99c --- /dev/null +++ b/src/main/java/com/example/guoyan/common/CustomerException.java @@ -0,0 +1,13 @@ +package com.example.guoyan.common; + +/** +* 自定义一个运行时异常 +* +*/ +public class CustomerException extends RuntimeException{ + + public CustomerException(String message) { + + super(message); + } +} diff --git a/src/main/java/com/example/guoyan/common/GloableExceptionHandler.java b/src/main/java/com/example/guoyan/common/GloableExceptionHandler.java new file mode 100644 index 0000000..f8dc346 --- /dev/null +++ b/src/main/java/com/example/guoyan/common/GloableExceptionHandler.java @@ -0,0 +1,58 @@ +package com.example.guoyan.common; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.sql.SQLIntegrityConstraintViolationException; + +/** + * 全局异常处理 + * 基于代理实现,也就是通过AOP来对这些异常进行拦截 + * 如果抛异常了,就一起来这里进行处理 + * @ControllerAdvice(拦截哪些controller) + * @ControllerAdvice(annotations = {RestController.class, Controller.class})加入了@RestController、@Controller的注解 + * @ResponseBody 返回Result对象时解析成json + */ +@ControllerAdvice(annotations = {RestController.class, Controller.class}) +@ResponseBody +@Slf4j +public class GloableExceptionHandler { + /** + * @ExceptionHandler({异常类型.class,异常类型.class}) + * @param exception 异常对象,后面Get信息要用 + * @return 返回Result对象,既然都抓异常了,肯定就要Result.error("失败信息") + */ + @ExceptionHandler({SQLIntegrityConstraintViolationException.class,NullPointerException.class}) + public Result exceptionHandler(SQLIntegrityConstraintViolationException exception){ + log.error(exception.getMessage()); + //这里判断出来是添加员工时出现的异常 + if (exception.getMessage().contains("Duplicate entry")){ + //exception对象分割,同时存储 + String []splitErrorMessage=exception.getMessage().split(" "); + /** + * splitErrorMessage数组内存的信息 + * Duplicate entry '新增的账号' for key 'idx_username' + * 下标位2是新增账号,下标位5是关联的字段名 + */ + String errorMessage = "这个账号重复了" + splitErrorMessage[2]; + return Result.error(errorMessage); + } + return Result.error("失败了"); + } + + /** + * 自定义的全局异常处理 + * @param customerException 自定义异常对象 + * @return + */ + @ExceptionHandler({CustomerException.class}) + public Result exceptionHandlerCustomer(CustomerException customerException){ + log.error(customerException.getMessage()); + //直接返回处理信息 + return Result.error(customerException.getMessage()); + } +} diff --git a/src/main/java/com/example/guoyan/common/JacksonObjectMapper.java b/src/main/java/com/example/guoyan/common/JacksonObjectMapper.java new file mode 100644 index 0000000..2b4fe7a --- /dev/null +++ b/src/main/java/com/example/guoyan/common/JacksonObjectMapper.java @@ -0,0 +1,54 @@ +package com.example.guoyan.common; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; + +/** + * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象 + * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象] + * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON] + */ +public class JacksonObjectMapper extends ObjectMapper { + + public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; + public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss"; + + public JacksonObjectMapper() { + super(); + //收到未知属性时不报异常 + this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); + + //反序列化时,属性不存在的兼容处理 + this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + + SimpleModule simpleModule = new SimpleModule() + .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))) + .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))) + .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))) + + .addSerializer(BigInteger.class, ToStringSerializer.instance) + .addSerializer(Long.class, ToStringSerializer.instance) + .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))) + .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))) + .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))); + + //注册功能模块 例如,可以添加自定义序列化器和反序列化器 + this.registerModule(simpleModule); + } +} diff --git a/src/main/java/com/example/guoyan/common/MyMetaObjectHandler.java b/src/main/java/com/example/guoyan/common/MyMetaObjectHandler.java new file mode 100644 index 0000000..44cf847 --- /dev/null +++ b/src/main/java/com/example/guoyan/common/MyMetaObjectHandler.java @@ -0,0 +1,65 @@ +package com.example.guoyan.common; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.time.LocalDateTime; + +/** + * 自定义元数据处理器 + * MP提供的自动填充功能,通过实现MetaObjectHandler(元数据处理器),来实现服务 + * 为加入@TableField的注解提供自动填充的功能 + */ +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + + /*退而求其次选择了注入Request对象*/ + @Autowired + HttpServletRequest httpServletRequest; + + /** + * @param metaObject 插入时自动填充 + */ + @Override + public void insertFill(MetaObject metaObject) { + + //填充创建时间 + metaObject.setValue("createTime", LocalDateTime.now()); + //填充 更新的时间 + metaObject.setValue("updateTime", LocalDateTime.now()); + //BaseContext工具类获取当前登陆人员信息 + //填充创建人信息 + metaObject.setValue("createUser", httpServletRequest.getSession().getAttribute("employee")); + //填充更新人信息 + metaObject.setValue("updateUser", httpServletRequest.getSession().getAttribute("employee")); + /* + 这里有Bug,就是封装好的BaseContext通过ThreadLocal获取不了对象,虽然都是一个线程的 + 但就是获取不到,所以这里先写死了,后面慢慢再改吧 + * */ + /*//填充创建人信息 + metaObject.setValue("createUser", 1L); + //填充更新人信息 + metaObject.setValue("updateUser", 1L);*/ + + } + + /** + * @param metaObject 更新时自动填充 + */ + @Override + public void updateFill(MetaObject metaObject) { + //因为是更新,所以不用操作创建时间 + //更新 更新的时间 + metaObject.setValue("updateTime", LocalDateTime.now()); + //更新更新人员 + /* + 这里有Bug,就是封装好的BaseContext通过ThreadLocal获取不了对象,所以这里先写死了,后面慢慢再改吧 + metaObject.setValue("updateUser", 1L); + * */ + + metaObject.setValue("updateUser", httpServletRequest.getSession().getAttribute("employee")); + } +} diff --git a/src/main/java/com/example/guoyan/common/Result.java b/src/main/java/com/example/guoyan/common/Result.java new file mode 100644 index 0000000..5f29302 --- /dev/null +++ b/src/main/java/com/example/guoyan/common/Result.java @@ -0,0 +1,43 @@ +package com.example.guoyan.common; + +import lombok.Data; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * 通用返回结果,服务端响应的数据最终都会封装成此对象 + * @param + */ +@Data +public class Result implements Serializable { + + private Integer code; //编码:1成功,0和其它数字为失败 + + private String msg; //错误信息 + + private T data; //数据 + + private Map map = new HashMap(); //动态数据 + + public static Result success(T object) { + Result r = new Result(); + r.data = object; + r.code = 1; + return r; + } + + public static Result error(String msg) { + Result r = new Result(); + r.msg = msg; + r.code = 0; + return r; + } + + public Result add(String key, Object value) { + this.map.put(key, value); + return this; + } + +} diff --git a/src/main/java/com/example/guoyan/config/MybatisPlusConfig.java b/src/main/java/com/example/guoyan/config/MybatisPlusConfig.java new file mode 100644 index 0000000..488178b --- /dev/null +++ b/src/main/java/com/example/guoyan/config/MybatisPlusConfig.java @@ -0,0 +1,24 @@ +package com.example.guoyan.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MybatisPlus分页插件配置类 + */ +@Configuration +public class MybatisPlusConfig { + + //分页插件 + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor(){ + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + return interceptor; + } +} diff --git a/src/main/java/com/example/guoyan/config/RedisConfig.java b/src/main/java/com/example/guoyan/config/RedisConfig.java new file mode 100644 index 0000000..4d88f36 --- /dev/null +++ b/src/main/java/com/example/guoyan/config/RedisConfig.java @@ -0,0 +1,20 @@ +package com.example.guoyan.config; + +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig extends CachingConfigurerSupport { + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + //默认的Key序列化器为:JdkSerializationRedisSerializer + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setConnectionFactory(connectionFactory); + return redisTemplate; + } +} diff --git a/src/main/java/com/example/guoyan/config/RestTemplateConfig.java b/src/main/java/com/example/guoyan/config/RestTemplateConfig.java new file mode 100644 index 0000000..2d8ec7b --- /dev/null +++ b/src/main/java/com/example/guoyan/config/RestTemplateConfig.java @@ -0,0 +1,185 @@ +package com.example.guoyan.config; + +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.Header; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicHeader; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.*; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.RestTemplate; + + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +@Configuration + +public class RestTemplateConfig { + + @Value("${http.maxTotal}") + private Integer maxTotal; + + @Value("${http.defaultMaxPerRoute}") + private Integer defaultMaxPerRoute; + + @Value("${http.connectTimeout}") + private Integer connectTimeout; + + @Value("${http.connectionRequestTimeout}") + private Integer connectionRequestTimeout; + + @Value("${http.socketTimeout}") + private Integer socketTimeout; + + @Value("${http.staleConnectionCheckEnabled}") + private boolean staleConnectionCheckEnabled; + + @Value("${http.validateAfterInactivity}") + private Integer validateAfterInactivity; + + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(httpRequestFactory()); + } + + @Bean + public ClientHttpRequestFactory httpRequestFactory() { + return new HttpComponentsClientHttpRequestFactory(httpClient()); + } + + @Bean + public HttpClient httpClient() { + Registry registry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(); + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); + connectionManager.setMaxTotal(maxTotal); // 最大连接数 + connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute); //单个路由最大连接数 + connectionManager.setValidateAfterInactivity(validateAfterInactivity); // 最大空间时间 + + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(socketTimeout) //服务器返回数据(response)的时间,超过抛出read timeout + .setConnectTimeout(connectTimeout) //连接上服务器(握手成功)的时间,超出抛出connect timeout + .setStaleConnectionCheckEnabled(staleConnectionCheckEnabled) // 提交前检测是否可用 + .setConnectionRequestTimeout(connectionRequestTimeout)//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool + .build(); + + //headers + List
headers = new ArrayList<>(); + headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36")); + headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate")); + headers.add(new BasicHeader("Accept-Language", "zh-CN")); + headers.add(new BasicHeader("Connection", "Keep-Alive")); + headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8")); + + return HttpClientBuilder.create() + .setDefaultRequestConfig(requestConfig) + .setConnectionManager(connectionManager) + .setDefaultHeaders(headers) + // 保持长连接配置,需要在头添加Keep-Alive + .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) + //重试次数,默认是3次,没有开启 + .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)) + .build(); + } + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) { + return builder + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient())) + .interceptors(new CustomClientHttpRequestInterceptor()) + .build(); + } + @Slf4j + static class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + @Override + @NonNull + public ClientHttpResponse intercept(HttpRequest request, @NonNull byte[] bytes, @NonNull ClientHttpRequestExecution execution) throws IOException { + log.info("HTTP Method: {}, URI: {}, Headers: {}", request.getMethod(), request.getURI(), request.getHeaders()); + request.getMethod(); + if (request.getMethod().equals(HttpMethod.POST)) { + log.info("HTTP body: {}", new String(bytes, StandardCharsets.UTF_8)); + } + + ClientHttpResponse response = execution.execute(request, bytes); + ClientHttpResponse responseWrapper = new BufferingClientHttpResponseWrapper(response); + + String body = StreamUtils.copyToString(responseWrapper.getBody(), StandardCharsets.UTF_8); + log.info("RESPONSE body: {}", body); + + return responseWrapper; + } + } + static class BufferingClientHttpResponseWrapper implements ClientHttpResponse { + + private final ClientHttpResponse response; + private byte[] body; + + BufferingClientHttpResponseWrapper(ClientHttpResponse response) { + this.response = response; + } + +// @NonNull +// public HttpStatusCode getStatusCode() throws IOException { +// return this.response.getStatusCode(); +// } + + @Override + public HttpStatus getStatusCode() throws IOException { + return this.response.getStatusCode(); + } + + @Override + public int getRawStatusCode() throws IOException { + return this.response.getRawStatusCode(); + } + + @NonNull + public String getStatusText() throws IOException { + return this.response.getStatusText(); + } + + @NonNull + public HttpHeaders getHeaders() { + return this.response.getHeaders(); + } + + @NonNull + public InputStream getBody() throws IOException { + if (this.body == null) { + this.body = StreamUtils.copyToByteArray(this.response.getBody()); + } + return new ByteArrayInputStream(this.body); + } + + public void close() { + this.response.close(); + } + } + + +} diff --git a/src/main/java/com/example/guoyan/config/WebMvcConfig.java b/src/main/java/com/example/guoyan/config/WebMvcConfig.java new file mode 100644 index 0000000..b125d3b --- /dev/null +++ b/src/main/java/com/example/guoyan/config/WebMvcConfig.java @@ -0,0 +1,78 @@ +package com.example.guoyan.config; + +import com.example.guoyan.common.JacksonObjectMapper; +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.List; + + +/** + * 前端资源放行配置类 + * */ +@Configuration +@Slf4j +@EnableSwagger2 +@EnableKnife4j +public class WebMvcConfig extends WebMvcConfigurationSupport { + /** + * 设置静态资源映射 + * */ + @Override + protected void addResourceHandlers(ResourceHandlerRegistry registry) { + //添加映射 + log.info("映射资源开始"); + registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/"); + registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/"); + } + + /** + * 扩展mvc框架的消息转换器 + * @param converters + */ + @Override + protected void extendMessageConverters(List> converters) { + log.info("扩展消息转换器..........."); + //创建消息转换器对象 + MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); + //设置对象转换器,底层使用我们定义的对象转换器通过JackJson将java对象转换为json + messageConverter.setObjectMapper(new JacksonObjectMapper()); + //将上面的消息转换器对象追加到mvc框架的转换器集合中 + converters.add(0,messageConverter); //0表示最先执行我们的追加的转换器 + } + + @Bean + public Docket createRestApi() { + // 文档类型 + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.cc.controller")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("接口文档") + .version("1.0") + .description("接口文档") + .build(); + } +} diff --git a/src/main/java/com/example/guoyan/entity/ContractInfo.java b/src/main/java/com/example/guoyan/entity/ContractInfo.java new file mode 100644 index 0000000..98f0f7d --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/ContractInfo.java @@ -0,0 +1,56 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class ContractInfo { + + /** + *合同编号 + */ + @NotNull(message = "contractCode 必填") + private String contractCode; + /** + * 合同名称 + */ + @NotNull(message = "contractName 必填") + private String contractName; + /** + * 项目编号 + */ + @NotNull(message = "projectNo 必填") + private String projectNo; + /** + * 高新 1 是 0 否 + */ + @NotNull(message = "highTech 必填") + private Integer highTech; + /** + * 中标方式 字典-中标方式 + */ + @NotNull(message = "winningBidWay 必填") + private String winningBidWay; + + /** + * 合同金额 + */ + private String contractAmount; + + /** + * 签出 + */ + @NotNull(message ="signOut 必填" ) + private Integer signOut; + /** + * 签回 + */ + @NotNull(message = "signIn 必填 ") + private Integer signIn; + /** + * 确认日期 + */ + @NotNull(message = "confirmDate 必填") + private String confirmDate; +} diff --git a/src/main/java/com/example/guoyan/entity/Readlog.java b/src/main/java/com/example/guoyan/entity/Readlog.java new file mode 100644 index 0000000..ad64a1f --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/Readlog.java @@ -0,0 +1,37 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 保存流程已读日志(Readlog)实体类 + * + * @author makejava + * @since 2024-01-09 16:15:55 + */ +@Data +public class Readlog implements Serializable { + private static final long serialVersionUID = 778641858893674888L; + + private String id; + + private String dataid; + + private String staffid; + + private String stepid; + + private String readnum; + + private String adddate; + + private String lastaccessdate; + + private String memo; + + private String resid; + + +} + diff --git a/src/main/java/com/example/guoyan/entity/Requestlog.java b/src/main/java/com/example/guoyan/entity/Requestlog.java new file mode 100644 index 0000000..3a91be6 --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/Requestlog.java @@ -0,0 +1,64 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * (Requestlog)实体类 + * + * @author makejava + * @since 2024-01-09 16:28:31 + */ +@Data +public class Requestlog implements Serializable { + private static final long serialVersionUID = -12899290814932077L; + + private String requestid; + + private String staffid; + + private Integer isedit; + + private String createdate; + + private String stepid; + + private Integer ntype; + + private String info; + + private String attachids; + + private Integer istodo; + + private String typeinfo; + + private String id; + + private String nextstepid; + + private String clienttype; + + private String field1; + + private String field2; + + private String field3; + + private String field4; + + private String field5; + + private Integer intfield1; + + private Integer intfield2; + + private Integer intfield3; + + private String agentbyid; + + private String oristepid; + +} + diff --git a/src/main/java/com/example/guoyan/entity/Requestoperator.java b/src/main/java/com/example/guoyan/entity/Requestoperator.java new file mode 100644 index 0000000..754cea7 --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/Requestoperator.java @@ -0,0 +1,52 @@ +package com.example.guoyan.entity; + +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +import java.io.Serializable; + +/** + * 保存04节点审批人及操作 实体表 + * + * @author makejava + * @since 2024-01-09 16:20:14 + */ +@Data +public class Requestoperator implements Serializable { + + private String id; + + private String requestid; + + private String stepid; + + private String stepoperid; + + private Integer issubmit; + + private String agentbyid; + + private String staffid; + + private String receivedate; + + private String submitdate; + + private Integer opertype; + + private Integer isremind; + + private String lastreminddate; + + private Integer isorioperator; + + private String wfagentid; + + private String oristepid; + + private Integer dsporder; + + private String dingrecordid; + + } + diff --git a/src/main/java/com/example/guoyan/entity/Requeststatus.java b/src/main/java/com/example/guoyan/entity/Requeststatus.java new file mode 100644 index 0000000..2d62d1e --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/Requeststatus.java @@ -0,0 +1,31 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * (Requeststatus)实体类 + * + * @author makejava + * @since 2024-01-09 16:26:51 + */ +@Data +public class Requeststatus implements Serializable { + private static final long serialVersionUID = -31534422220247331L; + + private String id; + + private String requestid; + + private String stepid; + + private String prestepid; + + private Integer nstatus; + + private String modifydate; + + +} + diff --git a/src/main/java/com/example/guoyan/entity/ScKpsqsp.java b/src/main/java/com/example/guoyan/entity/ScKpsqsp.java new file mode 100644 index 0000000..0e1db0a --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/ScKpsqsp.java @@ -0,0 +1,109 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 开票申请审批(ScKpsqsp)实体类 + * + * @author makejava + * @since 2024-01-09 16:25:35 + */ +@Data +public class ScKpsqsp implements Serializable { + private static final long serialVersionUID = 466211042633160123L; + + private String requestid; + + private String id; + + private String cjr; + + private String khx; + + private String nsrsbh; + + private String zh; + + private String dh; + + private String dz; + + private String kprq; + + private String fphm; + + private String ssbm; + + private Double ssje; + + private String bz; + + private String fpfj; + + private String fplx; + + private String tssm; + + private String gw; + + private String cjrq; + + private String xmmc; + + private String xmbh; + + private String xsfzr; + + private String xmfzr; + + private String qy; + + private String xmlx; + + private String sfgx; + + private String bckpbl; + + private String htbh; + + private String ljkpbl000; + + private String htskjd; + + private Double htje0y0; + + private String xmjd; + + private Double kpje0y0; + + private String schz; + + private String zmwj; + + private String kpnr; + + private String sl; + + private String fpzl; + + private String kpbl0; + + private String kpbl; + + private Double kpje; + + private String kpdwmc; + + private String skrq; + + private Double qrsr; + + private String qrrq; + + private String csry; + + +} + diff --git a/src/main/java/com/example/guoyan/entity/ScXglc.java b/src/main/java/com/example/guoyan/entity/ScXglc.java new file mode 100644 index 0000000..daf9e12 --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/ScXglc.java @@ -0,0 +1,42 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 更新sc_xglcb(当前节点、是否归档、最后提交人、最后提交时间) 相关流程(ScXglc)实体类 + * + * @author makejava + * @since 2024-01-09 16:23:49 + */ +@Data +public class ScXglc implements Serializable { + private static final long serialVersionUID = 122201132500120334L; + + private String requestid; + + private String id; + + private String cjr; + + private String cjrq; + + private String dqjd; + + private String xm; + + private String lc; + + private String lcmc; + + private String gxry; + + private String sfgd; + + private String zhtjsj; + + private String zhtjr; + +} + diff --git a/src/main/java/com/example/guoyan/entity/Wfrequest.java b/src/main/java/com/example/guoyan/entity/Wfrequest.java new file mode 100644 index 0000000..e6d0ef1 --- /dev/null +++ b/src/main/java/com/example/guoyan/entity/Wfrequest.java @@ -0,0 +1,55 @@ +package com.example.guoyan.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * (Wfrequest)实体类 + * + * @author makejava + * @since 2024-01-09 16:27:40 + */ +@Data +public class Wfrequest implements Serializable { + private static final long serialVersionUID = 783536966169674807L; + + private String name; + + private String workflowid; + + private String dataid; + + private String createdate; + + private String lastmodifydate; + + private String creatorid; + + private String id; + + private String laststaffid; + + private String requestnum; + + private String field1; + + private String field2; + + private String field3; + + private String field4; + + private String field5; + + private Integer intfield1; + + private Integer intfield2; + + private Integer intfield3; + + private Integer status; + + +} + diff --git a/src/main/java/com/example/guoyan/mapper/ReadlogMapper.java b/src/main/java/com/example/guoyan/mapper/ReadlogMapper.java new file mode 100644 index 0000000..dfe5042 --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/ReadlogMapper.java @@ -0,0 +1,9 @@ +package com.example.guoyan.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.guoyan.entity.Readlog; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ReadlogMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/guoyan/mapper/RequestlogMapper.java b/src/main/java/com/example/guoyan/mapper/RequestlogMapper.java new file mode 100644 index 0000000..8c55eac --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/RequestlogMapper.java @@ -0,0 +1,7 @@ +package com.example.guoyan.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.guoyan.entity.Requestlog; + +public interface RequestlogMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/guoyan/mapper/RequestoperatorMapper.java b/src/main/java/com/example/guoyan/mapper/RequestoperatorMapper.java new file mode 100644 index 0000000..f8f8737 --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/RequestoperatorMapper.java @@ -0,0 +1,7 @@ +package com.example.guoyan.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.guoyan.entity.Requestoperator; + +public interface RequestoperatorMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/guoyan/mapper/RequeststatusMapper.java b/src/main/java/com/example/guoyan/mapper/RequeststatusMapper.java new file mode 100644 index 0000000..7c87c9e --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/RequeststatusMapper.java @@ -0,0 +1,7 @@ +package com.example.guoyan.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.guoyan.entity.Requeststatus; + +public interface RequeststatusMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/guoyan/mapper/ScKpsqspMapper.java b/src/main/java/com/example/guoyan/mapper/ScKpsqspMapper.java new file mode 100644 index 0000000..9e9770f --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/ScKpsqspMapper.java @@ -0,0 +1,4 @@ +package com.example.guoyan.mapper; + +public interface ScKpsqspMapper { +} diff --git a/src/main/java/com/example/guoyan/mapper/ScXglcMapper.java b/src/main/java/com/example/guoyan/mapper/ScXglcMapper.java new file mode 100644 index 0000000..07529c3 --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/ScXglcMapper.java @@ -0,0 +1,7 @@ +package com.example.guoyan.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.guoyan.entity.ScXglc; + +public interface ScXglcMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/guoyan/mapper/WfrequestMapper.java b/src/main/java/com/example/guoyan/mapper/WfrequestMapper.java new file mode 100644 index 0000000..804ba07 --- /dev/null +++ b/src/main/java/com/example/guoyan/mapper/WfrequestMapper.java @@ -0,0 +1,7 @@ +package com.example.guoyan.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.guoyan.entity.Wfrequest; + +public interface WfrequestMapper extends BaseMapper { +} diff --git a/src/main/java/com/example/guoyan/response/ResponseBeanForBeiJing.java b/src/main/java/com/example/guoyan/response/ResponseBeanForBeiJing.java new file mode 100644 index 0000000..675f068 --- /dev/null +++ b/src/main/java/com/example/guoyan/response/ResponseBeanForBeiJing.java @@ -0,0 +1,12 @@ +package com.example.guoyan.response; + +import lombok.Data; + +@Data +public class ResponseBeanForBeiJing { + + private Integer Status; + private String code; + private Object message; + private Object data; +} diff --git a/src/main/java/com/example/guoyan/scheduled/ProcessScheduled.java b/src/main/java/com/example/guoyan/scheduled/ProcessScheduled.java new file mode 100644 index 0000000..f94e5a0 --- /dev/null +++ b/src/main/java/com/example/guoyan/scheduled/ProcessScheduled.java @@ -0,0 +1,19 @@ +package com.example.guoyan.scheduled; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +@Slf4j +public class ProcessScheduled { + + @Scheduled(cron = "0 0/5 * * * ?") + public void invoice_request_Process_Scheduled(){ + //先查询开票申请的流程 + + log.info(new Date ().toString()); + } +} diff --git a/src/main/java/com/example/guoyan/utils/MD5Util.java b/src/main/java/com/example/guoyan/utils/MD5Util.java new file mode 100644 index 0000000..8042df4 --- /dev/null +++ b/src/main/java/com/example/guoyan/utils/MD5Util.java @@ -0,0 +1,32 @@ +package com.example.guoyan.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MD5Util { + public static String getMD5(String password) { + try { + // 得到一个信息摘要器 + MessageDigest digest = MessageDigest.getInstance("md5"); + byte[] result = digest.digest(password.getBytes()); + StringBuffer buffer = new StringBuffer(); + // 把每一个byte 做一个与运算 0xff; + for (byte b : result) { + // 与运算 + int number = b & 0xff;// 加盐 + String str = Integer.toHexString(number); + if (str.length() == 1) { + buffer.append("0"); + } + buffer.append(str); + } + + // 标准的md5加密后的结果 + return buffer.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return ""; + } + } + +} diff --git a/src/main/java/com/example/guoyan/utils/ValidateCodeUtils.java b/src/main/java/com/example/guoyan/utils/ValidateCodeUtils.java new file mode 100644 index 0000000..a624dbd --- /dev/null +++ b/src/main/java/com/example/guoyan/utils/ValidateCodeUtils.java @@ -0,0 +1,43 @@ +package com.example.guoyan.utils; + +import java.util.Random; + +/** + * 随机生成验证码工具类 + */ +public class ValidateCodeUtils { + /** + * 随机生成验证码 + * @param length 长度为4位或者6位 + * @return + */ + public static Integer generateValidateCode(int length){ + Integer code =null; + if(length == 4){ + code = new Random().nextInt(9999);//生成随机数,最大为9999 + if(code < 1000){ + code = code + 1000;//保证随机数为4位数字 + } + }else if(length == 6){ + code = new Random().nextInt(999999);//生成随机数,最大为999999 + if(code < 100000){ + code = code + 100000;//保证随机数为6位数字 + } + }else{ + throw new RuntimeException("只能生成4位或6位数字验证码"); + } + return code; + } + + /** + * 随机生成指定长度字符串验证码 + * @param length 长度 + * @return + */ + public static String generateValidateCode4String(int length){ + Random rdm = new Random(); + String hash1 = Integer.toHexString(rdm.nextInt()); + String capstr = hash1.substring(0, length); + return capstr; + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..77ee752 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,9 @@ +spring: + datasource: + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + # + #serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://116.62.210.190:3306/guoyantest?autoReconnect=true&useUnicode=true&characterEncoding=UTF8&mysqlEncoding=utf8&zeroDateTimeBehavior=convertToNull + username: test + password: Jyy83086775 \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..0b3e7e7 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,9 @@ +spring: + datasource: + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + # + #serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true + url: jdbc:mysql://116.62.210.190:3306/guoyan?autoReconnect=true&useUnicode=true&characterEncoding=UTF8&mysqlEncoding=utf8&zeroDateTimeBehavior=convertToNull + username: root + password: Guoyan83086775 \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..c46436a --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,33 @@ +server: + port: 9001 + +spring: + application: + name: Guoyan + profiles: + active: dev +# 是否允许定义重名的bean对象覆盖原有的bean (spring boot默认是false) +# main: +# allow-bean-definition-overriding: true + +mybatis-plus: + configuration: + #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,开启按照驼峰命名法映射 + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + id-type: ASSIGN_UUID + +logging: + # 配置日志文件存储位置 + file: + path: F:\log +http: + maxTotal: 100 #最大连接数 + defaultMaxPerRoute: 20 #并发数 + connectTimeout: 1000 #创建连接的最长时间 + connectionRequestTimeout: 500 #从连接池中获取到连接的最长时间 + socketTimeout: 10000 #数据传输的最长时间 + staleConnectionCheckEnabled: true #提交请求前测试连接是否可用 + validateAfterInactivity: 3000000 #可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立 \ No newline at end of file diff --git a/src/test/java/com/example/guoyan/TestController.java b/src/test/java/com/example/guoyan/TestController.java new file mode 100644 index 0000000..4b8c18b --- /dev/null +++ b/src/test/java/com/example/guoyan/TestController.java @@ -0,0 +1,81 @@ +package com.example.guoyan; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.example.guoyan.common.Result; +import com.example.guoyan.entity.ContractInfo; +import com.example.guoyan.entity.Readlog; +import com.example.guoyan.mapper.ReadlogMapper; +import com.example.guoyan.response.ResponseBeanForBeiJing; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +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.client.RestTemplate; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; + +@RestController +@RequestMapping("/test") +@Slf4j +public class TestController { + @Resource + private RestTemplate restTemplate; + @Autowired + private ReadlogMapper readlogMapper; + + @GetMapping() + public Result upLoadFile(){ + String url = "http://123.57.82.48:13310/api/auth/login"; + + + //提交参数设置 + HashMap map = new HashMap<>(); + map.put("username", "0519999"); + map.put("password", "123456"); + + //发起请求 + ResponseBeanForBeiJing responseBean = restTemplate.postForObject(url,map, ResponseBeanForBeiJing.class); + System.out.println(responseBean.toString()); + String data = responseBean.getData().toString(); + + HttpHeaders headers = new HttpHeaders(); + //headers.setBearerAuth(data); + headers.set("Authorization",data); + // headers.setContentType(MediaType.APPLICATION_JSON); + ContractInfo contractInfo = new ContractInfo(); + contractInfo.setContractCode("83086775"); + contractInfo.setContractName("测试合同"); + contractInfo.setConfirmDate("2023-01-02"); + contractInfo.setProjectNo("83086775"); + contractInfo.setHighTech(1); + contractInfo.setSignIn(1); + contractInfo.setSignOut(1); + contractInfo.setWinningBidWay("公开招标"); + // 组装请求体 + HttpEntity request = new HttpEntity<>(contractInfo, headers); + try{ + Object object = restTemplate.exchange("http://123.57.82.48:13310/api/nb/contract", HttpMethod.POST, request, Object.class); + System.out.println(object.toString()); + }catch (Exception E){ + log.info(E.getMessage()); + } + log.info("测试成功"); + return Result.success("成功"); + } + + @GetMapping("/t") + public Result test(){ + LambdaQueryWrapper readlogLambdaQueryWrapper = new LambdaQueryWrapper(); + readlogLambdaQueryWrapper.eq(Readlog::getId,"0008e8b65fd7e3c55354664279ed7b9b"); + List readlogs = readlogMapper.selectList(readlogLambdaQueryWrapper); + log.info(readlogs.toString()); + log.info("测试成功"); + return Result.success("成功"); + } +}