diff --git a/pom.xml b/pom.xml index 527aa25..366face 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,14 @@ spring-boot-configuration-processor true + + org.springframework.boot + spring-boot-starter-activemq + + + org.apache.activemq + activemq-pool + @@ -171,7 +179,6 @@ org.eclipse.jdt.core 3.16.0 - diff --git a/src/main/generator/jdt/EnhanceSourceCodeGenerator.java b/src/main/generator/jdt/EnhanceSourceCodeGenerator.java index 6a8f8f4..2da1f5b 100644 --- a/src/main/generator/jdt/EnhanceSourceCodeGenerator.java +++ b/src/main/generator/jdt/EnhanceSourceCodeGenerator.java @@ -8,7 +8,7 @@ public class EnhanceSourceCodeGenerator { private static final String PATH = - "file:/D:/Code/Eclipse/workspace/BlogManagePlatform/src/main/java/frodez/dao/param/user/AddPermissionParam.java"; + "file:/D:/Code/Eclipse/workspace/BlogManagePlatform/src/main/java/frodez/dao/param/task/AddTask.java"; public static void main(String[] args) throws URISyntaxException, IOException, MalformedTreeException, BadLocationException { diff --git a/src/main/generator/mybatis/generator.xml b/src/main/generator/mybatis/generator.xml index cb4a02a..f39828a 100644 --- a/src/main/generator/mybatis/generator.xml +++ b/src/main/generator/mybatis/generator.xml @@ -30,16 +30,16 @@ - - - - +
diff --git a/src/main/generator/security/InitPermissionService.java b/src/main/generator/security/InitPermissionService.java index 7772f17..2fc3f97 100644 --- a/src/main/generator/security/InitPermissionService.java +++ b/src/main/generator/security/InitPermissionService.java @@ -9,8 +9,8 @@ import frodez.util.http.URLMatcher; import frodez.util.json.JSONUtil; import frodez.util.reflect.ReflectUtil; -import frodez.util.spring.context.ContextUtil; -import frodez.util.spring.properties.PropertyUtil; +import frodez.util.spring.ContextUtil; +import frodez.util.spring.PropertyUtil; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -32,18 +32,17 @@ public class InitPermissionService { public static void main(String[] args) { SpringApplication.run(BlogManagePlatformApplication.class, args); PermissionMapper permissionMapper = ContextUtil.get(PermissionMapper.class); - String errorPath = PropertyUtil.get(PropertyKey.Web.BASE_PATH) + "/error"; List permissionList = new ArrayList<>(); Date date = new Date(); BeanFactoryUtils.beansOfTypeIncludingAncestors(ContextUtil.context(), HandlerMapping.class, true, false) .values().stream().filter((iter) -> { return iter instanceof RequestMappingHandlerMapping; }).map((iter) -> { - return RequestMappingHandlerMapping.class.cast(iter).getHandlerMethods().entrySet(); + return ((RequestMappingHandlerMapping) iter).getHandlerMethods().entrySet(); }).flatMap(Collection::stream).forEach((entry) -> { String requestUrl = PropertyUtil.get(PropertyKey.Web.BASE_PATH) + entry.getKey().getPatternsCondition() .getPatterns().stream().findFirst().get(); - if (!URLMatcher.needVerify(requestUrl) || requestUrl.equals(errorPath)) { + if (!URLMatcher.needVerify(requestUrl)) { return; } requestUrl = requestUrl.substring(PropertyUtil.get(PropertyKey.Web.BASE_PATH).length()); diff --git a/src/main/java/frodez/BlogManagePlatformApplication.java b/src/main/java/frodez/BlogManagePlatformApplication.java index 663f7ba..fb6a3a3 100644 --- a/src/main/java/frodez/BlogManagePlatformApplication.java +++ b/src/main/java/frodez/BlogManagePlatformApplication.java @@ -47,9 +47,7 @@ import org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration; -import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration; -import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration; import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration; import org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration; import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration; @@ -73,7 +71,6 @@ import org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration; import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration; import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; -import org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; @@ -87,6 +84,7 @@ import org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration; import org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration; import org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration; +import org.springframework.jms.annotation.EnableJms; import tk.mybatis.spring.annotation.MapperScan; /** @@ -94,19 +92,19 @@ * @author Frodez * @date 2019-01-07 */ -@MapperScan(basePackages = "frodez.dao.mapper") -@SpringBootApplication(exclude = { ActiveMQAutoConfiguration.class, ArtemisAutoConfiguration.class, - BatchAutoConfiguration.class, CacheAutoConfiguration.class, CassandraAutoConfiguration.class, - CassandraDataAutoConfiguration.class, CassandraReactiveDataAutoConfiguration.class, - CassandraReactiveRepositoriesAutoConfiguration.class, CassandraRepositoriesAutoConfiguration.class, - ClientHttpConnectorAutoConfiguration.class, CloudServiceConnectorsAutoConfiguration.class, - CouchbaseAutoConfiguration.class, CouchbaseDataAutoConfiguration.class, - CouchbaseReactiveDataAutoConfiguration.class, CouchbaseReactiveRepositoriesAutoConfiguration.class, - CouchbaseRepositoriesAutoConfiguration.class, XADataSourceAutoConfiguration.class, - WebSocketServletAutoConfiguration.class, WebSocketMessagingAutoConfiguration.class, - WebSocketReactiveAutoConfiguration.class, WebServicesAutoConfiguration.class, - WebServiceTemplateAutoConfiguration.class, WebFluxAutoConfiguration.class, WebClientAutoConfiguration.class, - ThymeleafAutoConfiguration.class, TaskSchedulingAutoConfiguration.class, SessionAutoConfiguration.class, +@EnableJms +@MapperScan(basePackages = { "frodez.dao.mapper" }) +@SpringBootApplication(exclude = { ArtemisAutoConfiguration.class, BatchAutoConfiguration.class, + CacheAutoConfiguration.class, CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class, + CassandraReactiveDataAutoConfiguration.class, CassandraReactiveRepositoriesAutoConfiguration.class, + CassandraRepositoriesAutoConfiguration.class, ClientHttpConnectorAutoConfiguration.class, + CloudServiceConnectorsAutoConfiguration.class, CouchbaseAutoConfiguration.class, + CouchbaseDataAutoConfiguration.class, CouchbaseReactiveDataAutoConfiguration.class, + CouchbaseReactiveRepositoriesAutoConfiguration.class, CouchbaseRepositoriesAutoConfiguration.class, + XADataSourceAutoConfiguration.class, WebSocketServletAutoConfiguration.class, + WebSocketMessagingAutoConfiguration.class, WebSocketReactiveAutoConfiguration.class, + WebServicesAutoConfiguration.class, WebServiceTemplateAutoConfiguration.class, WebFluxAutoConfiguration.class, + WebClientAutoConfiguration.class, ThymeleafAutoConfiguration.class, SessionAutoConfiguration.class, SolrAutoConfiguration.class, SolrRepositoriesAutoConfiguration.class, SendGridAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class, RestClientAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, @@ -120,15 +118,14 @@ MessageSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class, LdapRepositoriesAutoConfiguration.class, LdapAutoConfiguration.class, KafkaAutoConfiguration.class, JtaAutoConfiguration.class, JsonbAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class, JooqAutoConfiguration.class, JndiDataSourceAutoConfiguration.class, - JndiConnectionFactoryAutoConfiguration.class, JmsAutoConfiguration.class, JestAutoConfiguration.class, - JerseyAutoConfiguration.class, JdbcRepositoriesAutoConfiguration.class, IntegrationAutoConfiguration.class, - InfluxDbAutoConfiguration.class, HypermediaAutoConfiguration.class, HttpHandlerAutoConfiguration.class, - HibernateJpaAutoConfiguration.class, HazelcastJpaDependencyAutoConfiguration.class, - HazelcastAutoConfiguration.class, H2ConsoleAutoConfiguration.class, GsonAutoConfiguration.class, - GroovyTemplateAutoConfiguration.class, FreeMarkerAutoConfiguration.class, FlywayAutoConfiguration.class, - ErrorWebFluxAutoConfiguration.class, EmbeddedMongoAutoConfiguration.class, EmbeddedLdapAutoConfiguration.class, - ElasticsearchRepositoriesAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class, - ElasticsearchAutoConfiguration.class }) + JndiConnectionFactoryAutoConfiguration.class, JestAutoConfiguration.class, JerseyAutoConfiguration.class, + JdbcRepositoriesAutoConfiguration.class, IntegrationAutoConfiguration.class, InfluxDbAutoConfiguration.class, + HypermediaAutoConfiguration.class, HttpHandlerAutoConfiguration.class, HibernateJpaAutoConfiguration.class, + HazelcastJpaDependencyAutoConfiguration.class, HazelcastAutoConfiguration.class, H2ConsoleAutoConfiguration.class, + GsonAutoConfiguration.class, GroovyTemplateAutoConfiguration.class, FreeMarkerAutoConfiguration.class, + FlywayAutoConfiguration.class, ErrorWebFluxAutoConfiguration.class, EmbeddedMongoAutoConfiguration.class, + EmbeddedLdapAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class, + ElasticsearchDataAutoConfiguration.class, ElasticsearchAutoConfiguration.class }) public class BlogManagePlatformApplication { public static void main(String[] args) { diff --git a/src/main/java/frodez/config/aop/request/LimitUserAOP.java b/src/main/java/frodez/config/aop/request/LimitUserAOP.java index a76caa1..2437e60 100644 --- a/src/main/java/frodez/config/aop/request/LimitUserAOP.java +++ b/src/main/java/frodez/config/aop/request/LimitUserAOP.java @@ -5,7 +5,7 @@ import frodez.util.aop.AspectUtil; import frodez.util.beans.result.Result; import frodez.util.constant.setting.DefTime; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.MVCUtil; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.aspectj.lang.ProceedingJoinPoint; @@ -27,7 +27,7 @@ public class LimitUserAOP { @Around("@annotation(frodez.config.aop.request.annotation.Limit)") public Object limit(ProceedingJoinPoint point) throws Throwable { Limit limit = AspectUtil.annotation(point, Limit.class); - RateLimiter limiter = limitCache.computeIfAbsent(ContextUtil.request().getRequestURI(), i -> RateLimiter.create( + RateLimiter limiter = limitCache.computeIfAbsent(MVCUtil.request().getRequestURI(), i -> RateLimiter.create( limit.value())); if (!limiter.tryAcquire(limit.timeout(), DefTime.UNIT)) { return Result.busy(); diff --git a/src/main/java/frodez/config/aop/request/RepeatAOP.java b/src/main/java/frodez/config/aop/request/RepeatAOP.java index 76d8cb3..f1d9bce 100644 --- a/src/main/java/frodez/config/aop/request/RepeatAOP.java +++ b/src/main/java/frodez/config/aop/request/RepeatAOP.java @@ -5,7 +5,7 @@ import frodez.util.aop.AspectUtil; import frodez.util.beans.result.Result; import frodez.util.http.ServletUtil; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.MVCUtil; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; @@ -47,7 +47,7 @@ public class RepeatAOP { */ @Around("@annotation(frodez.config.aop.request.annotation.RepeatLock)") public Object process(ProceedingJoinPoint point) throws Throwable { - HttpServletRequest request = ContextUtil.request(); + HttpServletRequest request = MVCUtil.request(); String key = KeyGenerator.servletKey(AspectUtil.fullMethodName(point), request); try { if (checker.check(key)) { diff --git a/src/main/java/frodez/config/aop/request/TimeoutAOP.java b/src/main/java/frodez/config/aop/request/TimeoutAOP.java index 72337e6..d2a5549 100644 --- a/src/main/java/frodez/config/aop/request/TimeoutAOP.java +++ b/src/main/java/frodez/config/aop/request/TimeoutAOP.java @@ -6,7 +6,7 @@ import frodez.util.aop.AspectUtil; import frodez.util.beans.result.Result; import frodez.util.http.ServletUtil; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.MVCUtil; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; @@ -47,7 +47,7 @@ public class TimeoutAOP { */ @Around("@annotation(frodez.config.aop.request.annotation.TimeoutLock)") public Object process(ProceedingJoinPoint point) throws Throwable { - HttpServletRequest request = ContextUtil.request(); + HttpServletRequest request = MVCUtil.request(); TimeoutLock timeoutLock = AspectUtil.annotation(point, TimeoutLock.class); String key = KeyGenerator.servletKey(AspectUtil.fullMethodName(point), request); if (checker.check(key)) { diff --git a/src/main/java/frodez/config/aop/request/checker/impl/AutoGuavaChecker.java b/src/main/java/frodez/config/aop/request/checker/impl/AutoGuavaChecker.java index f11be18..bdcbd31 100644 --- a/src/main/java/frodez/config/aop/request/checker/impl/AutoGuavaChecker.java +++ b/src/main/java/frodez/config/aop/request/checker/impl/AutoGuavaChecker.java @@ -5,11 +5,11 @@ import frodez.config.aop.request.checker.facade.AutoChecker; import frodez.config.cache.CacheProperties; import frodez.util.constant.setting.DefTime; -import frodez.util.spring.context.ContextUtil; -import java.util.Objects; +import frodez.util.spring.ContextUtil; import javax.annotation.PostConstruct; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * 自动超时型重复请求检查GUAVACACHE实现 @@ -26,7 +26,7 @@ public class AutoGuavaChecker implements AutoChecker { private void init() { cache = CacheBuilder.newBuilder().expireAfterAccess(ContextUtil.get(CacheProperties.class).getAutoGuavaChecker() .getTimeout(), DefTime.UNIT).build(); - Objects.requireNonNull(cache); + Assert.notNull(cache, "cache must not be null"); } @Override diff --git a/src/main/java/frodez/config/aop/request/checker/impl/ManualGuavaChecker.java b/src/main/java/frodez/config/aop/request/checker/impl/ManualGuavaChecker.java index b950745..5dba8ea 100644 --- a/src/main/java/frodez/config/aop/request/checker/impl/ManualGuavaChecker.java +++ b/src/main/java/frodez/config/aop/request/checker/impl/ManualGuavaChecker.java @@ -5,11 +5,11 @@ import frodez.config.aop.request.checker.facade.ManualChecker; import frodez.config.cache.CacheProperties; import frodez.util.constant.setting.DefTime; -import frodez.util.spring.context.ContextUtil; -import java.util.Objects; +import frodez.util.spring.ContextUtil; import javax.annotation.PostConstruct; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * 阻塞型重复请求检查HASHMAP实现 @@ -26,7 +26,7 @@ public class ManualGuavaChecker implements ManualChecker { private void init() { cache = CacheBuilder.newBuilder().expireAfterAccess(ContextUtil.get(CacheProperties.class) .getManualGuavaChecker().getTimeout(), DefTime.UNIT).build(); - Objects.requireNonNull(cache); + Assert.notNull(cache, "cache must not be null"); } @Override diff --git a/src/main/java/frodez/config/security/auth/AuthorityManager.java b/src/main/java/frodez/config/security/auth/AuthorityManager.java index c0e1d89..a222b25 100644 --- a/src/main/java/frodez/config/security/auth/AuthorityManager.java +++ b/src/main/java/frodez/config/security/auth/AuthorityManager.java @@ -3,11 +3,10 @@ import frodez.config.security.settings.SecurityProperties; import frodez.util.common.EmptyUtil; import frodez.util.http.URLMatcher; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.ContextUtil; import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.stream.Collectors; import javax.annotation.PostConstruct; import org.springframework.context.annotation.DependsOn; @@ -20,6 +19,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.FilterInvocation; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * 权限匹配管理器 @@ -36,7 +36,7 @@ public class AuthorityManager implements AccessDecisionManager { private void init() { SecurityProperties properties = ContextUtil.get(SecurityProperties.class); defaultDeniedRoles = Arrays.asList(new SecurityConfig(properties.getAuth().getDeniedRole())); - Objects.requireNonNull(defaultDeniedRoles); + Assert.notNull(defaultDeniedRoles, "defaultDeniedRoles must not be null"); } /** diff --git a/src/main/java/frodez/config/security/auth/AuthoritySource.java b/src/main/java/frodez/config/security/auth/AuthoritySource.java index a61b18f..d50836f 100644 --- a/src/main/java/frodez/config/security/auth/AuthoritySource.java +++ b/src/main/java/frodez/config/security/auth/AuthoritySource.java @@ -4,7 +4,7 @@ import frodez.dao.mapper.user.PermissionMapper; import frodez.dao.model.user.Permission; import frodez.util.constant.user.PermissionTypeEnum; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.ContextUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -13,10 +13,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.stream.Collectors; import javax.annotation.PostConstruct; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.DependsOn; import org.springframework.http.HttpMethod; import org.springframework.security.access.ConfigAttribute; @@ -24,6 +22,7 @@ import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * 获取权限资源 @@ -35,11 +34,8 @@ public class AuthoritySource implements FilterInvocationSecurityMetadataSource { /** - * 用户授权服务 + * 默认无权限角色 */ - @Autowired - private PermissionMapper permissionMapper; - private Collection defaultDeniedRoles; /** @@ -79,10 +75,10 @@ public void refresh() { */ @PostConstruct private void init() { - SecurityProperties properties = ContextUtil.get(SecurityProperties.class); - defaultDeniedRoles = Arrays.asList(new SecurityConfig(properties.getAuth().getDeniedRole())); + defaultDeniedRoles = Arrays.asList(new SecurityConfig(ContextUtil.get(SecurityProperties.class).getAuth() + .getDeniedRole())); if (allCache == null) { - List permissions = permissionMapper.selectAll(); + List permissions = ContextUtil.get(PermissionMapper.class).selectAll(); allCache = permissions.stream().map((iter) -> { return new SecurityConfig(iter.getName()); }).collect(Collectors.toList()); @@ -124,10 +120,10 @@ private void init() { urlTypeCache.put(url, typeMap); } } - Objects.requireNonNull(defaultDeniedRoles); - Objects.requireNonNull(allCache); - Objects.requireNonNull(urlCache); - Objects.requireNonNull(urlTypeCache); + Assert.notNull(defaultDeniedRoles, "defaultDeniedRoles must not be null"); + Assert.notNull(allCache, "allCache must not be null"); + Assert.notNull(urlCache, "urlCache must not be null"); + Assert.notNull(urlTypeCache, "urlTypeCache must not be null"); } /** diff --git a/src/main/java/frodez/config/security/login/UserUtil.java b/src/main/java/frodez/config/security/login/UserUtil.java index 0094708..d154a29 100644 --- a/src/main/java/frodez/config/security/login/UserUtil.java +++ b/src/main/java/frodez/config/security/login/UserUtil.java @@ -6,12 +6,13 @@ import frodez.service.user.facade.IAuthorityService; import frodez.util.beans.result.Result; import frodez.util.http.URLMatcher; -import frodez.util.spring.context.ContextUtil; -import java.util.Objects; +import frodez.util.spring.ContextUtil; +import frodez.util.spring.MVCUtil; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * 登录用户信息获取工具类 @@ -30,8 +31,8 @@ public class UserUtil { private void init() { authorityService = ContextUtil.get(IAuthorityService.class); tokenCache = ContextUtil.get(TokenCache.class); - Objects.requireNonNull(authorityService); - Objects.requireNonNull(tokenCache); + Assert.notNull(authorityService, "authorityService must not be null"); + Assert.notNull(tokenCache, "tokenCache must not be null"); } /** @@ -40,7 +41,7 @@ private void init() { * @date 2019-01-09 */ public static UserInfo get() { - HttpServletRequest request = ContextUtil.request(); + HttpServletRequest request = MVCUtil.request(); if (!URLMatcher.needVerify(request.getRequestURI())) { throw new RuntimeException("不能在免验证URI中获取token信息!"); } diff --git a/src/main/java/frodez/config/security/util/TokenManager.java b/src/main/java/frodez/config/security/util/TokenManager.java index 4dfe4eb..cb0491a 100644 --- a/src/main/java/frodez/config/security/util/TokenManager.java +++ b/src/main/java/frodez/config/security/util/TokenManager.java @@ -4,16 +4,16 @@ import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import frodez.config.security.settings.SecurityProperties; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.ContextUtil; import java.util.Date; import java.util.List; -import java.util.Objects; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import org.springframework.context.annotation.DependsOn; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * token工具类 @@ -60,13 +60,13 @@ private void init() { header = properties.getJwt().getHeader(); tokenPrefix = properties.getJwt().getTokenPrefix(); tokenPrefixLength = tokenPrefix.length(); - Objects.requireNonNull(algorithm); - Objects.requireNonNull(issuer); - Objects.requireNonNull(expiration); - Objects.requireNonNull(claim); - Objects.requireNonNull(header); - Objects.requireNonNull(tokenPrefix); - Objects.requireNonNull(tokenPrefixLength); + Assert.notNull(algorithm, "algorithm must not be null"); + Assert.notNull(issuer, "issuer must not be null"); + Assert.notNull(expiration, "expiration must not be null"); + Assert.notNull(claim, "claim must not be null"); + Assert.notNull(header, "header must not be null"); + Assert.notNull(tokenPrefix, "tokenPrefix must not be null"); + Assert.notNull(tokenPrefixLength, "tokenPrefixLength must not be null"); } /** diff --git a/src/main/java/frodez/config/swagger/SwaggerConfig.java b/src/main/java/frodez/config/swagger/SwaggerConfig.java index 3ee3a08..b9a04bf 100644 --- a/src/main/java/frodez/config/swagger/SwaggerConfig.java +++ b/src/main/java/frodez/config/swagger/SwaggerConfig.java @@ -4,7 +4,7 @@ import frodez.config.security.settings.SecurityProperties; import frodez.util.beans.result.Result; import frodez.util.constant.setting.PropertyKey; -import frodez.util.spring.properties.PropertyUtil; +import frodez.util.spring.PropertyUtil; import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/frodez/config/task/TaskProperties.java b/src/main/java/frodez/config/task/TaskProperties.java new file mode 100644 index 0000000..aa2f8a3 --- /dev/null +++ b/src/main/java/frodez/config/task/TaskProperties.java @@ -0,0 +1,29 @@ +package frodez.config.task; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +/** + * 定时任务配置 + * @author Frodez + * @date 2019-03-20 + */ +@Data +@Component +@PropertySource(value = { "classpath:settings/task.properties" }) +@ConfigurationProperties(prefix = "task") +public class TaskProperties { + + /** + * 前缀 + */ + private String prefix = ""; + + /** + * 最大任务数量 + */ + private Integer maxSize = 127; + +} diff --git a/src/main/java/frodez/controller/task/TaskController.java b/src/main/java/frodez/controller/task/TaskController.java new file mode 100644 index 0000000..6cb35e1 --- /dev/null +++ b/src/main/java/frodez/controller/task/TaskController.java @@ -0,0 +1,92 @@ +package frodez.controller.task; + +import frodez.dao.model.task.Task; +import frodez.dao.param.task.AddTask; +import frodez.dao.result.task.AvailableTaskInfo; +import frodez.service.task.base.BaseTaskService; +import frodez.util.beans.param.QueryPage; +import frodez.util.beans.result.Result; +import frodez.util.constant.setting.DefDesc; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 任务控制器 + * @author Frodez + * @date 2019-03-21 + */ +@RestController +@RequestMapping("/task") +@Api(tags = "任务控制器") +public class TaskController { + + @Autowired + private BaseTaskService taskService; + + @GetMapping("/availables") + @ApiOperation(value = "查询可用定时任务接口") + @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = AvailableTaskInfo.class) }) + public Result getAvailableTasks(@RequestBody @ApiParam(value = DefDesc.Message.PAGE_QUERY, + required = true) QueryPage param) { + return taskService.getAvailableTasks(param); + } + + @GetMapping("/runnings") + @ApiOperation(value = "查询正在运行定时任务接口") + @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = Task.class) }) + public Result getRunningTaskInfo(@RequestBody @ApiParam(value = DefDesc.Message.PAGE_QUERY, + required = true) QueryPage param) { + return taskService.getRunningTasksInfo(param); + } + + @GetMapping("/saves") + @ApiOperation(value = "查询已保存定时任务接口") + @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = Task.class) }) + public Result getTasks(@RequestBody @ApiParam(value = DefDesc.Message.PAGE_QUERY, + required = true) QueryPage param) { + return taskService.getTasks(param); + } + + @PostMapping("/add") + @ApiOperation(value = "添加新定时任务接口") + public Result addTask(@RequestBody @ApiParam(value = "新增定时任务请求参数", required = true) AddTask param) { + return taskService.addTask(param); + } + + @PostMapping("/cancel/all") + @ApiOperation(value = "取消所有定时任务接口") + public Result cancelAll() { + return taskService.cancelAllTasks(); + } + + @PostMapping("/cancel") + @ApiOperation(value = "取消定时任务接口") + public Result cancelTask(@RequestParam("id") @ApiParam(value = "任务ID", required = true) Long id) { + return taskService.cancelTask(id); + } + + @PostMapping("/change") + @ApiOperation(value = "更改定时任务活跃状态接口") + public Result changeStatus(@RequestParam("id") @ApiParam(value = "任务ID", required = true) Long id, + @RequestParam("status") @ApiParam(value = "是否立刻启动 1:立刻启动 2:暂不启动", required = true) Byte status) { + return taskService.changeStatus(id, status); + } + + @DeleteMapping + @ApiOperation(value = "删除定时任务接口") + public Result deleteTask(@RequestParam("id") @ApiParam(value = "任务ID", required = true) Long id) { + return taskService.deleteTask(id); + } + +} diff --git a/src/main/java/frodez/controller/user/PermissionController.java b/src/main/java/frodez/controller/user/PermissionController.java index 98908f7..d768216 100644 --- a/src/main/java/frodez/controller/user/PermissionController.java +++ b/src/main/java/frodez/controller/user/PermissionController.java @@ -1,7 +1,10 @@ package frodez.controller.user; import frodez.dao.model.user.Permission; +import frodez.dao.param.user.AddPermission; import frodez.dao.param.user.QueryRolePermission; +import frodez.dao.param.user.UpdatePermission; +import frodez.dao.result.user.PermissionDetail; import frodez.dao.result.user.PermissionInfo; import frodez.service.user.facade.IAuthorityService; import frodez.util.beans.param.QueryPage; @@ -13,9 +16,12 @@ import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -24,19 +30,21 @@ * @date 2018-12-01 */ @RestController -@RequestMapping("/user/permissions") +@RequestMapping("/permission") @Api(tags = "用户权限信息控制器") public class PermissionController { @Autowired private IAuthorityService authorityService; - /** - * 分页查询权限信息 - * @author Frodez - * @date 2019-03-06 - */ @GetMapping + @ApiOperation(value = "查询权限信息接口") + @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = PermissionDetail.class) }) + public Result getPermission(@RequestParam("id") @ApiParam(value = "权限ID", required = true) Long id) { + return authorityService.getPermission(id); + } + + @GetMapping("/page") @ApiOperation(value = "分页查询权限信息接口") @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = Permission.class) }) public Result getPermissions(@RequestBody @ApiParam(value = DefDesc.Message.PAGE_QUERY, @@ -44,11 +52,6 @@ public Result getPermissions(@RequestBody @ApiParam(value = DefDesc.Message.PAGE return authorityService.getPermissions(param); } - /** - * 根据角色ID获取权限信息 - * @author Frodez - * @date 2019-03-06 - */ @GetMapping("/byRoleId") @ApiOperation(value = "根据角色ID获取权限信息接口") @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = PermissionInfo.class) }) @@ -57,4 +60,22 @@ public Result getRolePermissions(@RequestBody @ApiParam(value = "权限信息获 return authorityService.getRolePermissions(param); } + @DeleteMapping + @ApiOperation(value = "删除权限接口") + public Result removePermission(@RequestParam("id") @ApiParam(value = "权限ID", required = true) Long id) { + return authorityService.removePermission(id); + } + + @PostMapping("/add") + @ApiOperation(value = "添加新权限接口") + public Result addPermission(@RequestBody @ApiParam(value = "新增权限请求参数", required = true) AddPermission param) { + return authorityService.addPermission(param); + } + + @PostMapping("/update") + @ApiOperation(value = "修改权限接口") + public Result updatePermission(@RequestBody @ApiParam(value = "修改权限请求参数", required = true) UpdatePermission param) { + return authorityService.updatePermission(param); + } + } diff --git a/src/main/java/frodez/controller/user/RoleController.java b/src/main/java/frodez/controller/user/RoleController.java index 7e4945c..ded4ed1 100644 --- a/src/main/java/frodez/controller/user/RoleController.java +++ b/src/main/java/frodez/controller/user/RoleController.java @@ -1,6 +1,10 @@ package frodez.controller.user; import frodez.dao.model.user.Role; +import frodez.dao.param.user.AddRole; +import frodez.dao.param.user.UpdateRole; +import frodez.dao.param.user.UpdateRolePermission; +import frodez.dao.result.user.RoleDetail; import frodez.service.user.facade.IAuthorityService; import frodez.util.beans.param.QueryPage; import frodez.util.beans.result.Result; @@ -11,9 +15,12 @@ import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -22,19 +29,26 @@ * @date 2018-12-01 */ @RestController -@RequestMapping("/user/roles") +@RequestMapping("/role") @Api(tags = "用户角色信息控制器") public class RoleController { @Autowired private IAuthorityService authorityService; + @GetMapping + @ApiOperation(value = "查询角色信息接口") + @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = RoleDetail.class) }) + public Result getRole(@RequestParam("id") @ApiParam(value = "角色ID", required = true) Long id) { + return authorityService.getRole(id); + } + /** * 分页查询角色信息 * @author Frodez * @date 2019-03-06 */ - @GetMapping + @GetMapping("/page") @ApiOperation(value = "分页查询角色信息接口") @ApiResponses(value = { @ApiResponse(code = 200, message = "成功", response = Role.class) }) public Result getRoles(@RequestBody @ApiParam(value = DefDesc.Message.PAGE_QUERY, @@ -42,4 +56,29 @@ public Result getRoles(@RequestBody @ApiParam(value = DefDesc.Message.PAGE_QUERY return authorityService.getRoles(param); } + @PostMapping("/updatePermission") + @ApiOperation(value = "修改角色权限接口") + public Result updateRolePermission(@RequestBody @ApiParam(value = "修改角色权限请求参数", + required = true) UpdateRolePermission param) { + return authorityService.updateRolePermission(param); + } + + @DeleteMapping + @ApiOperation(value = "删除角色接口") + public Result removeRole(@RequestParam("id") @ApiParam(value = "角色ID", required = true) Long id) { + return authorityService.removeRole(id); + } + + @PostMapping("/add") + @ApiOperation(value = "添加新角色接口") + public Result addRole(@RequestBody @ApiParam(value = "新增角色请求参数", required = true) AddRole param) { + return authorityService.addRole(param); + } + + @PostMapping("/update") + @ApiOperation(value = "修改角色接口") + public Result updateRole(@RequestBody @ApiParam(value = "修改角色请求参数", required = true) UpdateRole param) { + return authorityService.updateRole(param); + } + } diff --git a/src/main/java/frodez/controller/user/UserController.java b/src/main/java/frodez/controller/user/UserController.java index 5d48337..2986d30 100644 --- a/src/main/java/frodez/controller/user/UserController.java +++ b/src/main/java/frodez/controller/user/UserController.java @@ -1,6 +1,7 @@ package frodez.controller.user; import frodez.config.aop.request.annotation.RepeatLock; +import frodez.config.security.login.UserUtil; import frodez.dao.param.user.Doregister; import frodez.service.user.facade.IAuthorityService; import frodez.service.user.facade.IUserService; @@ -8,11 +9,13 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -32,24 +35,43 @@ public class UserController { private IUserService userService; @RepeatLock - @GetMapping("/self") - @ApiOperation(value = "查看本用户详情接口") - public Result getUserDetail() { - return null; + @GetMapping("/info/self") + @ApiOperation(value = "查看本用户信息接口") + public Result getUserInfo() { + return Result.success(UserUtil.get()); } @RepeatLock - @GetMapping("/detail") - @ApiOperation(value = "查看用户详情接口") - public Result getUserDetail(Long userId) { + @GetMapping("/info/byId") + @ApiOperation(value = "查看用户信息接口") + public Result getUserInfoById(@RequestParam("userId") @ApiParam(value = "用户ID", required = true) Long userId) { return authorityService.getUserInfo(userId); } - /** - * 注册接口 - * @author Frodez - * @date 2019-02-02 - */ + @RepeatLock + @GetMapping("/info/byName") + @ApiOperation(value = "查看用户信息接口") + public Result getUserInfoByName(@RequestParam("userName") @ApiParam(value = "用户名", + required = true) String userName) { + return authorityService.getUserInfo(userName); + } + + @RepeatLock + @GetMapping("/infos/byId") + @ApiOperation(value = "批量查看用户信息接口") + public Result getUserInfosById(@RequestParam("userId") @ApiParam(value = "用户ID", required = true) List< + Long> userIds) { + return authorityService.getUserInfosByIds(userIds, false); + } + + @RepeatLock + @GetMapping("/infos/byName") + @ApiOperation(value = "批量查看用户信息接口") + public Result getUserInfosByName(@RequestParam("userName") @ApiParam(value = "用户名", required = true) List< + String> userNames) { + return authorityService.getUserInfosByNames(userNames, false); + } + @RepeatLock @PostMapping("/register") @ApiOperation(value = "注册接口") diff --git a/src/main/java/frodez/dao/mapper/task/TaskMapper.java b/src/main/java/frodez/dao/mapper/task/TaskMapper.java new file mode 100644 index 0000000..5aa25de --- /dev/null +++ b/src/main/java/frodez/dao/mapper/task/TaskMapper.java @@ -0,0 +1,14 @@ +package frodez.dao.mapper.task; + +import frodez.config.mybatis.DataMapper; +import frodez.dao.model.task.Task; +import org.springframework.stereotype.Repository; + +/** + * @description 定时任务表 + * @table tb_spring_task + * @date 2019-03-20 + */ +@Repository +public interface TaskMapper extends DataMapper { +} \ No newline at end of file diff --git a/src/main/java/frodez/dao/mapper/task/TaskMapper.xml b/src/main/java/frodez/dao/mapper/task/TaskMapper.xml new file mode 100644 index 0000000..12f2616 --- /dev/null +++ b/src/main/java/frodez/dao/mapper/task/TaskMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/frodez/dao/model/task/Task.java b/src/main/java/frodez/dao/model/task/Task.java new file mode 100644 index 0000000..b5b36a6 --- /dev/null +++ b/src/main/java/frodez/dao/model/task/Task.java @@ -0,0 +1,68 @@ +package frodez.dao.model.task; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Data; + +/** + * @description 定时任务表 + * @table tb_spring_task + * @date 2019-03-20 + */ +@Data +@Entity +@Table(name = "tb_spring_task") +@ApiModel(description = "定时任务返回数据") +public class Task implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 定时任务ID(不能为空) + */ + @Id + @Column(name = "id") + @ApiModelProperty(value = "定时任务ID") + private Long id; + + /** + * 创建时间(不能为空) + */ + @Column(name = "create_time") + @ApiModelProperty(value = "创建时间") + private Date createTime; + + /** + * 活跃状态 1:活跃中 2:不活跃(不能为空) + */ + @Column(name = "status") + @ApiModelProperty(value = "活跃状态 1:活跃中 2:不活跃") + private Byte status; + + /** + * 目标(不能为空) + */ + @Column(name = "target", length = 255) + @ApiModelProperty(value = "目标") + private String target; + + /** + * 任务描述(不能为空) + */ + @Column(name = "description", length = 255) + @ApiModelProperty(value = "任务描述") + private String description; + + /** + * cron表达式(不能为空) + */ + @Column(name = "cron_exp", length = 31) + @ApiModelProperty(value = "cron表达式") + private String cronExp; +} diff --git a/src/main/java/frodez/dao/param/task/AddTask.java b/src/main/java/frodez/dao/param/task/AddTask.java new file mode 100644 index 0000000..f175e37 --- /dev/null +++ b/src/main/java/frodez/dao/param/task/AddTask.java @@ -0,0 +1,59 @@ +package frodez.dao.param.task; + +import frodez.config.aop.validation.annotation.common.LegalEnum; +import frodez.util.constant.task.StatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +/** + * 新增定时任务请求参数 + * @author Frodez + * @date 2019-03-20 + */ +@Data +@NoArgsConstructor +@ApiModel(description = "新增定时任务请求参数") +public class AddTask implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * 目标 + */ + @NotBlank(message = "目标不能为空!") + @Length(max = 255) + @ApiModelProperty(value = "目标", required = true) + private String target; + + /** + * 任务描述 + */ + @NotBlank(message = "任务描述不能为空!") + @Length(max = 65535) + @ApiModelProperty(value = "任务描述", required = true) + private String description; + + /** + * cron表达式 + */ + @NotBlank(message = "cron表达式不能为空!") + @Length(max = 31) + @ApiModelProperty(value = "cron表达式", required = true) + private String cronExp; + + /** + * 是否立刻启动 1:立刻启动 2:暂不启动 + */ + @LegalEnum(message = "是否立刻启动不能为空!", type = StatusEnum.class) + @ApiModelProperty(value = "是否立刻启动 1:立刻启动 2:暂不启动", required = true) + private Byte startNow; + +} diff --git a/src/main/java/frodez/dao/param/user/UpdatePermission.java b/src/main/java/frodez/dao/param/user/UpdatePermission.java index 911c6ae..b743097 100644 --- a/src/main/java/frodez/dao/param/user/UpdatePermission.java +++ b/src/main/java/frodez/dao/param/user/UpdatePermission.java @@ -7,6 +7,8 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; /** * 修改权限请求参数 @@ -15,6 +17,7 @@ */ @Data @NoArgsConstructor +@ApiModel(description = "修改权限请求参数") public class UpdatePermission implements Serializable { /** @@ -26,29 +29,34 @@ public class UpdatePermission implements Serializable { * 权限ID */ @NotNull(message = "权限ID不能为空!") + @ApiModelProperty(value = "权限ID", required = true) private Long id; /** * 类型 0:ALL 1:GET 2:POST 3:DELETE 4:PUT */ @LegalEnum(message = "类型错误!", type = PermissionTypeEnum.class) + @ApiModelProperty(value = "类型 0:ALL 1:GET 2:POST 3:DELETE 4:PUT") private Byte type; /** * 权限名称 */ @Length(max = 255) + @ApiModelProperty(value = "权限名称") private String name; /** * 地址 */ + @ApiModelProperty(value = "地址") private String url; /** * 描述 */ @Length(max = 1000) + @ApiModelProperty(value = "描述") private String description; } diff --git a/src/main/java/frodez/dao/param/user/UpdateRole.java b/src/main/java/frodez/dao/param/user/UpdateRole.java index 3907b3a..e8e1d3b 100644 --- a/src/main/java/frodez/dao/param/user/UpdateRole.java +++ b/src/main/java/frodez/dao/param/user/UpdateRole.java @@ -7,6 +7,8 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; /** * 修改角色请求参数 @@ -15,6 +17,7 @@ */ @Data @NoArgsConstructor +@ApiModel(description = "修改角色请求参数") public class UpdateRole implements Serializable { /** @@ -26,12 +29,14 @@ public class UpdateRole implements Serializable { * 角色ID */ @NotNull(message = "角色ID不能为空!") + @ApiModelProperty(value = "角色ID", required = true) private Long id; /** * 角色名称 */ @Length(max = 255) + @ApiModelProperty(value = "角色名称") private String name; /** @@ -39,12 +44,14 @@ public class UpdateRole implements Serializable { */ @Min(0) @Max(9) + @ApiModelProperty(value = "角色等级 0-9 0最高,9最低") private Byte level; /** * 描述 */ @Length(max = 1000) + @ApiModelProperty(value = "描述") private String description; } diff --git a/src/main/java/frodez/dao/param/user/SetRolePermission.java b/src/main/java/frodez/dao/param/user/UpdateRolePermission.java similarity index 65% rename from src/main/java/frodez/dao/param/user/SetRolePermission.java rename to src/main/java/frodez/dao/param/user/UpdateRolePermission.java index d0fc672..d25532a 100644 --- a/src/main/java/frodez/dao/param/user/SetRolePermission.java +++ b/src/main/java/frodez/dao/param/user/UpdateRolePermission.java @@ -1,7 +1,7 @@ package frodez.dao.param.user; import frodez.config.aop.validation.annotation.common.LegalEnum; -import frodez.util.constant.common.OperationEnum; +import frodez.util.constant.common.ModifyEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; @@ -11,14 +11,14 @@ import lombok.NoArgsConstructor; /** - * 赋予角色权限请求参数 + * 修改角色权限请求参数 * @author Frodez * @date 2019-03-17 */ @Data @NoArgsConstructor -@ApiModel(description = "赋予角色权限请求参数") -public class SetRolePermission implements Serializable { +@ApiModel(description = "修改角色权限请求参数") +public class UpdateRolePermission implements Serializable { /** * @@ -33,10 +33,10 @@ public class SetRolePermission implements Serializable { private Long roleId; /** - * 操作类型 1:新增 2:删除 3:修改 4:查询(不支持) + * 操作类型 1:新增 2:删除 3:修改 */ - @LegalEnum(message = "操作类型错误!", type = OperationEnum.class) - @ApiModelProperty(value = "操作类型 1:新增 2:删除 3:修改 4:查询(不支持)", required = true) + @LegalEnum(message = "操作类型错误!", type = ModifyEnum.class) + @ApiModelProperty(value = "操作类型 1:新增 2:删除 3:修改", required = true) private Byte operationType; /** diff --git a/src/main/java/frodez/dao/result/task/AvailableTaskInfo.java b/src/main/java/frodez/dao/result/task/AvailableTaskInfo.java new file mode 100644 index 0000000..cbd92bf --- /dev/null +++ b/src/main/java/frodez/dao/result/task/AvailableTaskInfo.java @@ -0,0 +1,42 @@ +package frodez.dao.result.task; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 可用任务信息 + * @author Frodez + * @date 2019-03-21 + */ +@Data +@NoArgsConstructor +@ApiModel(value = "可用任务信息返回数据") +public class AvailableTaskInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @ApiModelProperty(value = "名称") + private String name; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String description; + + /** + * 可被强制中断(只是建议,非必要) + */ + @ApiModelProperty(value = "可被强制中断(只是建议,非必要)") + private Boolean permitForceInterrupt; + +} diff --git a/src/main/java/frodez/dao/result/user/PermissionDetail.java b/src/main/java/frodez/dao/result/user/PermissionDetail.java new file mode 100644 index 0000000..2e82b0e --- /dev/null +++ b/src/main/java/frodez/dao/result/user/PermissionDetail.java @@ -0,0 +1,68 @@ +package frodez.dao.result.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 权限详细信息返回数据 + * @author Frodez + * @date 2019-03-19 + */ +@Data +@NoArgsConstructor +@ApiModel(value = "权限详细信息返回数据") +public class PermissionDetail implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * 权限ID + */ + @ApiModelProperty(value = "权限ID") + private Long id; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + private Date createTime; + + /** + * 类型 1:GET 2:POST 3:DELETE 4:PUT + */ + @ApiModelProperty(value = "类型 1:GET 2:POST 3:DELETE 4:PUT") + private Byte type; + + /** + * 权限名称 + */ + @ApiModelProperty(value = "权限名称") + private String name; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址") + private String url; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String description; + + /** + * 拥有该权限的角色ID + */ + @ApiModelProperty(value = "拥有该权限的角色ID") + private List roleIds; + +} diff --git a/src/main/java/frodez/dao/result/user/RoleDetail.java b/src/main/java/frodez/dao/result/user/RoleDetail.java new file mode 100644 index 0000000..2f3a45a --- /dev/null +++ b/src/main/java/frodez/dao/result/user/RoleDetail.java @@ -0,0 +1,62 @@ +package frodez.dao.result.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 角色详细信息返回数据 + * @author Frodez + * @date 2019-03-19 + */ +@Data +@NoArgsConstructor +@ApiModel(value = "角色详细信息返回数据") +public class RoleDetail implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * 角色ID(不能为空) + */ + @ApiModelProperty(value = "角色ID") + private Long id; + + /** + * 创建时间(不能为空) + */ + @ApiModelProperty(value = "创建时间") + private Date createTime; + + /** + * 角色名称(不能为空) + */ + @ApiModelProperty(value = "角色名称") + private String name; + + /** + * 角色等级 0-9 0最高,9最低(不能为空,默认值:0) + */ + @ApiModelProperty(value = "角色等级 0-9 0最高,9最低", example = "0") + private Byte level = 0; + + /** + * 描述 + */ + @ApiModelProperty(value = "描述") + private String description; + + /** + * 角色拥有的权限ID + */ + @ApiModelProperty(value = "角色拥有的权限ID") + private List permissionIds; + +} diff --git a/src/main/java/frodez/service/cache/package-info.java b/src/main/java/frodez/service/cache/package-info.java index 68511e5..98d7d2c 100644 --- a/src/main/java/frodez/service/cache/package-info.java +++ b/src/main/java/frodez/service/cache/package-info.java @@ -2,7 +2,7 @@ * 本包用于存放所有与业务有关的cache。
* base包为cache的基础包,包括了基本redis service和cache接口。
* vm包存放了使用jvm作为存储的cache实现。
- * 在没有特殊需求时,可以直接使用基本redis service。但建议最好实现cache接口,对专用的业务逻辑使用专门的cache。 + * 在没有特殊需求(比如持久化)时,可以直接使用基本redis service。但建议最好实现cache接口,对专用的业务逻辑使用专门的cache。 * @author Frodez * @date 2019-03-11 */ diff --git a/src/main/java/frodez/service/package-info.java b/src/main/java/frodez/service/package-info.java index edba169..ee4a315 100644 --- a/src/main/java/frodez/service/package-info.java +++ b/src/main/java/frodez/service/package-info.java @@ -1,6 +1,6 @@ /** * 本包用于存放service。按业务模块划分子包。
- * 除cache包外,每个子包均有两个子包:facade为接口,service为实现。
+ * 除cache包和task包外,每个子包均有两个子包:facade为接口,service为实现。
* @author Frodez * @date 2019-03-11 */ diff --git a/src/main/java/frodez/service/task/HelloWorldTask.java b/src/main/java/frodez/service/task/HelloWorldTask.java new file mode 100644 index 0000000..08a8834 --- /dev/null +++ b/src/main/java/frodez/service/task/HelloWorldTask.java @@ -0,0 +1,25 @@ +package frodez.service.task; + +import frodez.service.task.base.ITask; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Component +@Transactional +@Service +public class HelloWorldTask implements ITask { + + @Override + public void run() { + log.info("hello world!"); + } + + @Override + public String getDescription() { + return "hello world!"; + } + +} diff --git a/src/main/java/frodez/service/task/base/BaseTaskService.java b/src/main/java/frodez/service/task/base/BaseTaskService.java new file mode 100644 index 0000000..c804d34 --- /dev/null +++ b/src/main/java/frodez/service/task/base/BaseTaskService.java @@ -0,0 +1,367 @@ +package frodez.service.task.base; + +import com.github.pagehelper.PageHelper; +import frodez.config.aop.validation.annotation.Check; +import frodez.config.aop.validation.annotation.common.LegalEnum; +import frodez.config.task.TaskProperties; +import frodez.dao.mapper.task.TaskMapper; +import frodez.dao.model.task.Task; +import frodez.dao.param.task.AddTask; +import frodez.dao.result.task.AvailableTaskInfo; +import frodez.util.beans.param.QueryPage; +import frodez.util.beans.result.Result; +import frodez.util.constant.setting.DefStr; +import frodez.util.constant.task.StatusEnum; +import frodez.util.error.ErrorCode; +import frodez.util.error.exception.ServiceException; +import frodez.util.reflect.BeanUtil; +import frodez.util.spring.ContextUtil; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.transaction.annotation.Transactional; +import tk.mybatis.mapper.entity.Example; + +@Slf4j +@Configuration +@EnableScheduling +public class BaseTaskService { + + @Autowired + private ThreadPoolTaskScheduler scheduler; + + @Autowired + private TaskProperties properties; + + @Autowired + private TaskMapper taskMapper; + + /** + * 可用任务信息 + */ + private List taskServiceInfos; + + /** + * 当前任务 + */ + private Map> taskMap = new ConcurrentHashMap<>(); + + /** + * 当前任务信息 + */ + private Map taskInfoMap = new ConcurrentHashMap<>(); + + /** + * 初始化
+ * @author Frodez + * @date 2019-03-21 + */ + @PostConstruct + private void init() { + try { + taskServiceInfos = ContextUtil.gets(ITask.class).entrySet().stream().map((entry) -> { + AvailableTaskInfo info = new AvailableTaskInfo(); + info.setName(entry.getKey()); + info.setDescription(entry.getValue().getDescription()); + info.setPermitForceInterrupt(!canForcelyIntterrupt(entry.getValue())); + return info; + }).collect(Collectors.toList()); + Example example = new Example(Task.class); + example.createCriteria().andNotIn("target", taskServiceInfos.stream().map(AvailableTaskInfo::getName) + .collect(Collectors.toList())); + taskMapper.deleteByExample(example); + example.clear(); + example.createCriteria().andIsNotNull("target").andEqualTo("status", StatusEnum.ACTIVE.getVal()); + example.orderBy("id"); + PageHelper.startPage(new QueryPage(properties.getMaxSize())); + List tasks = taskMapper.selectByExample(example); + tasks.parallelStream().forEach((task) -> { + Runnable runnable = null; + CronTrigger trigger = null; + try { + runnable = getRunnable(task.getTarget()); + } catch (ClassNotFoundException e) { + log.error("init", e); + log.warn("初始化任务——类型初始化失败!类型名:{}", task.getTarget()); + return; + } + try { + trigger = new CronTrigger(task.getCronExp()); + } catch (IllegalArgumentException e) { + log.error("init", e); + log.warn("初始化任务——时间表达式错误!表达式:{}", task.getCronExp()); + return; + } + if (runnable != null && trigger != null) { + taskMap.put(task.getId(), scheduler.schedule(runnable, trigger)); + taskInfoMap.put(task.getId(), task); + } + }); + } catch (Exception e) { + log.error("初始化任务错误!应用仍将继续启动...", e); + } + } + + /** + * 判断是否为可以强行中断的接口 + * @author Frodez + * @date 2019-03-21 + */ + private boolean canForcelyIntterrupt(Runnable runnable) { + return isTransactional(runnable); + } + + /** + * 判断是否为带有事务的接口 + * @author Frodez + * @date 2019-03-21 + */ + private boolean isTransactional(Runnable runnable) { + try { + return runnable.getClass().getAnnotation(Transactional.class) != null || runnable.getClass().getMethod( + "run").getAnnotation(Transactional.class) != null; + } catch (NoSuchMethodException e) { + return false; + } catch (SecurityException e) { + return false; + } + } + + /** + * 获取可用的定时任务实例用于开启定时任务 + * @author Frodez + * @date 2019-03-21 + */ + private Runnable getRunnable(String className) throws ClassNotFoundException { + return (Runnable) ContextUtil.get(Class.forName(properties.getPrefix().concat(DefStr.POINT_SEPERATOR).concat( + className))); + } + + /** + * 是否可用 + * @author Frodez + * @date 2019-03-21 + */ + private boolean isAvailable(String target) { + return taskServiceInfos.stream().filter((iter) -> { + return iter.getName().equals(target); + }).count() != 0; + } + + /** + * 获得可用的任务 + * @author Frodez + * @date 2019-03-21 + */ + @Check + public Result getAvailableTasks(@Valid @NotNull QueryPage param) { + try { + param = QueryPage.resonable(param); + List infos = taskServiceInfos.stream().skip((param.getPageNum() - 1) * param + .getPageSize()).limit(param.getPageNum() * param.getPageSize()).collect(Collectors.toList()); + return Result.page(param.getPageNum(), param.getPageSize(), infos.size(), infos); + } catch (Exception e) { + log.error("[getAllAvailableTasks]", e); + return Result.errorService(); + } + } + + /** + * 获取正在运行的任务信息 + * @author Frodez + * @date 2019-03-21 + */ + @Check + public Result getRunningTasksInfo(@Valid @NotNull QueryPage param) { + try { + param = QueryPage.resonable(param); + List tasks = taskInfoMap.values().stream().skip((param.getPageNum() - 1) * param.getPageSize()).limit( + param.getPageNum() * param.getPageSize()).collect(Collectors.toList()); + return Result.page(param.getPageNum(), param.getPageSize(), tasks.size(), tasks); + } catch (Exception e) { + log.error("[getRunningTasksInfo]", e); + return Result.errorService(); + } + } + + /** + * 获取保存的任务信息 + * @author Frodez + * @date 2019-03-21 + */ + @Check + public Result getTasks(@Valid @NotNull QueryPage param) { + try { + return Result.page(PageHelper.startPage(QueryPage.resonable(param)).doSelectPage(() -> { + taskMapper.selectAll(); + })); + } catch (Exception e) { + log.error("[getRunningTasks]", e); + return Result.errorService(); + } + } + + /** + * 强制取消当前所有任务 + * @author Frodez + * @date 2019-03-21 + */ + public Result cancelAllTasks() { + try { + int total = taskMap.size(); + int alreadyCanceled = 0; + for (Entry> entry : taskMap.entrySet()) { + if (entry.getValue().cancel(true)) { + taskMap.remove(entry.getKey()); + taskInfoMap.remove(entry.getKey()); + alreadyCanceled++; + } + } + return Result.success("共计" + total + "个任务正在执行,已取消" + alreadyCanceled + "个。"); + } catch (Exception e) { + log.error("[cancelAllTasks]", e); + return Result.errorService(); + } + } + + /** + * 添加任务 + * @author Frodez + * @date 2019-03-21 + */ + @Check + @Transactional + public Result addTask(@Valid @NotNull AddTask param) { + try { + if (isAvailable(param.getTarget())) { + return Result.fail("非法的类型!"); + } + Runnable runnable; + CronTrigger trigger; + try { + runnable = getRunnable(param.getTarget()); + trigger = new CronTrigger(param.getCronExp()); + } catch (ClassNotFoundException e) { + return Result.fail("类型初始化失败!"); + } catch (IllegalArgumentException e) { + return Result.fail("时间表达式错误!"); + } + if (taskMapper.selectCount(null) >= properties.getMaxSize()) { + return Result.fail("已达可用任务最大数量!"); + } + Task task = new Task(); + BeanUtil.copy(param, task); + task.setCreateTime(new Date()); + task.setStatus(param.getStartNow()); + taskMapper.insertUseGeneratedKeys(task); + if (param.getStartNow() == StatusEnum.ACTIVE.getVal()) { + taskMap.put(task.getId(), scheduler.schedule(runnable, trigger)); + taskInfoMap.put(task.getId(), task); + } + return Result.success(task.getId()); + } catch (Exception e) { + log.error("[addJob]", e); + throw new ServiceException(ErrorCode.TASK_SERVICE_ERROR); + } + } + + /** + * 中止并删除任务 + * @author Frodez + * @date 2019-03-21 + */ + @Check + public Result deleteTask(@NotNull Long id) { + try { + Task task = taskMapper.selectByPrimaryKey(id); + if (task == null) { + return Result.fail("未找到该任务!"); + } + ScheduledFuture future = taskMap.get(id); + if (future != null) { + Runnable runnable; + try { + runnable = getRunnable(task.getTarget()); + } catch (ClassNotFoundException e) { + return Result.fail("类型初始化失败!"); + } + boolean mayInterruptIfRunning = canForcelyIntterrupt(runnable); + if (!future.cancel(mayInterruptIfRunning)) { + if (mayInterruptIfRunning) { + return Result.fail("该任务正在执行,且不能强行中止,因此暂不能删除!"); + } else { + return Result.fail("该任务正在执行,且中止失败,因此暂不能删除!"); + } + } + } + taskMapper.deleteByPrimaryKey(id); + taskMap.remove(id); + taskInfoMap.remove(id); + return Result.success(); + } catch (Exception e) { + log.error("[removeJob]", e); + throw new ServiceException(ErrorCode.TASK_SERVICE_ERROR); + } + } + + /** + * 中止任务 + * @author Frodez + * @date 2019-03-21 + */ + @Check + public Result cancelTask(@NotNull Long id) { + try { + ScheduledFuture future = taskMap.get(id); + if (future == null) { + return Result.fail("未找到该任务!"); + } + if (!future.cancel(true)) { + return Result.fail("强行取消任务失败!"); + } + taskMap.remove(id); + taskInfoMap.remove(id); + return Result.success(); + } catch (Exception e) { + log.error("[removeJob]", e); + return Result.errorService(); + } + } + + /** + * 更改任务活跃状态 + * @author Frodez + * @date 2019-03-21 + */ + @Check + @Transactional + public Result changeStatus(@NotNull Long id, @LegalEnum(message = "是否立刻启动不能为空!", + type = StatusEnum.class) Byte status) { + try { + Task task = taskMapper.selectByPrimaryKey(id); + if (task == null) { + return Result.fail("未找到该任务!"); + } + task.setStatus(status); + taskMapper.updateByPrimaryKeySelective(task); + return Result.success(); + } catch (Exception e) { + log.error("[removeJob]", e); + throw new ServiceException(ErrorCode.TASK_SERVICE_ERROR); + } + } + +} diff --git a/src/main/java/frodez/service/task/base/ITask.java b/src/main/java/frodez/service/task/base/ITask.java new file mode 100644 index 0000000..c7f6d59 --- /dev/null +++ b/src/main/java/frodez/service/task/base/ITask.java @@ -0,0 +1,7 @@ +package frodez.service.task.base; + +public interface ITask extends Runnable { + + String getDescription(); + +} diff --git a/src/main/java/frodez/service/task/package-info.java b/src/main/java/frodez/service/task/package-info.java new file mode 100644 index 0000000..58aa8a4 --- /dev/null +++ b/src/main/java/frodez/service/task/package-info.java @@ -0,0 +1,6 @@ +/** + * 本包用于存放spring task定时任务相关实现 + * @author Frodez + * @date 2019-03-19 + */ +package frodez.service.task; diff --git a/src/main/java/frodez/service/user/facade/IAuthorityService.java b/src/main/java/frodez/service/user/facade/IAuthorityService.java index 9245624..fc3d9d9 100644 --- a/src/main/java/frodez/service/user/facade/IAuthorityService.java +++ b/src/main/java/frodez/service/user/facade/IAuthorityService.java @@ -3,11 +3,12 @@ import frodez.dao.param.user.AddPermission; import frodez.dao.param.user.AddRole; import frodez.dao.param.user.QueryRolePermission; -import frodez.dao.param.user.SetRolePermission; import frodez.dao.param.user.UpdatePermission; import frodez.dao.param.user.UpdateRole; +import frodez.dao.param.user.UpdateRolePermission; import frodez.util.beans.param.QueryPage; import frodez.util.beans.result.Result; +import frodez.util.constant.annotation.ServiceOnly; import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotBlank; @@ -22,46 +23,62 @@ public interface IAuthorityService { /** - * 根据用户ID查询用户信息 + * 根据用户ID查询用户基本信息 * @author Frodez * @date 2019-03-06 */ - Result getUserInfo(@Valid @NotNull Long userId); + Result getUserInfo(@NotNull Long userId); /** - * 根据用户名获取用户信息 + * 根据用户名获取用户基本信息 * @author Frodez * @date 2018-11-14 */ Result getUserInfo(@NotBlank String userName); /** - * 根据用户ID批量获取用户信息 + * 分页查询用户基本信息 + * @author Frodez + * @date 2019-03-19 + */ + Result getUserInfos(@Valid @NotNull QueryPage param); + + /** + * 根据用户ID批量获取用户基本信息 * @author Frodez * @date 2019-03-17 */ - Result getUserInfosByIds(@NotEmpty List userIds); + Result getUserInfosByIds(@NotEmpty List userIds, boolean includeFobiddens); /** - * 根据用户名批量获取用户信息 + * 根据用户名批量获取用户基本信息 * @author Frodez * @date 2019-03-17 */ - Result getUserInfosByNames(@NotEmpty List userNames); + Result getUserInfosByNames(@NotEmpty List userNames, boolean includeFobiddens); /** - * 根据用户ID更新用户信息 + * 根据用户ID更新用户基本信息 * @author Frodez * @date 2019-03-16 */ - Result refreshUserInfoByIds(@NotEmpty List userIds); + @ServiceOnly + Result refreshUserInfoByIds(@NotEmpty List userIds, boolean includeFobiddens); /** - * 根据用户名更新用户信息 + * 根据用户名更新用户基本信息 * @author Frodez * @date 2019-03-16 */ - Result refreshUserInfoByNames(@NotEmpty List userNames); + @ServiceOnly + Result refreshUserInfoByNames(@NotEmpty List userNames, boolean includeFobiddens); + + /** + * 获取权限信息 + * @author Frodez + * @date 2019-03-19 + */ + Result getPermission(@NotNull Long permissionId); /** * 分页查询权限信息 @@ -70,6 +87,13 @@ public interface IAuthorityService { */ Result getPermissions(@Valid @NotNull QueryPage param); + /** + * 获取角色信息 + * @author Frodez + * @date 2019-03-19 + */ + Result getRole(@NotNull Long roleId); + /** * 分页查询角色信息 * @author Frodez @@ -113,10 +137,31 @@ public interface IAuthorityService { Result updatePermission(@Valid @NotNull UpdatePermission param); /** - * 赋予角色权限(并覆盖原权限) + * 修改角色权限 * @author Frodez * @date 2019-03-15 */ - Result setRolePermission(@Valid @NotNull SetRolePermission param); + Result updateRolePermission(@Valid @NotNull UpdateRolePermission param); + + /** + * 删除角色 + * @author Frodez + * @date 2019-03-18 + */ + Result removeRole(@NotNull Long roleId); + + /** + * 删除权限 + * @author Frodez + * @date 2019-03-18 + */ + Result removePermission(@NotNull Long permissionId); + + /** + * 扫描系统中所有端点并添加权限 + * @author Frodez + * @date 2019-03-18 + */ + Result scanAndCreatePermissions(); } diff --git a/src/main/java/frodez/service/user/impl/AuthorityService.java b/src/main/java/frodez/service/user/impl/AuthorityService.java index 28e5e87..6f708dc 100644 --- a/src/main/java/frodez/service/user/impl/AuthorityService.java +++ b/src/main/java/frodez/service/user/impl/AuthorityService.java @@ -1,5 +1,6 @@ package frodez.service.user.impl; +import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import frodez.config.aop.validation.annotation.Check; import frodez.config.security.auth.AuthorityManager; @@ -15,10 +16,12 @@ import frodez.dao.param.user.AddPermission; import frodez.dao.param.user.AddRole; import frodez.dao.param.user.QueryRolePermission; -import frodez.dao.param.user.SetRolePermission; import frodez.dao.param.user.UpdatePermission; import frodez.dao.param.user.UpdateRole; +import frodez.dao.param.user.UpdateRolePermission; +import frodez.dao.result.user.PermissionDetail; import frodez.dao.result.user.PermissionInfo; +import frodez.dao.result.user.RoleDetail; import frodez.dao.result.user.UserInfo; import frodez.service.cache.vm.facade.NameCache; import frodez.service.cache.vm.facade.TokenCache; @@ -28,13 +31,18 @@ import frodez.util.beans.param.QueryPage; import frodez.util.beans.result.Result; import frodez.util.common.EmptyUtil; -import frodez.util.constant.common.OperationEnum; +import frodez.util.constant.common.ModifyEnum; +import frodez.util.constant.setting.PropertyKey; import frodez.util.constant.user.PermissionTypeEnum; import frodez.util.constant.user.UserStatusEnum; import frodez.util.error.ErrorCode; import frodez.util.error.exception.ServiceException; +import frodez.util.http.URLMatcher; import frodez.util.reflect.BeanUtil; -import frodez.util.spring.context.ContextUtil; +import frodez.util.reflect.ReflectUtil; +import frodez.util.spring.ContextUtil; +import frodez.util.spring.MVCUtil; +import frodez.util.spring.PropertyUtil; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -44,10 +52,14 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import tk.mybatis.mapper.entity.Example; /** @@ -157,10 +169,27 @@ public Result getUserInfo(String userName) { @Check @Override - public Result getUserInfosByIds(List userIds) { + public Result getUserInfos(QueryPage param) { + try { + Page page = PageHelper.startPage(QueryPage.resonable(param)).doSelectPage(() -> { + userMapper.selectAll(); + }); + return Result.page(page.getPageNum(), page.getPageSize(), page.getTotal(), getUserInfos(page.getResult())); + } catch (Exception e) { + log.error("[getUserInfos]", e); + return Result.errorService(); + } + } + + @Check + @Override + public Result getUserInfosByIds(List userIds, boolean includeFobiddens) { try { Example example = new Example(User.class); - example.createCriteria().andEqualTo("status", UserStatusEnum.NORMAL.getVal()).andIn("id", userIds); + example.createCriteria().andIn("id", userIds); + if (includeFobiddens) { + example.and().andEqualTo("status", UserStatusEnum.NORMAL.getVal()); + } List users = userMapper.selectByExample(example); if (users.size() != userIds.size()) { return Result.fail("存在非法的用户ID!"); @@ -174,10 +203,13 @@ public Result getUserInfosByIds(List userIds) { @Check @Override - public Result getUserInfosByNames(List userNames) { + public Result getUserInfosByNames(List userNames, boolean includeFobiddens) { try { Example example = new Example(User.class); - example.createCriteria().andEqualTo("status", UserStatusEnum.NORMAL.getVal()).andIn("name", userNames); + example.createCriteria().andIn("name", userNames); + if (includeFobiddens) { + example.and().andEqualTo("status", UserStatusEnum.NORMAL.getVal()); + } List users = userMapper.selectByExample(example); if (users.size() != userNames.size()) { return Result.fail("存在非法的用户名!"); @@ -191,10 +223,13 @@ public Result getUserInfosByNames(List userNames) { @Check @Override - public Result refreshUserInfoByIds(List userIds) { + public Result refreshUserInfoByIds(List userIds, boolean includeFobiddens) { try { Example example = new Example(User.class); - example.createCriteria().andEqualTo("status", UserStatusEnum.NORMAL.getVal()).andIn("id", userIds); + example.createCriteria().andIn("id", userIds); + if (includeFobiddens) { + example.and().andEqualTo("status", UserStatusEnum.NORMAL.getVal()); + } List users = userMapper.selectByExample(example); if (users.size() != userIds.size()) { return Result.fail("存在非法的用户ID!"); @@ -209,10 +244,13 @@ public Result refreshUserInfoByIds(List userIds) { @Check @Override - public Result refreshUserInfoByNames(List userNames) { + public Result refreshUserInfoByNames(List userNames, boolean includeFobiddens) { try { Example example = new Example(User.class); - example.createCriteria().andEqualTo("status", UserStatusEnum.NORMAL.getVal()).andIn("name", userNames); + example.createCriteria().andIn("name", userNames); + if (includeFobiddens) { + example.and().andEqualTo("status", UserStatusEnum.NORMAL.getVal()); + } List users = userMapper.selectByExample(example); if (users.size() != userNames.size()) { return Result.fail("存在非法的用户名!"); @@ -239,31 +277,29 @@ private List getUserInfos(List users) { })); Map> rolePermissionsMap = new HashMap<>(); for (Long roleId : roleIds) { - List list = permissions.stream().filter((iter) -> { + rolePermissionsMap.put(roleId, permissions.stream().filter((iter) -> { return roleId.equals(iter.getId()); }).map((iter) -> { PermissionInfo info = new PermissionInfo(); BeanUtil.copy(iter, info); return info; - }).collect(Collectors.toList()); - rolePermissionsMap.put(roleId, list); + }).collect(Collectors.toList())); } - List userInfos = new ArrayList<>(); - for (User user : users) { + List userInfos = users.stream().map((user) -> { UserInfo info = new UserInfo(); BeanUtil.copy(user, info); info.setRoleName(roleMap.get(user.getRoleId()).getName()); info.setRoleLevel(roleMap.get(user.getRoleId()).getLevel()); info.setRoleDescription(roleMap.get(user.getRoleId()).getDescription()); info.setPermissionList(rolePermissionsMap.get(user.getRoleId())); - userInfos.add(info); - } + return info; + }).collect(Collectors.toList()); return userInfos; } private void refreshUserInfo(List userInfos) { Stream stream = userInfos.stream(); - if (userInfos.size() > 1024 || tokenCache.size() > 1024) { + if (Runtime.getRuntime().availableProcessors() > 1 && userInfos.size() > 1024 || tokenCache.size() > 1024) { stream = stream.parallel(); } stream.forEach((item) -> { @@ -275,6 +311,27 @@ private void refreshUserInfo(List userInfos) { }); } + @Check + @Override + public Result getPermission(Long permissionId) { + try { + Permission permission = permissionMapper.selectByPrimaryKey(permissionId); + if (permission == null) { + return Result.fail("未找到该权限!"); + } + PermissionDetail data = new PermissionDetail(); + BeanUtil.copy(permission, data); + Example example = new Example(RolePermission.class); + example.createCriteria().andEqualTo("permissionId", permissionId); + data.setRoleIds(rolePermissionMapper.selectByExample(example).stream().map(RolePermission::getRoleId) + .collect(Collectors.toList())); + return Result.success(data); + } catch (Exception e) { + log.error("[getAllRoles]", e); + return Result.errorService(); + } + } + @Check @Override public Result getPermissions(QueryPage param) { @@ -287,6 +344,27 @@ public Result getPermissions(QueryPage param) { } } + @Check + @Override + public Result getRole(Long roleId) { + try { + Role role = roleMapper.selectByPrimaryKey(roleId); + if (role == null) { + return Result.fail("未找到该角色!"); + } + RoleDetail data = new RoleDetail(); + BeanUtil.copy(role, data); + Example example = new Example(RolePermission.class); + example.createCriteria().andEqualTo("roleId", roleId); + data.setPermissionIds(rolePermissionMapper.selectByExample(example).stream().map( + RolePermission::getPermissionId).collect(Collectors.toList())); + return Result.success(data); + } catch (Exception e) { + log.error("[getAllRoles]", e); + return Result.errorService(); + } + } + @Check @Override public Result getRoles(QueryPage param) { @@ -394,6 +472,9 @@ public Result addPermission(AddPermission param) { if (checkPermissionName(param.getName())) { return Result.fail("权限不能重名!"); } + if (URLMatcher.isPermitAllPath(param.getUrl())) { + return Result.fail("免验证路径不能配备权限!"); + } if (!checkPermissionUrl(PermissionTypeEnum.of(param.getType()), param.getUrl())) { return Result.fail("系统不存在与此匹配的url!"); } @@ -401,12 +482,14 @@ public Result addPermission(AddPermission param) { BeanUtil.copy(param, permission); permission.setCreateTime(new Date()); permissionMapper.insert(permission); - authorityManager.refresh(); - authoritySource.refresh(); return Result.success(); } catch (Exception e) { log.error("[addPermission]", e); - throw new ServiceException(ErrorCode.USER_SERVICE_ERROR); + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.errorService(); + } finally { + authorityManager.refresh(); + authoritySource.refresh(); } } @@ -419,6 +502,12 @@ public Result updatePermission(UpdatePermission param) { .getUrl() == null) { return Result.errorRequest("类型和url必须同时存在!"); } + if (param.getUrl() != null && URLMatcher.isPermitAllPath(param.getUrl())) { + return Result.fail("免验证路径不能配备权限!"); + } + if (!checkPermissionUrl(PermissionTypeEnum.of(param.getType()), param.getUrl())) { + return Result.fail("系统不存在与此匹配的url!"); + } Permission permission = permissionMapper.selectByPrimaryKey(param.getId()); if (permission == null) { return Result.fail("找不到该权限!"); @@ -426,17 +515,16 @@ public Result updatePermission(UpdatePermission param) { if (param.getName() != null && checkPermissionName(param.getName())) { return Result.fail("权限不能重名!"); } - if (!checkPermissionUrl(PermissionTypeEnum.of(param.getType()), param.getUrl())) { - return Result.fail("系统不存在与此匹配的url!"); - } BeanUtil.cover(param, permission); permissionMapper.updateByPrimaryKeySelective(permission); - authorityManager.refresh(); - authoritySource.refresh(); return Result.success(); } catch (Exception e) { log.error("[addPermission]", e); - throw new ServiceException(ErrorCode.USER_SERVICE_ERROR); + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.errorService(); + } finally { + authorityManager.refresh(); + authoritySource.refresh(); } } @@ -448,27 +536,27 @@ public Result updatePermission(UpdatePermission param) { private boolean checkPermissionUrl(PermissionTypeEnum type, String url) { switch (type) { case GET : { - return ContextUtil.getAllEndPoints().get(RequestMethod.GET).stream().filter((iter) -> { + return MVCUtil.endPoints().get(RequestMethod.GET).stream().filter((iter) -> { return iter.getPatternsCondition().getPatterns().iterator().next().equals(url); }).count() != 0; } case POST : { - return ContextUtil.getAllEndPoints().get(RequestMethod.POST).stream().filter((iter) -> { + return MVCUtil.endPoints().get(RequestMethod.POST).stream().filter((iter) -> { return iter.getPatternsCondition().getPatterns().iterator().next().equals(url); }).count() != 0; } case DELETE : { - return ContextUtil.getAllEndPoints().get(RequestMethod.DELETE).stream().filter((iter) -> { + return MVCUtil.endPoints().get(RequestMethod.DELETE).stream().filter((iter) -> { return iter.getPatternsCondition().getPatterns().iterator().next().equals(url); }).count() != 0; } case PUT : { - return ContextUtil.getAllEndPoints().get(RequestMethod.PUT).stream().filter((iter) -> { + return MVCUtil.endPoints().get(RequestMethod.PUT).stream().filter((iter) -> { return iter.getPatternsCondition().getPatterns().iterator().next().equals(url); }).count() != 0; } case ALL : { - return ContextUtil.getAllEndPoints().values().stream().flatMap(Collection::stream).filter((iter) -> { + return MVCUtil.endPoints().values().stream().flatMap(Collection::stream).filter((iter) -> { return iter.getPatternsCondition().getPatterns().contains(url); }).count() != 0; } @@ -481,19 +569,16 @@ private boolean checkPermissionUrl(PermissionTypeEnum type, String url) { @Check @Transactional @Override - public Result setRolePermission(SetRolePermission param) { + public Result updateRolePermission(UpdateRolePermission param) { try { + if (ModifyEnum.UPDATE.getVal() != param.getOperationType() && EmptyUtil.yes(param.getPermissionIds())) { + return Result.errorRequest("不能对角色新增或者删除一个空的权限!"); + } Role role = roleMapper.selectByPrimaryKey(param.getRoleId()); if (role == null) { return Result.fail("找不到该角色!"); } - if (OperationEnum.SELECT.getVal() == param.getOperationType()) { - return Result.errorRequest("本方法不支持查询类型!"); - } - if (OperationEnum.UPDATE.getVal() != param.getOperationType() && EmptyUtil.yes(param.getPermissionIds())) { - return Result.errorRequest("新增和删除角色对应权限时,权限ID不能为空!"); - } - switch (OperationEnum.of(param.getOperationType())) { + switch (ModifyEnum.of(param.getOperationType())) { case INSERT : { Example example = new Example(Permission.class); example.createCriteria().andIn("id", param.getPermissionIds()); @@ -563,7 +648,118 @@ public Result setRolePermission(SetRolePermission param) { return Result.success(); } catch (Exception e) { log.error("[setRolePermission]", e); - throw new ServiceException(ErrorCode.USER_SERVICE_ERROR); + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.errorService(); + } finally { + authorityManager.refresh(); + authoritySource.refresh(); + } + } + + @Check + @Transactional + @Override + public Result removeRole(Long roleId) { + try { + Role role = roleMapper.selectByPrimaryKey(roleId); + if (role == null) { + return Result.fail("找不到该角色!"); + } + Example example = new Example(User.class); + example.createCriteria().andEqualTo("roleId", roleId); + if (userMapper.selectCountByExample(example) != 0) { + return Result.fail("仍存在使用该角色的用户,请更改该用户角色后再删除!"); + } + roleMapper.deleteByPrimaryKey(roleId); + example = new Example(RolePermission.class); + example.createCriteria().andEqualTo("roleId", roleId); + rolePermissionMapper.deleteByExample(example); + return Result.success(); + } catch (Exception e) { + log.error("[removeRole]", e); + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.errorService(); + } finally { + authorityManager.refresh(); + authoritySource.refresh(); + } + } + + @Check + @Transactional + @Override + public Result removePermission(Long permissionId) { + try { + Permission permission = permissionMapper.selectByPrimaryKey(permissionId); + if (permission == null) { + return Result.fail("找不到该权限!"); + } + Example example = new Example(RolePermission.class); + example.createCriteria().andEqualTo("permissionId", permissionId); + if (rolePermissionMapper.selectCountByExample(example) != 0) { + return Result.fail("仍存在使用该权限的角色,请更改该角色权限后再删除!"); + } + rolePermissionMapper.deleteByExample(example); + permissionMapper.deleteByPrimaryKey(permissionId); + return Result.success(); + } catch (Exception e) { + log.error("[removePermission]", e); + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.errorService(); + } finally { + authorityManager.refresh(); + authoritySource.refresh(); + } + } + + @Transactional + @Override + public Result scanAndCreatePermissions() { + try { + List permissionList = new ArrayList<>(); + Date date = new Date(); + BeanFactoryUtils.beansOfTypeIncludingAncestors(ContextUtil.context(), HandlerMapping.class, true, false) + .values().stream().filter((iter) -> { + return iter instanceof RequestMappingHandlerMapping; + }).map((iter) -> { + return ((RequestMappingHandlerMapping) iter).getHandlerMethods().entrySet(); + }).flatMap(Collection::stream).forEach((entry) -> { + String requestUrl = PropertyUtil.get(PropertyKey.Web.BASE_PATH) + entry.getKey() + .getPatternsCondition().getPatterns().stream().findFirst().get(); + if (!URLMatcher.needVerify(requestUrl)) { + return; + } + requestUrl = requestUrl.substring(PropertyUtil.get(PropertyKey.Web.BASE_PATH).length()); + String requestType = entry.getKey().getMethodsCondition().getMethods().stream().map( + RequestMethod::name).findFirst().orElse(PermissionTypeEnum.ALL.name()); + String permissionName = ReflectUtil.getShortMethodName(entry.getValue().getMethod()); + Permission permission = new Permission(); + permission.setCreateTime(date); + permission.setUrl(requestUrl); + permission.setName(permissionName); + permission.setDescription(permissionName); + if (requestType.equals("GET")) { + permission.setType(PermissionTypeEnum.GET.getVal()); + } else if (requestType.equals("POST")) { + permission.setType(PermissionTypeEnum.POST.getVal()); + } else if (requestType.equals("DELETE")) { + permission.setType(PermissionTypeEnum.DELETE.getVal()); + } else if (requestType.equals("PUT")) { + permission.setType(PermissionTypeEnum.PUT.getVal()); + } else { + permission.setType(PermissionTypeEnum.ALL.getVal()); + } + permissionList.add(permission); + }); + permissionMapper.insertList(permissionList); + return Result.success(); + } catch (Exception e) { + log.error("[scanAndCreatePermissions]", e); + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.errorService(); + } finally { + authorityManager.refresh(); + authoritySource.refresh(); } } diff --git a/src/main/java/frodez/service/user/impl/LoginService.java b/src/main/java/frodez/service/user/impl/LoginService.java index e3a1936..0d9e3fa 100644 --- a/src/main/java/frodez/service/user/impl/LoginService.java +++ b/src/main/java/frodez/service/user/impl/LoginService.java @@ -10,7 +10,7 @@ import frodez.service.user.facade.IAuthorityService; import frodez.service.user.facade.ILoginService; import frodez.util.beans.result.Result; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.MVCUtil; import java.util.List; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -100,7 +100,7 @@ public Result refresh(DoRefresh param) { String token = TokenManager.generate(param.getUsername(), authorities); tokenCache.remove(param.getOldToken()); tokenCache.save(token, userInfo); - logoutHandler.logout(ContextUtil.request(), ContextUtil.response(), SecurityContextHolder.getContext() + logoutHandler.logout(MVCUtil.request(), MVCUtil.response(), SecurityContextHolder.getContext() .getAuthentication()); SecurityContextHolder.getContext().setAuthentication(authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(param.getUsername(), userInfo.getPassword()))); @@ -114,14 +114,13 @@ public Result refresh(DoRefresh param) { @Override public Result logout() { try { - HttpServletRequest request = ContextUtil.request(); + HttpServletRequest request = MVCUtil.request(); String token = TokenManager.getRealToken(request); if (!tokenCache.existKey(token)) { return Result.fail("用户已下线!"); } tokenCache.remove(token); - logoutHandler.logout(request, ContextUtil.response(), SecurityContextHolder.getContext() - .getAuthentication()); + logoutHandler.logout(request, MVCUtil.response(), SecurityContextHolder.getContext().getAuthentication()); return Result.success(); } catch (Exception e) { log.error("[logout]", e); diff --git a/src/main/java/frodez/util/aop/AspectUtil.java b/src/main/java/frodez/util/aop/AspectUtil.java index 7e4cda9..caa026a 100644 --- a/src/main/java/frodez/util/aop/AspectUtil.java +++ b/src/main/java/frodez/util/aop/AspectUtil.java @@ -16,7 +16,7 @@ public class AspectUtil { private static MethodSignature methodSignature(final JoinPoint point) { - return MethodSignature.class.cast(point.getSignature()); + return (MethodSignature) point.getSignature(); } /** diff --git a/src/main/java/frodez/util/beans/pair/ComPair.java b/src/main/java/frodez/util/beans/pair/ComPair.java index f4262e7..07d33f2 100644 --- a/src/main/java/frodez/util/beans/pair/ComPair.java +++ b/src/main/java/frodez/util/beans/pair/ComPair.java @@ -2,6 +2,12 @@ import lombok.EqualsAndHashCode; +/** + * 比较键值对
+ * 警告!!!本类重写了compareTo方法,以key值为比较对象。 + * @author Frodez + * @date 2019-03-20 + */ @EqualsAndHashCode(callSuper = true) public class ComPair, V> extends Pair implements Comparable> { diff --git a/src/main/java/frodez/util/beans/pair/StrComPair.java b/src/main/java/frodez/util/beans/pair/StrComPair.java index a61ad43..bb01639 100644 --- a/src/main/java/frodez/util/beans/pair/StrComPair.java +++ b/src/main/java/frodez/util/beans/pair/StrComPair.java @@ -2,6 +2,12 @@ import lombok.EqualsAndHashCode; +/** + * 比较键值对
+ * 警告!!!本类重写了compareTo方法,以key值为比较对象。 + * @author Frodez + * @date 2019-03-20 + */ @EqualsAndHashCode(callSuper = true) public class StrComPair extends ComPair { diff --git a/src/main/java/frodez/util/beans/param/QueryPage.java b/src/main/java/frodez/util/beans/param/QueryPage.java index 1a37df9..5a48a38 100644 --- a/src/main/java/frodez/util/beans/param/QueryPage.java +++ b/src/main/java/frodez/util/beans/param/QueryPage.java @@ -32,6 +32,11 @@ public class QueryPage implements IPage, Serializable { private static final QueryPage DEFAULT = new QueryPage(DefPage.PAGE_NUM, DefPage.PAGE_SIZE); + public QueryPage(Integer pageSize) { + this.pageNum = DefPage.PAGE_NUM; + this.pageSize = pageSize == null ? DefPage.PAGE_SIZE : pageSize; + } + /** * 合理化请求参数 * @author Frodez diff --git a/src/main/java/frodez/util/beans/result/Result.java b/src/main/java/frodez/util/beans/result/Result.java index f9ddac3..aad7b65 100644 --- a/src/main/java/frodez/util/beans/result/Result.java +++ b/src/main/java/frodez/util/beans/result/Result.java @@ -10,16 +10,17 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; +import java.util.Collection; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import org.springframework.http.HttpStatus; +import org.springframework.util.Assert; /** * 通用返回参数
@@ -38,17 +39,17 @@ public final class Result implements Serializable { /** * 默认json,只有默认类型实例才存在 */ - private String json; + private transient String json; /** * 默认类型实例 */ - private static final Map DEFAULT_RESULT_CACHE = new EnumMap<>(ResultEnum.class); + private static transient final Map DEFAULT_RESULT_CACHE = new EnumMap<>(ResultEnum.class); /** * jackson writer */ - private static ObjectWriter writer; + private static transient ObjectWriter writer; static { writer = JSONUtil.mapper().writerFor(Result.class); @@ -140,17 +141,27 @@ public static Result success() { * @date 2019-01-15 */ public static Result success(Object data) { - Objects.requireNonNull(data); + Assert.notNull(data, "data must not be null"); return new Result(ResultEnum.SUCCESS, data); } + /** + * 返回分页查询类型结果(仅在成功时使用) + * @author Frodez + * @date 2019-01-15 + */ + public static Result page(int pageNum, int pageSize, long total, Collection data) { + Assert.notNull(data, "data must not be null"); + return new Result(ResultEnum.SUCCESS, new PageData<>(pageNum, pageSize, total, data)); + } + /** * 返回分页查询类型结果(仅在成功时使用) * @author Frodez * @date 2019-01-15 */ public static Result page(Page page) { - Objects.requireNonNull(page); + Assert.notNull(page, "page must not be null"); return new Result(ResultEnum.SUCCESS, new PageData<>(page.getPageNum(), page.getPageSize(), page.getTotal(), page.getResult())); } @@ -161,7 +172,7 @@ public static Result page(Page page) { * @date 2019-01-15 */ public static Result page(PageInfo page) { - Objects.requireNonNull(page); + Assert.notNull(page, "page must not be null"); return new Result(ResultEnum.SUCCESS, new PageData<>(page.getPageNum(), page.getPageSize(), page.getTotal(), page.getList())); } @@ -181,7 +192,7 @@ public static Result fail() { * @date 2019-01-15 */ public static Result fail(String message) { - Objects.requireNonNull(message); + Assert.notNull(message, "message must not be null"); return new Result(message, ResultEnum.FAIL); } @@ -200,7 +211,7 @@ public static Result errorRequest() { * @date 2019-02-02 */ public static Result errorRequest(String message) { - Objects.requireNonNull(message); + Assert.notNull(message, "message must not be null"); return new Result(message, ResultEnum.ERROR_REQUEST); } @@ -219,7 +230,7 @@ public static Result errorService() { * @date 2019-01-15 */ public static Result errorService(String message) { - Objects.requireNonNull(message); + Assert.notNull(message, "message must not be null"); return new Result(message, ResultEnum.ERROR_SERVICE); } @@ -303,10 +314,11 @@ private Result(ResultEnum status) { * @param klass 类型 * @date 2018-11-13 */ + @SuppressWarnings("unchecked") public T as(Class klass) throws ClassCastException, ParseException { - Objects.requireNonNull(klass); + Assert.notNull(klass, "klass must not be null"); ableAndNotNull(); - return klass.cast(data); + return (T) data; } /** @@ -317,7 +329,7 @@ public T as(Class klass) throws ClassCastException, ParseException { */ @SuppressWarnings("unchecked") public PageData page(Class klass) throws ClassCastException, ParseException { - Objects.requireNonNull(klass); + Assert.notNull(klass, "klass must not be null"); ableAndNotNull(); return (PageData) data; } @@ -330,7 +342,7 @@ public PageData page(Class klass) throws ClassCastException, ParseExce */ @SuppressWarnings("unchecked") public List list(Class klass) throws ClassCastException, ParseException { - Objects.requireNonNull(klass); + Assert.notNull(klass, "klass must not be null"); ableAndNotNull(); return (List) data; } @@ -343,7 +355,7 @@ public List list(Class klass) throws ClassCastException, ParseExceptio */ @SuppressWarnings("unchecked") public Set set(Class klass) throws ClassCastException, ParseException { - Objects.requireNonNull(klass); + Assert.notNull(klass, "klass must not be null"); ableAndNotNull(); return (Set) data; } @@ -368,8 +380,8 @@ public Map map() throws ClassCastException, ParseException { */ @SuppressWarnings("unchecked") public Map map(Class keyClass, Class valueClass) throws ClassCastException, ParseException { - Objects.requireNonNull(keyClass); - Objects.requireNonNull(valueClass); + Assert.notNull(keyClass, "keyClass must not be null"); + Assert.notNull(valueClass, "valueClass must not be null"); ableAndNotNull(); return (Map) data; } diff --git a/src/main/java/frodez/util/common/DateUtil.java b/src/main/java/frodez/util/common/DateUtil.java index b5ac9db..92b37f4 100644 --- a/src/main/java/frodez/util/common/DateUtil.java +++ b/src/main/java/frodez/util/common/DateUtil.java @@ -9,8 +9,8 @@ import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Date; -import java.util.Objects; import lombok.experimental.UtilityClass; +import org.springframework.util.Assert; /** * 日期工具类 @@ -79,7 +79,7 @@ public static Date date(String date) { * @date 2019-03-01 */ public static boolean isDate(String date) { - Objects.requireNonNull(date); + Assert.notNull(date, "date must not be null"); try { LocalDate.parse(date, DATE_FORMATTER); return true; @@ -103,7 +103,7 @@ public static Date time(String date) { * @date 2019-03-01 */ public static boolean isTime(String date) { - Objects.requireNonNull(date); + Assert.notNull(date, "date must not be null"); try { LocalTime.parse(date, TIME_FORMATTER); return true; @@ -127,7 +127,7 @@ public static Date dateTime(String date) { * @date 2019-03-01 */ public static boolean isDateTime(String date) { - Objects.requireNonNull(date); + Assert.notNull(date, "date must not be null"); try { LocalDateTime.parse(date, DATE_TIME_FORMATTER); return true; diff --git a/src/main/java/frodez/util/common/DecimalUtil.java b/src/main/java/frodez/util/common/DecimalUtil.java index d9b746f..8b88a80 100644 --- a/src/main/java/frodez/util/common/DecimalUtil.java +++ b/src/main/java/frodez/util/common/DecimalUtil.java @@ -2,8 +2,8 @@ import frodez.util.constant.setting.DefDecimal; import java.math.BigDecimal; -import java.util.Objects; import lombok.experimental.UtilityClass; +import org.springframework.util.Assert; @UtilityClass public class DecimalUtil { @@ -14,7 +14,7 @@ public class DecimalUtil { * @date 2019-01-28 */ public static BigDecimal normalize(BigDecimal decimal) { - Objects.requireNonNull(decimal); + Assert.notNull(decimal, "decimal must not be null"); return decimal.setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE); } @@ -24,7 +24,7 @@ public static BigDecimal normalize(BigDecimal decimal) { * @date 2019-01-28 */ public static BigDecimal normalize(Integer value) { - Objects.requireNonNull(value); + Assert.notNull(value, "value must not be null"); return new BigDecimal(value).setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE); } @@ -34,7 +34,7 @@ public static BigDecimal normalize(Integer value) { * @date 2019-01-28 */ public static BigDecimal normalize(Double value) { - Objects.requireNonNull(value); + Assert.notNull(value, "value must not be null"); return new BigDecimal(value).setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE); } @@ -44,7 +44,7 @@ public static BigDecimal normalize(Double value) { * @date 2019-01-28 */ public static BigDecimal normalize(Long value) { - Objects.requireNonNull(value); + Assert.notNull(value, "value must not be null"); return new BigDecimal(value).setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE); } @@ -54,7 +54,7 @@ public static BigDecimal normalize(Long value) { * @date 2019-01-28 */ public static BigDecimal normalize(String value) { - Objects.requireNonNull(value); + Assert.notNull(value, "value must not be null"); return new BigDecimal(value).setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE); } diff --git a/src/main/java/frodez/util/common/StrUtil.java b/src/main/java/frodez/util/common/StrUtil.java index 74f41ef..1c8867a 100644 --- a/src/main/java/frodez/util/common/StrUtil.java +++ b/src/main/java/frodez/util/common/StrUtil.java @@ -17,7 +17,7 @@ public static String get(@Nullable Object object, String defaultStr) { return defaultStr; } if (object.getClass() == BigDecimal.class) { - return BigDecimal.class.cast(object).setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE).toString(); + return ((BigDecimal) object).setScale(DefDecimal.PRECISION, DefDecimal.ROUND_MODE).toString(); } return object.toString(); } diff --git a/src/main/java/frodez/util/constant/annotation/ServiceOnly.java b/src/main/java/frodez/util/constant/annotation/ServiceOnly.java new file mode 100644 index 0000000..7be0aa8 --- /dev/null +++ b/src/main/java/frodez/util/constant/annotation/ServiceOnly.java @@ -0,0 +1,19 @@ +package frodez.util.constant.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 本注解标明的方法或者类下的所有方法,不要用于controller中,只能用于内部调用或者远程调用。 + * @author Frodez + * @date 2019-03-18 + */ +@Documented +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.SOURCE) +public @interface ServiceOnly { + +} diff --git a/src/main/java/frodez/util/constant/common/ModifyEnum.java b/src/main/java/frodez/util/constant/common/ModifyEnum.java new file mode 100644 index 0000000..4b0e003 --- /dev/null +++ b/src/main/java/frodez/util/constant/common/ModifyEnum.java @@ -0,0 +1,47 @@ +package frodez.util.constant.common; + +import java.util.HashMap; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 修改操作类型枚举 + * @author Frodez + * @date 2019-03-17 + */ +@Getter +@AllArgsConstructor +public enum ModifyEnum { + + /** + * 新增 + */ + INSERT((byte) 1, "新增"), + /** + * 删除 + */ + DELETE((byte) 2, "删除"), + /** + * 修改 + */ + UPDATE((byte) 3, "修改"); + + private byte val; + + private String desc; + + private static final Map enumMap; + + static { + enumMap = new HashMap<>(); + for (ModifyEnum iter : ModifyEnum.values()) { + enumMap.put(iter.val, iter); + } + } + + public static ModifyEnum of(byte value) { + return enumMap.get(value); + } + +} diff --git a/src/main/java/frodez/util/constant/common/OperationEnum.java b/src/main/java/frodez/util/constant/common/OperationEnum.java index c1ad2a7..4e518b6 100644 --- a/src/main/java/frodez/util/constant/common/OperationEnum.java +++ b/src/main/java/frodez/util/constant/common/OperationEnum.java @@ -25,11 +25,11 @@ public enum OperationEnum { /** * 修改 */ - UPDATE((byte) 2, "修改"), + UPDATE((byte) 3, "修改"), /** * 查询 */ - SELECT((byte) 2, "查询"); + SELECT((byte) 4, "查询"); private byte val; diff --git a/src/main/java/frodez/util/constant/package-info.java b/src/main/java/frodez/util/constant/package-info.java index 5b73780..cd82e93 100644 --- a/src/main/java/frodez/util/constant/package-info.java +++ b/src/main/java/frodez/util/constant/package-info.java @@ -1,5 +1,5 @@ /** - * 本包存放了项目的公共常量。
+ * 本包存放了项目的公共常量和注解。
* @author Frodez * @date 2019-03-11 */ diff --git a/src/main/java/frodez/util/constant/setting/DefStr.java b/src/main/java/frodez/util/constant/setting/DefStr.java index 1dd0590..0a6b80a 100644 --- a/src/main/java/frodez/util/constant/setting/DefStr.java +++ b/src/main/java/frodez/util/constant/setting/DefStr.java @@ -4,4 +4,6 @@ public class DefStr { public static final String SEPERATOR = ":"; + public static final String POINT_SEPERATOR = "."; + } diff --git a/src/main/java/frodez/util/constant/setting/PropertyKey.java b/src/main/java/frodez/util/constant/setting/PropertyKey.java index de2583a..d70eef2 100644 --- a/src/main/java/frodez/util/constant/setting/PropertyKey.java +++ b/src/main/java/frodez/util/constant/setting/PropertyKey.java @@ -26,6 +26,11 @@ public class Web { */ public static final String PORT = "server.port"; + /** + * 默认错误路径 + */ + public static final String ERROR_PATH = "server.error.path"; + } /** diff --git a/src/main/java/frodez/util/constant/task/StatusEnum.java b/src/main/java/frodez/util/constant/task/StatusEnum.java new file mode 100644 index 0000000..24c2626 --- /dev/null +++ b/src/main/java/frodez/util/constant/task/StatusEnum.java @@ -0,0 +1,43 @@ +package frodez.util.constant.task; + +import java.util.HashMap; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 任务状态枚举 + * @author Frodez + * @date 2019-03-20 + */ +@Getter +@AllArgsConstructor +public enum StatusEnum { + + /** + * 1:活跃中 + */ + ACTIVE((byte) 1, "活跃中"), + /** + * 2:不活跃 + */ + PAUSED((byte) 2, "不活跃"); + + private byte val; + + private String desc; + + private static final Map enumMap; + + static { + enumMap = new HashMap<>(); + for (StatusEnum iter : StatusEnum.values()) { + enumMap.put(iter.val, iter); + } + } + + public static StatusEnum of(byte value) { + return enumMap.get(value); + } + +} diff --git a/src/main/java/frodez/util/error/ErrorCode.java b/src/main/java/frodez/util/error/ErrorCode.java index 9c509e3..ca0c313 100644 --- a/src/main/java/frodez/util/error/ErrorCode.java +++ b/src/main/java/frodez/util/error/ErrorCode.java @@ -2,7 +2,6 @@ import java.util.HashMap; import java.util.Map; - import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +9,9 @@ @AllArgsConstructor public enum ErrorCode { - USER_SERVICE_ERROR("用户信息服务失败!"); + USER_SERVICE_ERROR("用户信息服务失败!"), + + TASK_SERVICE_ERROR("定时任务服务失败!"); private String description; diff --git a/src/main/java/frodez/util/http/ServletUtil.java b/src/main/java/frodez/util/http/ServletUtil.java index 69ddf3d..722b550 100644 --- a/src/main/java/frodez/util/http/ServletUtil.java +++ b/src/main/java/frodez/util/http/ServletUtil.java @@ -4,13 +4,13 @@ import frodez.util.common.EmptyUtil; import frodez.util.constant.setting.DefCharset; import java.io.PrintWriter; -import java.util.Objects; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.experimental.UtilityClass; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.util.Assert; /** * HTTP工具类 @@ -62,7 +62,7 @@ public static String getAddr(HttpServletRequest request) { * @date 2019-01-07 */ public static void writeJson(HttpServletResponse response, Result result) { - Objects.requireNonNull(result); + Assert.notNull(result, "result must not be null"); if (response.isCommitted()) { return; } diff --git a/src/main/java/frodez/util/http/URLMatcher.java b/src/main/java/frodez/util/http/URLMatcher.java index a58c2aa..7bb095c 100644 --- a/src/main/java/frodez/util/http/URLMatcher.java +++ b/src/main/java/frodez/util/http/URLMatcher.java @@ -1,19 +1,20 @@ package frodez.util.http; import frodez.config.security.settings.SecurityProperties; +import frodez.dao.mapper.user.PermissionMapper; import frodez.util.constant.setting.PropertyKey; -import frodez.util.spring.context.ContextUtil; -import frodez.util.spring.properties.PropertyUtil; +import frodez.util.spring.ContextUtil; +import frodez.util.spring.PropertyUtil; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Objects; import java.util.Set; import javax.annotation.PostConstruct; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; import org.springframework.util.PathMatcher; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -34,21 +35,20 @@ public class URLMatcher { @PostConstruct private void init() { - SecurityProperties securityProperties = ContextUtil.get(SecurityProperties.class); PathMatcher matcher = ContextUtil.get(PathMatcher.class); String basePath = PropertyUtil.get(PropertyKey.Web.BASE_PATH); List permitPaths = new ArrayList<>(); - for (String path : securityProperties.getAuth().getPermitAllPath()) { + for (String path : ContextUtil.get(SecurityProperties.class).getAuth().getPermitAllPath()) { permitUrls.add(basePath + path); permitPaths.add(basePath + path); } - String errorPath = basePath + "/error"; + String errorPath = basePath + PropertyUtil.get(PropertyKey.Web.ERROR_PATH); permitUrls.add(errorPath); BeanFactoryUtils.beansOfTypeIncludingAncestors(ContextUtil.context(), HandlerMapping.class, true, false) .values().stream().filter((iter) -> { return iter instanceof RequestMappingHandlerMapping; }).map((iter) -> { - return RequestMappingHandlerMapping.class.cast(iter).getHandlerMethods().entrySet(); + return ((RequestMappingHandlerMapping) iter).getHandlerMethods().entrySet(); }).flatMap(Collection::stream).forEach((entry) -> { String requestUrl = PropertyUtil.get(PropertyKey.Web.BASE_PATH) + entry.getKey().getPatternsCondition() .getPatterns().iterator().next(); @@ -62,8 +62,13 @@ private void init() { } needVerifyUrls.add(requestUrl); }); - Objects.requireNonNull(needVerifyUrls); - Objects.requireNonNull(permitUrls); + Assert.notNull(needVerifyUrls, "needVerifyUrls must not be null"); + Assert.notNull(permitUrls, "permitUrls must not be null"); + if (ContextUtil.get(PermissionMapper.class).selectAll().stream().filter((iter) -> { + return permitUrls.contains(PropertyUtil.get(PropertyKey.Web.BASE_PATH) + iter.getUrl()); + }).count() != 0) { + throw new RuntimeException("不能在免验证路径下配置权限!"); + } } /** diff --git a/src/main/java/frodez/util/json/JSONUtil.java b/src/main/java/frodez/util/json/JSONUtil.java index 264ad25..93e53be 100644 --- a/src/main/java/frodez/util/json/JSONUtil.java +++ b/src/main/java/frodez/util/json/JSONUtil.java @@ -9,7 +9,7 @@ import com.google.common.escape.Escaper; import com.google.common.escape.Escapers; import frodez.util.common.EmptyUtil; -import frodez.util.spring.context.ContextUtil; +import frodez.util.spring.ContextUtil; import java.io.InputStream; import java.lang.reflect.Type; import java.util.ArrayList; @@ -17,12 +17,12 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * json工具类 @@ -100,8 +100,8 @@ public int[] getEscapeCodesForAscii() { return asciiEscapes; } }); - Objects.requireNonNull(OBJECT_MAPPER); - Objects.requireNonNull(DEFAULT_MAP_READER); + Assert.notNull(OBJECT_MAPPER, "OBJECT_MAPPER must not be null"); + Assert.notNull(DEFAULT_MAP_READER, "DEFAULT_MAP_READER must not be null"); } /** @@ -120,7 +120,7 @@ public static ObjectMapper mapper() { * @date 2018-12-02 */ public static String string(Object object) { - Objects.requireNonNull(object); + Assert.notNull(object, "object must not be null"); try { return writerCache.computeIfAbsent(object.getClass(), (o) -> OBJECT_MAPPER.writerFor(object.getClass())) .writeValueAsString(object); @@ -138,7 +138,7 @@ public static String string(Object object) { * @date 2018-12-02 */ public static Map map(InputStream stream) { - Objects.requireNonNull(stream); + Assert.notNull(stream, "stream must not be null"); try { return DEFAULT_MAP_READER.readValue(stream); } catch (Exception e) { @@ -155,7 +155,7 @@ public static Map map(InputStream stream) { * @date 2018-12-02 */ public static Map map(String json) { - Objects.requireNonNull(json); + Assert.notNull(json, "json must not be null"); try { return DEFAULT_MAP_READER.readValue(json); } catch (Exception e) { @@ -172,9 +172,9 @@ public static Map map(String json) { * @date 2018-12-02 */ public static Map map(InputStream stream, Class k, Class v) { - Objects.requireNonNull(stream); - Objects.requireNonNull(k); - Objects.requireNonNull(v); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(k, "k must not be null"); + Assert.notNull(v, "v must not be null"); try { return multiClassReaderCache.computeIfAbsent(DEFAULT_MAP_CLASS_NAME.concat(k.getName()).concat(v.getName()), (i) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER.getTypeFactory().constructParametricType(DEFAULT_MAP_CLASS, @@ -193,9 +193,9 @@ public static Map map(InputStream stream, Class k, Class v) { * @date 2018-12-02 */ public static Map map(String json, Class k, Class v) { - Objects.requireNonNull(json); - Objects.requireNonNull(k); - Objects.requireNonNull(v); + Assert.notNull(json, "json must not be null"); + Assert.notNull(k, "k must not be null"); + Assert.notNull(v, "v must not be null"); try { return multiClassReaderCache.computeIfAbsent(DEFAULT_MAP_CLASS_NAME.concat(k.getName()).concat(v.getName()), (i) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER.getTypeFactory().constructParametricType(DEFAULT_MAP_CLASS, @@ -213,8 +213,8 @@ public static Map map(String json, Class k, Class v) { * @date 2018-12-02 */ public static List list(InputStream stream, Class klass) { - Objects.requireNonNull(stream); - Objects.requireNonNull(klass); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(stream, "stream must not be null"); try { return multiClassReaderCache.computeIfAbsent(DEFAULT_LIST_CLASS_NAME.concat(klass.getName()), ( i) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER.getTypeFactory().constructParametricType(DEFAULT_LIST_CLASS, @@ -232,8 +232,8 @@ public static List list(InputStream stream, Class klass) { * @date 2018-12-02 */ public static List list(String json, Class klass) { - Objects.requireNonNull(json); - Objects.requireNonNull(klass); + Assert.notNull(json, "json must not be null"); + Assert.notNull(klass, "klass must not be null"); try { return multiClassReaderCache.computeIfAbsent(DEFAULT_LIST_CLASS_NAME.concat(klass.getName()), ( i) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER.getTypeFactory().constructParametricType(DEFAULT_LIST_CLASS, @@ -251,8 +251,8 @@ public static List list(String json, Class klass) { * @date 2018-12-02 */ public static Set set(InputStream stream, Class klass) { - Objects.requireNonNull(stream); - Objects.requireNonNull(klass); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(klass, "klass must not be null"); try { return multiClassReaderCache.computeIfAbsent(DEFAULT_SET_CLASS_NAME.concat(klass.getName()), ( i) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER.getTypeFactory().constructParametricType(DEFAULT_SET_CLASS, @@ -270,8 +270,8 @@ public static Set set(InputStream stream, Class klass) { * @date 2018-12-02 */ public static Set set(String json, Class klass) { - Objects.requireNonNull(json); - Objects.requireNonNull(klass); + Assert.notNull(json, "json must not be null"); + Assert.notNull(klass, "klass must not be null"); try { return multiClassReaderCache.computeIfAbsent(DEFAULT_SET_CLASS_NAME.concat(klass.getName()), ( i) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER.getTypeFactory().constructParametricType(DEFAULT_SET_CLASS, @@ -289,8 +289,8 @@ public static Set set(String json, Class klass) { * @date 2018-12-02 */ public static T as(InputStream stream, Class klass) { - Objects.requireNonNull(stream); - Objects.requireNonNull(klass); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(klass, "klass must not be null"); try { return singleClassReaderCache.computeIfAbsent(klass, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER .getTypeFactory().constructType(klass))).readValue(stream); @@ -307,8 +307,8 @@ public static T as(InputStream stream, Class klass) { * @date 2018-12-02 */ public static T as(String json, Class klass) { - Objects.requireNonNull(json); - Objects.requireNonNull(klass); + Assert.notNull(json, "json must not be null"); + Assert.notNull(klass, "klass must not be null"); try { return singleClassReaderCache.computeIfAbsent(klass, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER .getTypeFactory().constructType(klass))).readValue(json); @@ -325,8 +325,8 @@ public static T as(String json, Class klass) { * @date 2018-12-02 */ public static T as(InputStream stream, Type type) { - Objects.requireNonNull(stream); - Objects.requireNonNull(type); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(type, "type must not be null"); try { return singleTypeReaderCache.computeIfAbsent(type, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER .getTypeFactory().constructType(type))).readValue(stream); @@ -343,8 +343,8 @@ public static T as(InputStream stream, Type type) { * @date 2018-12-02 */ public static T as(String json, Type type) { - Objects.requireNonNull(json); - Objects.requireNonNull(type); + Assert.notNull(json, "json must not be null"); + Assert.notNull(type, "type must not be null"); try { return singleTypeReaderCache.computeIfAbsent(type, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER .getTypeFactory().constructType(type))).readValue(json); @@ -361,8 +361,8 @@ public static T as(String json, Type type) { * @date 2019-03-13 */ public static T as(InputStream stream, Class parametrized, @Nullable Class... genericClasses) { - Objects.requireNonNull(stream); - Objects.requireNonNull(parametrized); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(parametrized, "parametrized must not be null"); try { if (EmptyUtil.yes(genericClasses)) { return singleClassReaderCache.computeIfAbsent(parametrized, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER @@ -389,8 +389,8 @@ public static T as(InputStream stream, Class parametrized, @Nullable Clas * @date 2019-03-13 */ public static T as(String json, Class parametrized, @Nullable Class... genericClasses) { - Objects.requireNonNull(json); - Objects.requireNonNull(parametrized); + Assert.notNull(json, "json must not be null"); + Assert.notNull(parametrized, "parametrized must not be null"); try { if (EmptyUtil.yes(genericClasses)) { return singleClassReaderCache.computeIfAbsent(parametrized, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER @@ -417,8 +417,8 @@ public static T as(String json, Class parametrized, @Nullable Class... * @date 2019-03-13 */ public static Object object(String json, Class parametrized, Class... genericClasses) { - Objects.requireNonNull(json); - Objects.requireNonNull(parametrized); + Assert.notNull(json, "json must not be null"); + Assert.notNull(parametrized, "parametrized must not be null"); try { if (EmptyUtil.yes(genericClasses)) { return singleClassReaderCache.computeIfAbsent(parametrized, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER @@ -445,8 +445,8 @@ public static Object object(String json, Class parametrized, Class... gene * @date 2019-03-13 */ public static Object object(InputStream stream, Class parametrized, Class... genericClasses) { - Objects.requireNonNull(stream); - Objects.requireNonNull(parametrized); + Assert.notNull(stream, "stream must not be null"); + Assert.notNull(parametrized, "parametrized must not be null"); try { if (EmptyUtil.yes(genericClasses)) { return singleClassReaderCache.computeIfAbsent(parametrized, (k) -> OBJECT_MAPPER.readerFor(OBJECT_MAPPER diff --git a/src/main/java/frodez/util/reflect/BeanUtil.java b/src/main/java/frodez/util/reflect/BeanUtil.java index 1c2f5ab..1f26f70 100644 --- a/src/main/java/frodez/util/reflect/BeanUtil.java +++ b/src/main/java/frodez/util/reflect/BeanUtil.java @@ -8,13 +8,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import lombok.experimental.UtilityClass; import org.springframework.cglib.beans.BeanCopier; import org.springframework.cglib.beans.BeanMap; import org.springframework.cglib.reflect.FastClass; import org.springframework.cglib.reflect.FastMethod; +import org.springframework.util.Assert; /** * Java Bean工具类 @@ -105,7 +105,7 @@ public static T cover(Object source, Class target) { */ @SuppressWarnings("unchecked") public static Map map(Object bean) { - Objects.requireNonNull(bean); + Assert.notNull(bean, "bean must not be null"); Map map = new HashMap<>(); map.putAll(BeanMap.create(bean)); return map; @@ -117,7 +117,7 @@ public static Map map(Object bean) { * @date 2019-02-08 */ public static T as(Map map, Class klass) { - Objects.requireNonNull(map); + Assert.notNull(map, "map must not be null"); try { T bean = ReflectUtil.newInstance(klass); BeanMap.create(bean).putAll(map); @@ -133,7 +133,7 @@ public static T as(Map map, Class klass) { * @date 2019-02-08 */ public static boolean isClear(Object bean) { - Objects.requireNonNull(bean); + Assert.notNull(bean, "bean must not be null"); try { for (Field field : bean.getClass().getDeclaredFields()) { if (PROPERTY_MODIFIER == field.getModifiers() && field.trySetAccessible() && field.get(bean) != null) { @@ -153,7 +153,7 @@ public static boolean isClear(Object bean) { * @date 2019-02-08 */ public static void clear(Object bean) { - Objects.requireNonNull(bean); + Assert.notNull(bean, "bean must not be null"); try { for (FastMethod method : getSetters(bean.getClass())) { method.invoke(bean, NULL_PARAM); diff --git a/src/main/java/frodez/util/reflect/ReflectUtil.java b/src/main/java/frodez/util/reflect/ReflectUtil.java index 1f8173b..73268e7 100644 --- a/src/main/java/frodez/util/reflect/ReflectUtil.java +++ b/src/main/java/frodez/util/reflect/ReflectUtil.java @@ -5,12 +5,12 @@ import java.lang.reflect.Method; import java.util.Map; import java.util.NoSuchElementException; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; import lombok.experimental.UtilityClass; import org.springframework.cglib.reflect.FastClass; import org.springframework.cglib.reflect.FastMethod; +import org.springframework.util.Assert; /** * 反射工具类 @@ -32,7 +32,7 @@ public T newInstance(Class klass) { } public static FastClass getFastClass(Class klass) { - Objects.requireNonNull(klass); + Assert.notNull(klass, "klass must not be null"); Pair pair = CGLIB_CACHE.get(klass); if (pair == null) { FastClass fastClass = FastClass.create(klass); @@ -47,8 +47,8 @@ public static FastClass getFastClass(Class klass) { } public static FastMethod getFastMethod(Class klass, String method, Class... params) { - Objects.requireNonNull(klass); - Objects.requireNonNull(method); + Assert.notNull(klass, "klass must not be null"); + Assert.notNull(method, "method must not be null"); Pair pair = CGLIB_CACHE.get(klass); if (pair == null) { FastClass fastClass = FastClass.create(klass); @@ -101,7 +101,7 @@ public static String getShortMethodName(Method method) { * @date 2018-12-17 */ public static Object primitiveAdapt(@Nullable Object value, Class parameterClass) { - Objects.requireNonNull(parameterClass); + Assert.notNull(parameterClass, "parameterClass must not be null"); if (value == null) { return null; } diff --git a/src/main/java/frodez/util/spring/ContextUtil.java b/src/main/java/frodez/util/spring/ContextUtil.java new file mode 100644 index 0000000..8dfd347 --- /dev/null +++ b/src/main/java/frodez/util/spring/ContextUtil.java @@ -0,0 +1,79 @@ +package frodez.util.spring; + +import java.util.Map; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; +import org.springframework.util.ClassUtils; + +/** + * spring工具类 + * @author Frodez + * @date 2018-12-21 + */ +@Component("contextUtil") +public class ContextUtil implements ApplicationContextAware { + + private static ApplicationContext context; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context = applicationContext; + if (context == null) { + throw new RuntimeException("获取spring上下文环境失败!"); + } + } + + /** + * 获取项目根路径 + * @author Frodez + * @date 2019-01-13 + */ + public static String rootPath() { + return ClassUtils.getDefaultClassLoader().getResource("").getPath(); + } + + /** + * 获取spring上下文环境 + * @author Frodez + * @date 2018-12-21 + */ + public static ApplicationContext context() { + return context; + } + + /** + * 使用spring上下文环境获取bean + * @param klass bean的类型 + * @author Frodez + * @date 2018-12-21 + */ + public static T get(Class klass) { + return context().getBean(klass); + } + + /** + * 使用spring上下文环境获取bean + * @param klass bean的类型 + * @author Frodez + * @param + * @date 2018-12-21 + */ + public static Map gets(Class klass) { + return context().getBeansOfType(klass); + } + + /** + * 使用spring上下文环境获取bean + * @param beanName bean的名字 + * @param klass bean的类型 + * @author Frodez + * @date 2018-12-21 + */ + @SuppressWarnings("unchecked") + public static T get(String beanName, Class klass) { + return (T) context().getBean(beanName); + } + +} diff --git a/src/main/java/frodez/util/spring/MVCUtil.java b/src/main/java/frodez/util/spring/MVCUtil.java new file mode 100644 index 0000000..0e7b9eb --- /dev/null +++ b/src/main/java/frodez/util/spring/MVCUtil.java @@ -0,0 +1,65 @@ +package frodez.util.spring; + +import java.util.Collection; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.experimental.UtilityClass; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * springMVC相关工具类 + * @author Frodez + * @date 2019-03-19 + */ +@UtilityClass +public class MVCUtil { + + /** + * 从spring上下文中获取HttpServletResponse + * @author Frodez + * @date 2019-01-09 + */ + public static HttpServletResponse response() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); + } + + /** + * 从spring上下文中获取HttpServletRequest + * @author Frodez + * @date 2019-01-09 + */ + public static HttpServletRequest request() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + } + + /** + * 使用spring上下文环境获取所有端点,按请求方式分类(同一端点可能有多种请求方式) + * @author Frodez + * @date 2019-03-16 + */ + public static Map> endPoints() { + Map> endPoints = new EnumMap<>(RequestMethod.class); + for (RequestMethod method : RequestMethod.values()) { + endPoints.put(method, BeanFactoryUtils.beansOfTypeIncludingAncestors(ContextUtil.context(), + HandlerMapping.class, true, false).values().stream().filter((iter) -> { + return iter instanceof RequestMappingHandlerMapping; + }).map((iter) -> { + return ((RequestMappingHandlerMapping) iter).getHandlerMethods().keySet(); + }).flatMap(Collection::stream).filter((iter) -> { + return iter.getMethodsCondition().getMethods().contains(method); + }).collect(Collectors.toList())); + } + return endPoints; + } + +} diff --git a/src/main/java/frodez/util/spring/properties/PropertyUtil.java b/src/main/java/frodez/util/spring/PropertyUtil.java similarity index 87% rename from src/main/java/frodez/util/spring/properties/PropertyUtil.java rename to src/main/java/frodez/util/spring/PropertyUtil.java index fa04d3f..8a94cd0 100644 --- a/src/main/java/frodez/util/spring/properties/PropertyUtil.java +++ b/src/main/java/frodez/util/spring/PropertyUtil.java @@ -1,14 +1,13 @@ -package frodez.util.spring.properties; +package frodez.util.spring; import frodez.util.constant.setting.PropertyKey; -import frodez.util.spring.context.ContextUtil; import java.util.Arrays; import java.util.List; -import java.util.Objects; import javax.annotation.PostConstruct; import org.springframework.context.annotation.DependsOn; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * 访问控制参数配置 @@ -27,7 +26,7 @@ public class PropertyUtil { @PostConstruct private void init() { env = ContextUtil.get(Environment.class); - Objects.requireNonNull(env); + Assert.notNull(env, "env must not be null"); } /** diff --git a/src/main/java/frodez/util/spring/context/ContextUtil.java b/src/main/java/frodez/util/spring/context/ContextUtil.java deleted file mode 100644 index 0b27b2a..0000000 --- a/src/main/java/frodez/util/spring/context/ContextUtil.java +++ /dev/null @@ -1,118 +0,0 @@ -package frodez.util.spring.context; - -import java.util.Collection; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Component; -import org.springframework.util.ClassUtils; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.mvc.method.RequestMappingInfo; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -/** - * spring工具类 - * @author Frodez - * @date 2018-12-21 - */ -@Component("contextUtil") -public class ContextUtil implements ApplicationContextAware { - - private static ApplicationContext context; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - context = applicationContext; - } - - /** - * 获取项目根路径 - * @author Frodez - * @date 2019-01-13 - */ - public static String rootPath() { - return ClassUtils.getDefaultClassLoader().getResource("").getPath(); - } - - /** - * 从spring上下文中获取HttpServletResponse - * @author Frodez - * @date 2019-01-09 - */ - public static HttpServletResponse response() { - return ServletRequestAttributes.class.cast(RequestContextHolder.getRequestAttributes()).getResponse(); - } - - /** - * 从spring上下文中获取HttpServletRequest - * @author Frodez - * @date 2019-01-09 - */ - public static HttpServletRequest request() { - return ServletRequestAttributes.class.cast(RequestContextHolder.getRequestAttributes()).getRequest(); - } - - /** - * 获取spring上下文环境 - * @author Frodez - * @date 2018-12-21 - */ - public static ApplicationContext context() { - if (context == null) { - throw new RuntimeException("获取spring上下文环境失败!"); - } - return context; - } - - /** - * 使用spring上下文环境获取bean - * @param klass bean的类型 - * @author Frodez - * @date 2018-12-21 - */ - public static T get(Class klass) { - return context().getBean(klass); - } - - /** - * 使用spring上下文环境获取bean - * @param beanName bean的名字 - * @param klass bean的类型 - * @author Frodez - * @date 2018-12-21 - */ - public static T get(String beanName, Class klass) { - return klass.cast(context().getBean(beanName)); - } - - /** - * 使用spring上下文环境获取所有端点,按请求方式分类(同一端点可能有多种请求方式) - * @author Frodez - * @date 2019-03-16 - */ - public static Map> getAllEndPoints() { - Map> endPoints = new EnumMap<>(RequestMethod.class); - for (RequestMethod method : RequestMethod.values()) { - endPoints.put(method, BeanFactoryUtils.beansOfTypeIncludingAncestors(context(), HandlerMapping.class, true, - false).values().stream().filter((iter) -> { - return iter instanceof RequestMappingHandlerMapping; - }).map((iter) -> { - return RequestMappingHandlerMapping.class.cast(iter).getHandlerMethods().keySet(); - }).flatMap(Collection::stream).filter((iter) -> { - return iter.getMethodsCondition().getMethods().contains(method); - }).collect(Collectors.toList())); - } - return endPoints; - } - -} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 08dce43..5c8876f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,18 +1,11 @@ -logging: - config: classpath:settings/log.xml - -mapper: - identity: MYSQL - mappers: frodez.config.mybatis.DataMapper - -pagehelper: - helperDialect: mysql - params: count=countSql - pageSizeZero: true - supportMethodsArguments: true - server: + error: + path: /error port: 9090 + servlet: + context-path: /api + http2: + enabled: true #不在此处理https,建议使用nginx #ssl: #在jdk目录下使用keytool.命令如下: @@ -23,23 +16,15 @@ server: #key-store: classpath:settings/https.jks #key-store-password: 123456 #key-password: 123456 - servlet: - context-path: /api - http2: - enabled: true spring: + task: + scheduling: + pool: + size: 4 + thread-name-prefix: spring-task-thread profiles: active: dev - resources: - add-mappings: true - aop: - auto: true - proxy-target-class: true - data: - redis: - repositories: - enabled: true datasource: type: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.cj.jdbc.Driver @@ -66,4 +51,17 @@ spring: max-active: -1 max-wait: 45000 max-idle: -1 - min-idle: 10 \ No newline at end of file + min-idle: 10 + +logging: + config: classpath:settings/log.xml + +mapper: + identity: MYSQL + mappers: frodez.config.mybatis.DataMapper + +pagehelper: + helperDialect: mysql + params: count=countSql + pageSizeZero: true + supportMethodsArguments: true \ No newline at end of file diff --git a/src/main/resources/others/blog.sql b/src/main/resources/others/blog.sql index 828d3c3..e9d4c42 100644 --- a/src/main/resources/others/blog.sql +++ b/src/main/resources/others/blog.sql @@ -11,12 +11,30 @@ Target Server Version : 80013 File Encoding : 65001 - Date: 06/01/2019 17:39:48 + Date: 21/03/2019 02:46:13 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; +-- ---------------------------- +-- Table structure for tb_article +-- ---------------------------- +DROP TABLE IF EXISTS `tb_article`; +CREATE TABLE `tb_article` ( + `id` bigint(20) NOT NULL COMMENT 'ID', + `create_time` datetime(0) NOT NULL COMMENT '创建时间', + `update_time` datetime(0) NOT NULL COMMENT '修改时间', + `user_id` bigint(20) NOT NULL COMMENT '作者ID', + `permit_level` tinyint(4) NOT NULL COMMENT '可见角色最低等级', + `is_delete` tinyint(4) NOT NULL DEFAULT 1 COMMENT '是否被删除 1:未删除 2:已删除', + `title` varchar(127) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '标题', + `description` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '简介', + `tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '标签', + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '内容', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '文章表' ROW_FORMAT = Dynamic; + -- ---------------------------- -- Table structure for tb_permission -- ---------------------------- @@ -29,7 +47,7 @@ CREATE TABLE `tb_permission` ( `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '地址', `description` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户权限表' ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户权限表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tb_role @@ -54,7 +72,21 @@ CREATE TABLE `tb_role_permission` ( `role_id` bigint(20) NOT NULL COMMENT '角色ID', `permission_id` bigint(20) NOT NULL COMMENT '权限ID', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色权限表' ROW_FORMAT = Dynamic; +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for tb_spring_task +-- ---------------------------- +DROP TABLE IF EXISTS `tb_spring_task`; +CREATE TABLE `tb_spring_task` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `create_time` datetime(0) NOT NULL COMMENT '创建时间', + `status` tinyint(4) NOT NULL COMMENT '运行状态 1:活跃中 2:已暂停', + `target` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '目标', + `description` tinytext CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务描述', + `cron_exp` varchar(31) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'cron表达式', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tb_user @@ -73,22 +105,4 @@ CREATE TABLE `tb_user` ( PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; --- ---------------------------- --- Table structure for tb_article --- ---------------------------- -DROP TABLE IF EXISTS `tb_article`; -CREATE TABLE `tb_article` ( - `id` bigint(20) NOT NULL COMMENT 'ID', - `create_time` datetime NOT NULL COMMENT '创建时间', - `update_time` datetime NOT NULL COMMENT '修改时间', - `user_id` bigint(20) NOT NULL COMMENT '作者ID', - `permit_level` tinyint(4) NOT NULL COMMENT '可见角色最低等级', - `is_delete` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否被删除 1:未删除 2:已删除', - `title` varchar(127) NOT NULL COMMENT '标题', - `description` tinytext COMMENT '简介', - `tag` varchar(255) DEFAULT NULL COMMENT '标签', - `content` text NOT NULL COMMENT '内容', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='文章表'; - SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/resources/settings/log.xml b/src/main/resources/settings/log.xml index b2182a4..f3861b4 100644 --- a/src/main/resources/settings/log.xml +++ b/src/main/resources/settings/log.xml @@ -3,7 +3,7 @@ - +