初始化
This commit is contained in:
22
module-core/src/main/java/io/renren/Application.java
Normal file
22
module-core/src/main/java/io/renren/Application.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.common.aspect;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.renren.common.annotation.SysLog;
|
||||
import io.renren.common.utils.HttpContextUtils;
|
||||
import io.renren.common.utils.IPUtils;
|
||||
import io.renren.modules.sys.entity.SysLogEntity;
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import io.renren.modules.sys.service.SysLogService;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志,切面处理类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class SysLogAspect {
|
||||
@Autowired
|
||||
private SysLogService sysLogService;
|
||||
|
||||
@Pointcut("@annotation(io.renren.common.annotation.SysLog)")
|
||||
public void logPointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("logPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
long beginTime = System.currentTimeMillis();
|
||||
//执行方法
|
||||
Object result = point.proceed();
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
|
||||
//保存日志
|
||||
saveSysLog(point, time);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
SysLogEntity sysLog = new SysLogEntity();
|
||||
SysLog syslog = method.getAnnotation(SysLog.class);
|
||||
if(syslog != null){
|
||||
//注解上的描述
|
||||
sysLog.setOperation(syslog.value());
|
||||
}
|
||||
|
||||
//请求的方法名
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = signature.getName();
|
||||
sysLog.setMethod(className + "." + methodName + "()");
|
||||
|
||||
//请求的参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
try{
|
||||
String params = new Gson().toJson(args);
|
||||
sysLog.setParams(params);
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
|
||||
//获取request
|
||||
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
|
||||
//设置IP地址
|
||||
sysLog.setIp(IPUtils.getIpAddr(request));
|
||||
|
||||
//用户名
|
||||
String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
|
||||
sysLog.setUsername(username);
|
||||
|
||||
sysLog.setTime(time);
|
||||
sysLog.setCreateDate(new Date());
|
||||
//保存系统日志
|
||||
sysLogService.save(sysLog);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.common.aspect.utils;
|
||||
|
||||
import io.renren.common.exception.RRException;
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
/**
|
||||
* Shiro工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class ShiroUtils {
|
||||
|
||||
public static Session getSession() {
|
||||
return SecurityUtils.getSubject().getSession();
|
||||
}
|
||||
|
||||
public static Subject getSubject() {
|
||||
return SecurityUtils.getSubject();
|
||||
}
|
||||
|
||||
public static SysUserEntity getUserEntity() {
|
||||
return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
|
||||
}
|
||||
|
||||
public static Long getUserId() {
|
||||
return getUserEntity().getUserId();
|
||||
}
|
||||
|
||||
public static void setSessionAttribute(Object key, Object value) {
|
||||
getSession().setAttribute(key, value);
|
||||
}
|
||||
|
||||
public static Object getSessionAttribute(Object key) {
|
||||
return getSession().getAttribute(key);
|
||||
}
|
||||
|
||||
public static boolean isLogin() {
|
||||
return SecurityUtils.getSubject().getPrincipal() != null;
|
||||
}
|
||||
|
||||
public static String getKaptcha(String key) {
|
||||
Object kaptcha = getSessionAttribute(key);
|
||||
if(kaptcha == null){
|
||||
throw new RRException("验证码已失效");
|
||||
}
|
||||
getSession().removeAttribute(key);
|
||||
return kaptcha.toString();
|
||||
}
|
||||
|
||||
}
|
||||
26
module-core/src/main/java/io/renren/config/CorsConfig.java
Normal file
26
module-core/src/main/java/io/renren/config/CorsConfig.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowCredentials(true)
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.maxAge(3600);
|
||||
}
|
||||
}
|
||||
49
module-core/src/main/java/io/renren/config/FilterConfig.java
Normal file
49
module-core/src/main/java/io/renren/config/FilterConfig.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.config;
|
||||
|
||||
import io.renren.common.xss.XssFilter;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class FilterConfig {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean shiroFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
|
||||
//该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
|
||||
registration.addInitParameter("targetFilterLifecycle", "true");
|
||||
registration.setEnabled(true);
|
||||
registration.setOrder(Integer.MAX_VALUE - 1);
|
||||
registration.addUrlPatterns("/*");
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setFilter(new XssFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("xssFilter");
|
||||
registration.setOrder(Integer.MAX_VALUE);
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.config;
|
||||
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* 生成验证码配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class KaptchaConfig {
|
||||
|
||||
@Bean
|
||||
public DefaultKaptcha producer() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("kaptcha.border", "no");
|
||||
properties.put("kaptcha.textproducer.font.color", "black");
|
||||
properties.put("kaptcha.textproducer.char.space", "5");
|
||||
properties.put("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
|
||||
Config config = new Config(properties);
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.config;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* mybatis-plus配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
return new PaginationInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
63
module-core/src/main/java/io/renren/config/RedisConfig.java
Normal file
63
module-core/src/main/java/io/renren/config/RedisConfig.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
@Autowired
|
||||
private RedisConnectionFactory factory;
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new StringRedisSerializer());
|
||||
redisTemplate.setConnectionFactory(factory);
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForHash();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
|
||||
return redisTemplate.opsForValue();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForList();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForSet();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
|
||||
return redisTemplate.opsForZSet();
|
||||
}
|
||||
}
|
||||
84
module-core/src/main/java/io/renren/config/ShiroConfig.java
Normal file
84
module-core/src/main/java/io/renren/config/ShiroConfig.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.config;
|
||||
|
||||
import io.renren.modules.sys.oauth2.OAuth2Filter;
|
||||
import io.renren.modules.sys.oauth2.OAuth2Realm;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Shiro配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class ShiroConfig {
|
||||
|
||||
@Bean("securityManager")
|
||||
public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
securityManager.setRealm(oAuth2Realm);
|
||||
securityManager.setRememberMeManager(null);
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
@Bean("shiroFilter")
|
||||
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
|
||||
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
|
||||
shiroFilter.setSecurityManager(securityManager);
|
||||
|
||||
//oauth过滤
|
||||
Map<String, Filter> filters = new HashMap<>();
|
||||
filters.put("oauth2", new OAuth2Filter());
|
||||
shiroFilter.setFilters(filters);
|
||||
|
||||
Map<String, String> filterMap = new LinkedHashMap<>();
|
||||
filterMap.put("/webjars/**", "anon");
|
||||
filterMap.put("/druid/**", "anon");
|
||||
filterMap.put("/app/**", "anon");
|
||||
filterMap.put("/sys/login", "anon");
|
||||
filterMap.put("/swagger/**", "anon");
|
||||
filterMap.put("/v2/api-docs", "anon");
|
||||
filterMap.put("/swagger-ui.html", "anon");
|
||||
filterMap.put("/swagger-resources/**", "anon");
|
||||
filterMap.put("/captcha.jpg", "anon");
|
||||
filterMap.put("/aaa.txt", "anon");
|
||||
filterMap.put("/wcs/**", "anon");
|
||||
|
||||
|
||||
filterMap.put("/**", "oauth2");
|
||||
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
||||
|
||||
return shiroFilter;
|
||||
}
|
||||
|
||||
@Bean("lifecycleBeanPostProcessor")
|
||||
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
|
||||
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
|
||||
advisor.setSecurityManager(securityManager);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 多数据源注解
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface DataSource {
|
||||
String value() default "";
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.aspect;
|
||||
|
||||
|
||||
import io.renren.datasource.annotation.DataSource;
|
||||
import io.renren.datasource.config.DynamicContextHolder;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 多数据源,切面处理类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class DataSourceAspect {
|
||||
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Pointcut("@annotation(io.renren.datasource.annotation.DataSource) " +
|
||||
"|| @within(io.renren.datasource.annotation.DataSource)")
|
||||
public void dataSourcePointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("dataSourcePointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Class targetClass = point.getTarget().getClass();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
DataSource targetDataSource = (DataSource)targetClass.getAnnotation(DataSource.class);
|
||||
DataSource methodDataSource = method.getAnnotation(DataSource.class);
|
||||
if(targetDataSource != null || methodDataSource != null){
|
||||
String value;
|
||||
if(methodDataSource != null){
|
||||
value = methodDataSource.value();
|
||||
}else {
|
||||
value = targetDataSource.value();
|
||||
}
|
||||
|
||||
DynamicContextHolder.push(value);
|
||||
logger.debug("set datasource is {}", value);
|
||||
}
|
||||
|
||||
try {
|
||||
return point.proceed();
|
||||
} finally {
|
||||
DynamicContextHolder.poll();
|
||||
logger.debug("clean datasource");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.config;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* 多数据源上下文
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class DynamicContextHolder {
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ThreadLocal<Deque<String>> CONTEXT_HOLDER = new ThreadLocal() {
|
||||
@Override
|
||||
protected Object initialValue() {
|
||||
return new ArrayDeque();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获得当前线程数据源
|
||||
*
|
||||
* @return 数据源名称
|
||||
*/
|
||||
public static String peek() {
|
||||
return CONTEXT_HOLDER.get().peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前线程数据源
|
||||
*
|
||||
* @param dataSource 数据源名称
|
||||
*/
|
||||
public static void push(String dataSource) {
|
||||
CONTEXT_HOLDER.get().push(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空当前线程数据源
|
||||
*/
|
||||
public static void poll() {
|
||||
Deque<String> deque = CONTEXT_HOLDER.get();
|
||||
deque.poll();
|
||||
if (deque.isEmpty()) {
|
||||
CONTEXT_HOLDER.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.config;
|
||||
|
||||
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||
|
||||
/**
|
||||
* 多数据源
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey() {
|
||||
return DynamicContextHolder.peek();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.config;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import io.renren.datasource.properties.DataSourceProperties;
|
||||
import io.renren.datasource.properties.DynamicDataSourceProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 配置多数据源
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
|
||||
public class DynamicDataSourceConfig {
|
||||
@Autowired
|
||||
private DynamicDataSourceProperties properties;
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.druid")
|
||||
public DataSourceProperties dataSourceProperties() {
|
||||
return new DataSourceProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DynamicDataSource dynamicDataSource(DataSourceProperties dataSourceProperties) {
|
||||
DynamicDataSource dynamicDataSource = new DynamicDataSource();
|
||||
dynamicDataSource.setTargetDataSources(getDynamicDataSource());
|
||||
|
||||
//默认数据源
|
||||
DruidDataSource defaultDataSource = DynamicDataSourceFactory.buildDruidDataSource(dataSourceProperties);
|
||||
dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
|
||||
|
||||
return dynamicDataSource;
|
||||
}
|
||||
|
||||
private Map<Object, Object> getDynamicDataSource(){
|
||||
Map<String, DataSourceProperties> dataSourcePropertiesMap = properties.getDatasource();
|
||||
Map<Object, Object> targetDataSources = new HashMap<>(dataSourcePropertiesMap.size());
|
||||
dataSourcePropertiesMap.forEach((k, v) -> {
|
||||
DruidDataSource druidDataSource = DynamicDataSourceFactory.buildDruidDataSource(v);
|
||||
targetDataSources.put(k, druidDataSource);
|
||||
});
|
||||
|
||||
return targetDataSources;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.config;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import io.renren.datasource.properties.DataSourceProperties;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* DruidDataSource
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DynamicDataSourceFactory {
|
||||
|
||||
public static DruidDataSource buildDruidDataSource(DataSourceProperties properties) {
|
||||
DruidDataSource druidDataSource = new DruidDataSource();
|
||||
druidDataSource.setDriverClassName(properties.getDriverClassName());
|
||||
druidDataSource.setUrl(properties.getUrl());
|
||||
druidDataSource.setUsername(properties.getUsername());
|
||||
druidDataSource.setPassword(properties.getPassword());
|
||||
|
||||
druidDataSource.setInitialSize(properties.getInitialSize());
|
||||
druidDataSource.setMaxActive(properties.getMaxActive());
|
||||
druidDataSource.setMinIdle(properties.getMinIdle());
|
||||
druidDataSource.setMaxWait(properties.getMaxWait());
|
||||
druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
|
||||
druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
|
||||
druidDataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis());
|
||||
druidDataSource.setValidationQuery(properties.getValidationQuery());
|
||||
druidDataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout());
|
||||
druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
|
||||
druidDataSource.setTestOnReturn(properties.isTestOnReturn());
|
||||
druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
|
||||
druidDataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements());
|
||||
druidDataSource.setSharePreparedStatements(properties.isSharePreparedStatements());
|
||||
|
||||
try {
|
||||
druidDataSource.setFilters(properties.getFilters());
|
||||
druidDataSource.init();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return druidDataSource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.properties;
|
||||
|
||||
/**
|
||||
* 多数据源属性
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DataSourceProperties {
|
||||
private String driverClassName;
|
||||
private String url;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Druid默认参数
|
||||
*/
|
||||
private int initialSize = 2;
|
||||
private int maxActive = 10;
|
||||
private int minIdle = -1;
|
||||
private long maxWait = 60 * 1000L;
|
||||
private long timeBetweenEvictionRunsMillis = 60 * 1000L;
|
||||
private long minEvictableIdleTimeMillis = 1000L * 60L * 30L;
|
||||
private long maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7;
|
||||
private String validationQuery = "select 1";
|
||||
private int validationQueryTimeout = -1;
|
||||
private boolean testOnBorrow = false;
|
||||
private boolean testOnReturn = false;
|
||||
private boolean testWhileIdle = true;
|
||||
private boolean poolPreparedStatements = false;
|
||||
private int maxOpenPreparedStatements = -1;
|
||||
private boolean sharePreparedStatements = false;
|
||||
private String filters = "stat,wall";
|
||||
|
||||
public String getDriverClassName() {
|
||||
return driverClassName;
|
||||
}
|
||||
|
||||
public void setDriverClassName(String driverClassName) {
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getInitialSize() {
|
||||
return initialSize;
|
||||
}
|
||||
|
||||
public void setInitialSize(int initialSize) {
|
||||
this.initialSize = initialSize;
|
||||
}
|
||||
|
||||
public int getMaxActive() {
|
||||
return maxActive;
|
||||
}
|
||||
|
||||
public void setMaxActive(int maxActive) {
|
||||
this.maxActive = maxActive;
|
||||
}
|
||||
|
||||
public int getMinIdle() {
|
||||
return minIdle;
|
||||
}
|
||||
|
||||
public void setMinIdle(int minIdle) {
|
||||
this.minIdle = minIdle;
|
||||
}
|
||||
|
||||
public long getMaxWait() {
|
||||
return maxWait;
|
||||
}
|
||||
|
||||
public void setMaxWait(long maxWait) {
|
||||
this.maxWait = maxWait;
|
||||
}
|
||||
|
||||
public long getTimeBetweenEvictionRunsMillis() {
|
||||
return timeBetweenEvictionRunsMillis;
|
||||
}
|
||||
|
||||
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
|
||||
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
|
||||
}
|
||||
|
||||
public long getMinEvictableIdleTimeMillis() {
|
||||
return minEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
|
||||
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public long getMaxEvictableIdleTimeMillis() {
|
||||
return maxEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
|
||||
this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
|
||||
}
|
||||
|
||||
public String getValidationQuery() {
|
||||
return validationQuery;
|
||||
}
|
||||
|
||||
public void setValidationQuery(String validationQuery) {
|
||||
this.validationQuery = validationQuery;
|
||||
}
|
||||
|
||||
public int getValidationQueryTimeout() {
|
||||
return validationQueryTimeout;
|
||||
}
|
||||
|
||||
public void setValidationQueryTimeout(int validationQueryTimeout) {
|
||||
this.validationQueryTimeout = validationQueryTimeout;
|
||||
}
|
||||
|
||||
public boolean isTestOnBorrow() {
|
||||
return testOnBorrow;
|
||||
}
|
||||
|
||||
public void setTestOnBorrow(boolean testOnBorrow) {
|
||||
this.testOnBorrow = testOnBorrow;
|
||||
}
|
||||
|
||||
public boolean isTestOnReturn() {
|
||||
return testOnReturn;
|
||||
}
|
||||
|
||||
public void setTestOnReturn(boolean testOnReturn) {
|
||||
this.testOnReturn = testOnReturn;
|
||||
}
|
||||
|
||||
public boolean isTestWhileIdle() {
|
||||
return testWhileIdle;
|
||||
}
|
||||
|
||||
public void setTestWhileIdle(boolean testWhileIdle) {
|
||||
this.testWhileIdle = testWhileIdle;
|
||||
}
|
||||
|
||||
public boolean isPoolPreparedStatements() {
|
||||
return poolPreparedStatements;
|
||||
}
|
||||
|
||||
public void setPoolPreparedStatements(boolean poolPreparedStatements) {
|
||||
this.poolPreparedStatements = poolPreparedStatements;
|
||||
}
|
||||
|
||||
public int getMaxOpenPreparedStatements() {
|
||||
return maxOpenPreparedStatements;
|
||||
}
|
||||
|
||||
public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) {
|
||||
this.maxOpenPreparedStatements = maxOpenPreparedStatements;
|
||||
}
|
||||
|
||||
public boolean isSharePreparedStatements() {
|
||||
return sharePreparedStatements;
|
||||
}
|
||||
|
||||
public void setSharePreparedStatements(boolean sharePreparedStatements) {
|
||||
this.sharePreparedStatements = sharePreparedStatements;
|
||||
}
|
||||
|
||||
public String getFilters() {
|
||||
return filters;
|
||||
}
|
||||
|
||||
public void setFilters(String filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.datasource.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 多数据源属性
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "dynamic")
|
||||
public class DynamicDataSourceProperties {
|
||||
private Map<String, DataSourceProperties> datasource = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, DataSourceProperties> getDatasource() {
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public void setDatasource(Map<String, DataSourceProperties> datasource) {
|
||||
this.datasource = datasource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* app登录效验
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Login {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 登录用户信息
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LoginUser {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.config;
|
||||
|
||||
import io.renren.modules.app.interceptor.AuthorizationInterceptor;
|
||||
import io.renren.modules.app.resolver.LoginUserHandlerMethodArgumentResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MVC配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
@Autowired
|
||||
private AuthorizationInterceptor authorizationInterceptor;
|
||||
@Autowired
|
||||
private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(authorizationInterceptor).addPathPatterns("/app/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.controller;
|
||||
|
||||
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.modules.app.form.LoginForm;
|
||||
import io.renren.modules.app.service.UserService;
|
||||
import io.renren.modules.app.utils.JwtUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* APP登录授权
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@Api("APP登录接口")
|
||||
public class AppLoginController {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
@PostMapping("login")
|
||||
@ApiOperation("登录")
|
||||
public R login(@RequestBody LoginForm form){
|
||||
//表单校验
|
||||
ValidatorUtils.validateEntity(form);
|
||||
|
||||
//用户登录
|
||||
long userId = userService.login(form);
|
||||
|
||||
//生成token
|
||||
String token = jwtUtils.generateToken(userId);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("token", token);
|
||||
map.put("expire", jwtUtils.getExpire());
|
||||
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.controller;
|
||||
|
||||
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.modules.app.entity.UserEntity;
|
||||
import io.renren.modules.app.form.RegisterForm;
|
||||
import io.renren.modules.app.service.UserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.RestController;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@Api("APP注册接口")
|
||||
public class AppRegisterController {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping("register")
|
||||
@ApiOperation("注册")
|
||||
public R register(@RequestBody RegisterForm form){
|
||||
//表单校验
|
||||
ValidatorUtils.validateEntity(form);
|
||||
|
||||
UserEntity user = new UserEntity();
|
||||
user.setMobile(form.getMobile());
|
||||
user.setUsername(form.getMobile());
|
||||
user.setPassword(DigestUtils.sha256Hex(form.getPassword()));
|
||||
user.setCreateTime(new Date());
|
||||
userService.save(user);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.controller;
|
||||
|
||||
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.modules.app.annotation.Login;
|
||||
import io.renren.modules.app.annotation.LoginUser;
|
||||
import io.renren.modules.app.entity.UserEntity;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* APP测试接口
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@Api("APP测试接口")
|
||||
public class AppTestController {
|
||||
|
||||
@Login
|
||||
@GetMapping("userInfo")
|
||||
@ApiOperation("获取用户信息")
|
||||
public R userInfo(@LoginUser UserEntity user){
|
||||
return R.ok().put("user", user);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("userId")
|
||||
@ApiOperation("获取用户ID")
|
||||
public R userInfo(@RequestAttribute("userId") Integer userId){
|
||||
return R.ok().put("userId", userId);
|
||||
}
|
||||
|
||||
@GetMapping("notToken")
|
||||
@ApiOperation("忽略Token验证测试")
|
||||
public R notToken(){
|
||||
return R.ok().put("msg", "无需token也能访问。。。");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.app.entity.UserEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserDao extends BaseMapper<UserEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("tb_user")
|
||||
public class UserEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@TableId
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 登录表单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "登录表单")
|
||||
public class LoginForm {
|
||||
@ApiModelProperty(value = "手机号")
|
||||
@NotBlank(message="手机号不能为空")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "密码")
|
||||
@NotBlank(message="密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.form;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 注册表单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "注册表单")
|
||||
public class RegisterForm {
|
||||
@ApiModelProperty(value = "手机号")
|
||||
@NotBlank(message="手机号不能为空")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "密码")
|
||||
@NotBlank(message="密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.interceptor;
|
||||
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.renren.common.exception.RRException;
|
||||
import io.renren.modules.app.utils.JwtUtils;
|
||||
import io.renren.modules.app.annotation.Login;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 权限(Token)验证
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
|
||||
@Autowired
|
||||
private JwtUtils jwtUtils;
|
||||
|
||||
public static final String USER_KEY = "userId";
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
Login annotation;
|
||||
if(handler instanceof HandlerMethod) {
|
||||
annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(annotation == null){
|
||||
return true;
|
||||
}
|
||||
|
||||
//获取用户凭证
|
||||
String token = request.getHeader(jwtUtils.getHeader());
|
||||
if(StringUtils.isBlank(token)){
|
||||
token = request.getParameter(jwtUtils.getHeader());
|
||||
}
|
||||
|
||||
//凭证为空
|
||||
if(StringUtils.isBlank(token)){
|
||||
throw new RRException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value());
|
||||
}
|
||||
|
||||
Claims claims = jwtUtils.getClaimByToken(token);
|
||||
if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
|
||||
throw new RRException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
|
||||
}
|
||||
|
||||
//设置userId到request里,后续根据userId,获取用户信息
|
||||
request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject()));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.resolver;
|
||||
|
||||
import io.renren.modules.app.annotation.LoginUser;
|
||||
import io.renren.modules.app.entity.UserEntity;
|
||||
import io.renren.modules.app.interceptor.AuthorizationInterceptor;
|
||||
import io.renren.modules.app.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* 有@LoginUser注解的方法参数,注入当前登录用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
|
||||
NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
|
||||
//获取用户ID
|
||||
Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
|
||||
if(object == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
//获取用户信息
|
||||
UserEntity user = userService.getById((Long)object);
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.modules.app.entity.UserEntity;
|
||||
import io.renren.modules.app.form.LoginForm;
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface UserService extends IService<UserEntity> {
|
||||
|
||||
UserEntity queryByMobile(String mobile);
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param form 登录表单
|
||||
* @return 返回用户ID
|
||||
*/
|
||||
long login(LoginForm form);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import io.renren.common.exception.RRException;
|
||||
import io.renren.common.validator.Assert;
|
||||
import io.renren.modules.app.dao.UserDao;
|
||||
import io.renren.modules.app.entity.UserEntity;
|
||||
import io.renren.modules.app.form.LoginForm;
|
||||
import io.renren.modules.app.service.UserService;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
@Service("userService")
|
||||
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
|
||||
|
||||
@Override
|
||||
public UserEntity queryByMobile(String mobile) {
|
||||
return baseMapper.selectOne(new QueryWrapper<UserEntity>().eq("mobile", mobile));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long login(LoginForm form) {
|
||||
UserEntity user = queryByMobile(form.getMobile());
|
||||
Assert.isNull(user, "手机号或密码错误");
|
||||
|
||||
//密码错误
|
||||
if(!user.getPassword().equals(DigestUtils.sha256Hex(form.getPassword()))){
|
||||
throw new RRException("手机号或密码错误");
|
||||
}
|
||||
|
||||
return user.getUserId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.app.utils;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* jwt工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "renren.jwt")
|
||||
@Component
|
||||
public class JwtUtils {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private String secret;
|
||||
private long expire;
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* 生成jwt token
|
||||
*/
|
||||
public String generateToken(long userId) {
|
||||
Date nowDate = new Date();
|
||||
//过期时间
|
||||
Date expireDate = new Date(nowDate.getTime() + expire * 1000);
|
||||
|
||||
return Jwts.builder()
|
||||
.setHeaderParam("typ", "JWT")
|
||||
.setSubject(userId+"")
|
||||
.setIssuedAt(nowDate)
|
||||
.setExpiration(expireDate)
|
||||
.signWith(SignatureAlgorithm.HS512, secret)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Claims getClaimByToken(String token) {
|
||||
try {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(secret)
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}catch (Exception e){
|
||||
logger.debug("validate is token error ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* token是否过期
|
||||
* @return true:过期
|
||||
*/
|
||||
public boolean isTokenExpired(Date expiration) {
|
||||
return expiration.before(new Date());
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public long getExpire() {
|
||||
return expire;
|
||||
}
|
||||
|
||||
public void setExpire(long expire) {
|
||||
this.expire = expire;
|
||||
}
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 定时任务配置
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Configuration
|
||||
public class ScheduleConfig {
|
||||
|
||||
@Bean
|
||||
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
|
||||
SchedulerFactoryBean factory = new SchedulerFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
|
||||
//quartz参数
|
||||
Properties prop = new Properties();
|
||||
prop.put("org.quartz.scheduler.instanceName", "RenrenScheduler");
|
||||
prop.put("org.quartz.scheduler.instanceId", "AUTO");
|
||||
//线程池配置
|
||||
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
|
||||
prop.put("org.quartz.threadPool.threadCount", "20");
|
||||
prop.put("org.quartz.threadPool.threadPriority", "5");
|
||||
//JobStore配置
|
||||
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
|
||||
//集群配置
|
||||
prop.put("org.quartz.jobStore.isClustered", "true");
|
||||
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
|
||||
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
|
||||
|
||||
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
|
||||
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
|
||||
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
|
||||
|
||||
//PostgreSQL数据库,需要打开此注释
|
||||
//prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
|
||||
|
||||
factory.setQuartzProperties(prop);
|
||||
|
||||
factory.setSchedulerName("RenrenScheduler");
|
||||
//延时启动
|
||||
factory.setStartupDelay(30);
|
||||
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
|
||||
//可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
|
||||
factory.setOverwriteExistingJobs(true);
|
||||
//设置自动启动,默认为true
|
||||
factory.setAutoStartup(true);
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.controller;
|
||||
|
||||
import io.renren.common.annotation.SysLog;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.modules.job.entity.ScheduleJobEntity;
|
||||
import io.renren.modules.job.service.ScheduleJobService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sys/schedule")
|
||||
public class ScheduleJobController {
|
||||
@Autowired
|
||||
private ScheduleJobService scheduleJobService;
|
||||
|
||||
/**
|
||||
* 定时任务列表
|
||||
*/
|
||||
@RequestMapping("/list")
|
||||
@RequiresPermissions("sys:schedule:list")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
PageUtils page = scheduleJobService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时任务信息
|
||||
*/
|
||||
@RequestMapping("/info/{jobId}")
|
||||
@RequiresPermissions("sys:schedule:info")
|
||||
public R info(@PathVariable("jobId") Long jobId){
|
||||
ScheduleJobEntity schedule = scheduleJobService.getById(jobId);
|
||||
|
||||
return R.ok().put("schedule", schedule);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存定时任务
|
||||
*/
|
||||
@SysLog("保存定时任务")
|
||||
@RequestMapping("/save")
|
||||
@RequiresPermissions("sys:schedule:save")
|
||||
public R save(@RequestBody ScheduleJobEntity scheduleJob){
|
||||
ValidatorUtils.validateEntity(scheduleJob);
|
||||
|
||||
scheduleJobService.saveJob(scheduleJob);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改定时任务
|
||||
*/
|
||||
@SysLog("修改定时任务")
|
||||
@RequestMapping("/update")
|
||||
@RequiresPermissions("sys:schedule:update")
|
||||
public R update(@RequestBody ScheduleJobEntity scheduleJob){
|
||||
ValidatorUtils.validateEntity(scheduleJob);
|
||||
|
||||
scheduleJobService.update(scheduleJob);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除定时任务
|
||||
*/
|
||||
@SysLog("删除定时任务")
|
||||
@RequestMapping("/delete")
|
||||
@RequiresPermissions("sys:schedule:delete")
|
||||
public R delete(@RequestBody Long[] jobIds){
|
||||
scheduleJobService.deleteBatch(jobIds);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即执行任务
|
||||
*/
|
||||
@SysLog("立即执行任务")
|
||||
@RequestMapping("/run")
|
||||
@RequiresPermissions("sys:schedule:run")
|
||||
public R run(@RequestBody Long[] jobIds){
|
||||
scheduleJobService.run(jobIds);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停定时任务
|
||||
*/
|
||||
@SysLog("暂停定时任务")
|
||||
@RequestMapping("/pause")
|
||||
@RequiresPermissions("sys:schedule:pause")
|
||||
public R pause(@RequestBody Long[] jobIds){
|
||||
scheduleJobService.pause(jobIds);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复定时任务
|
||||
*/
|
||||
@SysLog("恢复定时任务")
|
||||
@RequestMapping("/resume")
|
||||
@RequiresPermissions("sys:schedule:resume")
|
||||
public R resume(@RequestBody Long[] jobIds){
|
||||
scheduleJobService.resume(jobIds);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.controller;
|
||||
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.modules.job.entity.ScheduleJobLogEntity;
|
||||
import io.renren.modules.job.service.ScheduleJobLogService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sys/scheduleLog")
|
||||
public class ScheduleJobLogController {
|
||||
@Autowired
|
||||
private ScheduleJobLogService scheduleJobLogService;
|
||||
|
||||
/**
|
||||
* 定时任务日志列表
|
||||
*/
|
||||
@RequestMapping("/list")
|
||||
@RequiresPermissions("sys:schedule:log")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
PageUtils page = scheduleJobLogService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时任务日志信息
|
||||
*/
|
||||
@RequestMapping("/info/{logId}")
|
||||
public R info(@PathVariable("logId") Long logId){
|
||||
ScheduleJobLogEntity log = scheduleJobLogService.getById(logId);
|
||||
|
||||
return R.ok().put("log", log);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.job.entity.ScheduleJobEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface ScheduleJobDao extends BaseMapper<ScheduleJobEntity> {
|
||||
|
||||
/**
|
||||
* 批量更新状态
|
||||
*/
|
||||
int updateBatch(Map<String, Object> map);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.job.entity.ScheduleJobLogEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface ScheduleJobLogDao extends BaseMapper<ScheduleJobLogEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("schedule_job")
|
||||
public class ScheduleJobEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务调度参数key
|
||||
*/
|
||||
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
@TableId
|
||||
private Long jobId;
|
||||
|
||||
/**
|
||||
* spring bean名称
|
||||
*/
|
||||
@NotBlank(message="bean名称不能为空")
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
private String params;
|
||||
|
||||
/**
|
||||
* cron表达式
|
||||
*/
|
||||
@NotBlank(message="cron表达式不能为空")
|
||||
private String cronExpression;
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("schedule_job_log")
|
||||
public class ScheduleJobLogEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 日志id
|
||||
*/
|
||||
@TableId
|
||||
private Long logId;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private Long jobId;
|
||||
|
||||
/**
|
||||
* spring bean名称
|
||||
*/
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
private String params;
|
||||
|
||||
/**
|
||||
* 任务状态 0:成功 1:失败
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 失败信息
|
||||
*/
|
||||
private String error;
|
||||
|
||||
/**
|
||||
* 耗时(单位:毫秒)
|
||||
*/
|
||||
private Integer times;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.job.entity.ScheduleJobLogEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 定时任务日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface ScheduleJobLogService extends IService<ScheduleJobLogEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.job.entity.ScheduleJobEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface ScheduleJobService extends IService<ScheduleJobEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 保存定时任务
|
||||
*/
|
||||
void saveJob(ScheduleJobEntity scheduleJob);
|
||||
|
||||
/**
|
||||
* 更新定时任务
|
||||
*/
|
||||
void update(ScheduleJobEntity scheduleJob);
|
||||
|
||||
/**
|
||||
* 批量删除定时任务
|
||||
*/
|
||||
void deleteBatch(Long[] jobIds);
|
||||
|
||||
/**
|
||||
* 批量更新定时任务状态
|
||||
*/
|
||||
int updateBatch(Long[] jobIds, int status);
|
||||
|
||||
/**
|
||||
* 立即执行
|
||||
*/
|
||||
void run(Long[] jobIds);
|
||||
|
||||
/**
|
||||
* 暂停运行
|
||||
*/
|
||||
void pause(Long[] jobIds);
|
||||
|
||||
/**
|
||||
* 恢复运行
|
||||
*/
|
||||
void resume(Long[] jobIds);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.Query;
|
||||
import io.renren.modules.job.dao.ScheduleJobLogDao;
|
||||
import io.renren.modules.job.entity.ScheduleJobLogEntity;
|
||||
import io.renren.modules.job.service.ScheduleJobLogService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Service("scheduleJobLogService")
|
||||
public class ScheduleJobLogServiceImpl extends ServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
|
||||
|
||||
@Override
|
||||
public PageUtils queryPage(Map<String, Object> params) {
|
||||
String jobId = (String)params.get("jobId");
|
||||
|
||||
IPage<ScheduleJobLogEntity> page = this.page(
|
||||
new Query<ScheduleJobLogEntity>().getPage(params),
|
||||
new QueryWrapper<ScheduleJobLogEntity>().like(StringUtils.isNotBlank(jobId),"job_id", jobId)
|
||||
);
|
||||
|
||||
return new PageUtils(page);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.Query;
|
||||
import io.renren.modules.job.dao.ScheduleJobDao;
|
||||
import io.renren.modules.job.entity.ScheduleJobEntity;
|
||||
import io.renren.modules.job.service.ScheduleJobService;
|
||||
import io.renren.modules.job.utils.ScheduleUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.Scheduler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.*;
|
||||
|
||||
@Service("scheduleJobService")
|
||||
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
|
||||
@Autowired
|
||||
private Scheduler scheduler;
|
||||
|
||||
/**
|
||||
* 项目启动时,初始化定时器
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init(){
|
||||
List<ScheduleJobEntity> scheduleJobList = this.list();
|
||||
for(ScheduleJobEntity scheduleJob : scheduleJobList){
|
||||
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
|
||||
//如果不存在,则创建
|
||||
if(cronTrigger == null) {
|
||||
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
|
||||
}else {
|
||||
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageUtils queryPage(Map<String, Object> params) {
|
||||
String beanName = (String)params.get("beanName");
|
||||
|
||||
IPage<ScheduleJobEntity> page = this.page(
|
||||
new Query<ScheduleJobEntity>().getPage(params),
|
||||
new QueryWrapper <ScheduleJobEntity>().like(StringUtils.isNotBlank(beanName),"bean_name", beanName)
|
||||
);
|
||||
|
||||
return new PageUtils(page);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveJob(ScheduleJobEntity scheduleJob) {
|
||||
scheduleJob.setCreateTime(new Date());
|
||||
scheduleJob.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
|
||||
this.save(scheduleJob);
|
||||
|
||||
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(ScheduleJobEntity scheduleJob) {
|
||||
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
|
||||
|
||||
this.updateById(scheduleJob);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteBatch(Long[] jobIds) {
|
||||
for(Long jobId : jobIds){
|
||||
ScheduleUtils.deleteScheduleJob(scheduler, jobId);
|
||||
}
|
||||
|
||||
//删除数据
|
||||
this.removeByIds(Arrays.asList(jobIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateBatch(Long[] jobIds, int status){
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("list", jobIds);
|
||||
map.put("status", status);
|
||||
return baseMapper.updateBatch(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void run(Long[] jobIds) {
|
||||
for(Long jobId : jobIds){
|
||||
ScheduleUtils.run(scheduler, this.getById(jobId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void pause(Long[] jobIds) {
|
||||
for(Long jobId : jobIds){
|
||||
ScheduleUtils.pauseJob(scheduler, jobId);
|
||||
}
|
||||
|
||||
updateBatch(jobIds, Constant.ScheduleStatus.PAUSE.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void resume(Long[] jobIds) {
|
||||
for(Long jobId : jobIds){
|
||||
ScheduleUtils.resumeJob(scheduler, jobId);
|
||||
}
|
||||
|
||||
updateBatch(jobIds, Constant.ScheduleStatus.NORMAL.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.task;
|
||||
|
||||
/**
|
||||
* 定时任务接口,所有定时任务都要实现该接口
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface ITask {
|
||||
|
||||
/**
|
||||
* 执行定时任务接口
|
||||
*
|
||||
* @param params 参数,多参数使用JSON数据
|
||||
*/
|
||||
void run(String params);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.task;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 测试定时任务(演示Demo,可删除)
|
||||
*
|
||||
* testTask为spring bean的名称
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component("testTask")
|
||||
public class TestTask implements ITask {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public void run(String params){
|
||||
logger.debug("TestTask定时任务正在执行,参数为:{}", params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.utils;
|
||||
|
||||
import io.renren.common.utils.SpringContextUtils;
|
||||
import io.renren.modules.job.entity.ScheduleJobEntity;
|
||||
import io.renren.modules.job.entity.ScheduleJobLogEntity;
|
||||
import io.renren.modules.job.service.ScheduleJobLogService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class ScheduleJob extends QuartzJobBean {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||
ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap()
|
||||
.get(ScheduleJobEntity.JOB_PARAM_KEY);
|
||||
|
||||
//获取spring bean
|
||||
ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService) SpringContextUtils.getBean("scheduleJobLogService");
|
||||
|
||||
//数据库保存执行记录
|
||||
ScheduleJobLogEntity log = new ScheduleJobLogEntity();
|
||||
log.setJobId(scheduleJob.getJobId());
|
||||
log.setBeanName(scheduleJob.getBeanName());
|
||||
log.setParams(scheduleJob.getParams());
|
||||
log.setCreateTime(new Date());
|
||||
|
||||
//任务开始时间
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
//执行任务
|
||||
logger.debug("任务准备执行,任务ID:" + scheduleJob.getJobId());
|
||||
|
||||
Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
|
||||
Method method = target.getClass().getDeclaredMethod("run", String.class);
|
||||
method.invoke(target, scheduleJob.getParams());
|
||||
|
||||
//任务执行总时长
|
||||
long times = System.currentTimeMillis() - startTime;
|
||||
log.setTimes((int)times);
|
||||
//任务状态 0:成功 1:失败
|
||||
log.setStatus(0);
|
||||
|
||||
logger.debug("任务执行完毕,任务ID:" + scheduleJob.getJobId() + " 总共耗时:" + times + "毫秒");
|
||||
} catch (Exception e) {
|
||||
logger.error("任务执行失败,任务ID:" + scheduleJob.getJobId(), e);
|
||||
|
||||
//任务执行总时长
|
||||
long times = System.currentTimeMillis() - startTime;
|
||||
log.setTimes((int)times);
|
||||
|
||||
//任务状态 0:成功 1:失败
|
||||
log.setStatus(1);
|
||||
log.setError(StringUtils.substring(e.toString(), 0, 2000));
|
||||
}finally {
|
||||
scheduleJobLogService.save(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.job.utils;
|
||||
|
||||
import io.renren.common.exception.RRException;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.modules.job.entity.ScheduleJobEntity;
|
||||
import org.quartz.*;
|
||||
|
||||
/**
|
||||
* 定时任务工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class ScheduleUtils {
|
||||
private final static String JOB_NAME = "TASK_";
|
||||
|
||||
/**
|
||||
* 获取触发器key
|
||||
*/
|
||||
public static TriggerKey getTriggerKey(Long jobId) {
|
||||
return TriggerKey.triggerKey(JOB_NAME + jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jobKey
|
||||
*/
|
||||
public static JobKey getJobKey(Long jobId) {
|
||||
return JobKey.jobKey(JOB_NAME + jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表达式触发器
|
||||
*/
|
||||
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
|
||||
try {
|
||||
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("获取定时任务CronTrigger出现异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建定时任务
|
||||
*/
|
||||
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
//构建job信息
|
||||
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getJobId())).build();
|
||||
|
||||
//表达式调度构建器
|
||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
||||
.withMisfireHandlingInstructionDoNothing();
|
||||
|
||||
//按新的cronExpression表达式构建一个新的trigger
|
||||
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder).build();
|
||||
|
||||
//放入参数,运行时的方法可以获取
|
||||
jobDetail.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);
|
||||
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
|
||||
//暂停任务
|
||||
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
|
||||
pauseJob(scheduler, scheduleJob.getJobId());
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("创建定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新定时任务
|
||||
*/
|
||||
public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
|
||||
|
||||
//表达式调度构建器
|
||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
|
||||
.withMisfireHandlingInstructionDoNothing();
|
||||
|
||||
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
|
||||
|
||||
//按新的cronExpression表达式重新构建trigger
|
||||
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
|
||||
|
||||
//参数
|
||||
trigger.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);
|
||||
|
||||
scheduler.rescheduleJob(triggerKey, trigger);
|
||||
|
||||
//暂停任务
|
||||
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
|
||||
pauseJob(scheduler, scheduleJob.getJobId());
|
||||
}
|
||||
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("更新定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即执行任务
|
||||
*/
|
||||
public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
|
||||
try {
|
||||
//参数
|
||||
JobDataMap dataMap = new JobDataMap();
|
||||
dataMap.put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);
|
||||
|
||||
scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("立即执行定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停任务
|
||||
*/
|
||||
public static void pauseJob(Scheduler scheduler, Long jobId) {
|
||||
try {
|
||||
scheduler.pauseJob(getJobKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("暂停定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务
|
||||
*/
|
||||
public static void resumeJob(Scheduler scheduler, Long jobId) {
|
||||
try {
|
||||
scheduler.resumeJob(getJobKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("暂停定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除定时任务
|
||||
*/
|
||||
public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
|
||||
try {
|
||||
scheduler.deleteJob(getJobKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new RRException("删除定时任务失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.cloud;
|
||||
|
||||
import com.aliyun.oss.OSSClient;
|
||||
import io.renren.common.exception.RRException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 阿里云存储
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class AliyunCloudStorageService extends CloudStorageService {
|
||||
private OSSClient client;
|
||||
|
||||
public AliyunCloudStorageService(CloudStorageConfig config){
|
||||
this.config = config;
|
||||
|
||||
//初始化
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(),
|
||||
config.getAliyunAccessKeySecret());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(byte[] data, String path) {
|
||||
return upload(new ByteArrayInputStream(data), path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(InputStream inputStream, String path) {
|
||||
try {
|
||||
client.putObject(config.getAliyunBucketName(), path, inputStream);
|
||||
} catch (Exception e){
|
||||
throw new RRException("上传文件失败,请检查配置信息", e);
|
||||
}
|
||||
|
||||
return config.getAliyunDomain() + "/" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadSuffix(byte[] data, String suffix) {
|
||||
return upload(data, getPath(config.getAliyunPrefix(), suffix));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadSuffix(InputStream inputStream, String suffix) {
|
||||
return upload(inputStream, getPath(config.getAliyunPrefix(), suffix));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.cloud;
|
||||
|
||||
|
||||
import io.renren.common.validator.group.AliyunGroup;
|
||||
import io.renren.common.validator.group.QcloudGroup;
|
||||
import io.renren.common.validator.group.QiniuGroup;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 云存储配置信息
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
public class CloudStorageConfig implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
//类型 1:七牛 2:阿里云 3:腾讯云
|
||||
@Range(min=1, max=3, message = "类型错误")
|
||||
private Integer type;
|
||||
|
||||
//七牛绑定的域名
|
||||
@NotBlank(message="七牛绑定的域名不能为空", groups = QiniuGroup.class)
|
||||
@URL(message = "七牛绑定的域名格式不正确", groups = QiniuGroup.class)
|
||||
private String qiniuDomain;
|
||||
//七牛路径前缀
|
||||
private String qiniuPrefix;
|
||||
//七牛ACCESS_KEY
|
||||
@NotBlank(message="七牛AccessKey不能为空", groups = QiniuGroup.class)
|
||||
private String qiniuAccessKey;
|
||||
//七牛SECRET_KEY
|
||||
@NotBlank(message="七牛SecretKey不能为空", groups = QiniuGroup.class)
|
||||
private String qiniuSecretKey;
|
||||
//七牛存储空间名
|
||||
@NotBlank(message="七牛空间名不能为空", groups = QiniuGroup.class)
|
||||
private String qiniuBucketName;
|
||||
|
||||
//阿里云绑定的域名
|
||||
@NotBlank(message="阿里云绑定的域名不能为空", groups = AliyunGroup.class)
|
||||
@URL(message = "阿里云绑定的域名格式不正确", groups = AliyunGroup.class)
|
||||
private String aliyunDomain;
|
||||
//阿里云路径前缀
|
||||
private String aliyunPrefix;
|
||||
//阿里云EndPoint
|
||||
@NotBlank(message="阿里云EndPoint不能为空", groups = AliyunGroup.class)
|
||||
private String aliyunEndPoint;
|
||||
//阿里云AccessKeyId
|
||||
@NotBlank(message="阿里云AccessKeyId不能为空", groups = AliyunGroup.class)
|
||||
private String aliyunAccessKeyId;
|
||||
//阿里云AccessKeySecret
|
||||
@NotBlank(message="阿里云AccessKeySecret不能为空", groups = AliyunGroup.class)
|
||||
private String aliyunAccessKeySecret;
|
||||
//阿里云BucketName
|
||||
@NotBlank(message="阿里云BucketName不能为空", groups = AliyunGroup.class)
|
||||
private String aliyunBucketName;
|
||||
|
||||
//腾讯云绑定的域名
|
||||
@NotBlank(message="腾讯云绑定的域名不能为空", groups = QcloudGroup.class)
|
||||
@URL(message = "腾讯云绑定的域名格式不正确", groups = QcloudGroup.class)
|
||||
private String qcloudDomain;
|
||||
//腾讯云路径前缀
|
||||
private String qcloudPrefix;
|
||||
//腾讯云AppId
|
||||
@NotNull(message="腾讯云AppId不能为空", groups = QcloudGroup.class)
|
||||
private Integer qcloudAppId;
|
||||
//腾讯云SecretId
|
||||
@NotBlank(message="腾讯云SecretId不能为空", groups = QcloudGroup.class)
|
||||
private String qcloudSecretId;
|
||||
//腾讯云SecretKey
|
||||
@NotBlank(message="腾讯云SecretKey不能为空", groups = QcloudGroup.class)
|
||||
private String qcloudSecretKey;
|
||||
//腾讯云BucketName
|
||||
@NotBlank(message="腾讯云BucketName不能为空", groups = QcloudGroup.class)
|
||||
private String qcloudBucketName;
|
||||
//腾讯云COS所属地区
|
||||
@NotBlank(message="所属地区不能为空", groups = QcloudGroup.class)
|
||||
private String qcloudRegion;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.cloud;
|
||||
|
||||
import io.renren.common.utils.DateUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 云存储(支持七牛、阿里云、腾讯云、又拍云)
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public abstract class CloudStorageService {
|
||||
/** 云存储配置信息 */
|
||||
CloudStorageConfig config;
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
* @param prefix 前缀
|
||||
* @param suffix 后缀
|
||||
* @return 返回上传路径
|
||||
*/
|
||||
public String getPath(String prefix, String suffix) {
|
||||
//生成uuid
|
||||
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
//文件路径
|
||||
String path = DateUtils.format(new Date(), "yyyyMMdd") + "/" + uuid;
|
||||
|
||||
if(StringUtils.isNotBlank(prefix)){
|
||||
path = prefix + "/" + path;
|
||||
}
|
||||
|
||||
return path + suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param data 文件字节数组
|
||||
* @param path 文件路径,包含文件名
|
||||
* @return 返回http地址
|
||||
*/
|
||||
public abstract String upload(byte[] data, String path);
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param data 文件字节数组
|
||||
* @param suffix 后缀
|
||||
* @return 返回http地址
|
||||
*/
|
||||
public abstract String uploadSuffix(byte[] data, String suffix);
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param inputStream 字节流
|
||||
* @param path 文件路径,包含文件名
|
||||
* @return 返回http地址
|
||||
*/
|
||||
public abstract String upload(InputStream inputStream, String path);
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param inputStream 字节流
|
||||
* @param suffix 后缀
|
||||
* @return 返回http地址
|
||||
*/
|
||||
public abstract String uploadSuffix(InputStream inputStream, String suffix);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.cloud;
|
||||
|
||||
|
||||
import io.renren.common.utils.ConfigConstant;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.common.utils.SpringContextUtils;
|
||||
import io.renren.modules.sys.service.SysConfigService;
|
||||
|
||||
/**
|
||||
* 文件上传Factory
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public final class OSSFactory {
|
||||
private static SysConfigService sysConfigService;
|
||||
|
||||
static {
|
||||
OSSFactory.sysConfigService = (SysConfigService) SpringContextUtils.getBean("sysConfigService");
|
||||
}
|
||||
|
||||
public static CloudStorageService build(){
|
||||
//获取云存储配置信息
|
||||
CloudStorageConfig config = sysConfigService.getConfigObject(ConfigConstant.CLOUD_STORAGE_CONFIG_KEY, CloudStorageConfig.class);
|
||||
|
||||
if(config.getType() == Constant.CloudService.QINIU.getValue()){
|
||||
return new QiniuCloudStorageService(config);
|
||||
}else if(config.getType() == Constant.CloudService.ALIYUN.getValue()){
|
||||
return new AliyunCloudStorageService(config);
|
||||
}else if(config.getType() == Constant.CloudService.QCLOUD.getValue()){
|
||||
return new QcloudCloudStorageService(config);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.cloud;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qcloud.cos.COSClient;
|
||||
import com.qcloud.cos.ClientConfig;
|
||||
import com.qcloud.cos.request.UploadFileRequest;
|
||||
import com.qcloud.cos.sign.Credentials;
|
||||
import io.renren.common.exception.RRException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 腾讯云存储
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class QcloudCloudStorageService extends CloudStorageService {
|
||||
private COSClient client;
|
||||
|
||||
public QcloudCloudStorageService(CloudStorageConfig config){
|
||||
this.config = config;
|
||||
|
||||
//初始化
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
Credentials credentials = new Credentials(config.getQcloudAppId(), config.getQcloudSecretId(),
|
||||
config.getQcloudSecretKey());
|
||||
|
||||
//初始化客户端配置
|
||||
ClientConfig clientConfig = new ClientConfig();
|
||||
//设置bucket所在的区域,华南:gz 华北:tj 华东:sh
|
||||
clientConfig.setRegion(config.getQcloudRegion());
|
||||
|
||||
client = new COSClient(clientConfig, credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(byte[] data, String path) {
|
||||
//腾讯云必需要以"/"开头
|
||||
if(!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
|
||||
//上传到腾讯云
|
||||
UploadFileRequest request = new UploadFileRequest(config.getQcloudBucketName(), path, data);
|
||||
String response = client.uploadFile(request);
|
||||
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
if(jsonObject.getInteger("code") != 0) {
|
||||
throw new RRException("文件上传失败," + jsonObject.getString("message"));
|
||||
}
|
||||
|
||||
return config.getQcloudDomain() + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(InputStream inputStream, String path) {
|
||||
try {
|
||||
byte[] data = IOUtils.toByteArray(inputStream);
|
||||
return this.upload(data, path);
|
||||
} catch (IOException e) {
|
||||
throw new RRException("上传文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadSuffix(byte[] data, String suffix) {
|
||||
return upload(data, getPath(config.getQcloudPrefix(), suffix));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadSuffix(InputStream inputStream, String suffix) {
|
||||
return upload(inputStream, getPath(config.getQcloudPrefix(), suffix));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.cloud;
|
||||
|
||||
import com.qiniu.common.Zone;
|
||||
import com.qiniu.http.Response;
|
||||
import com.qiniu.storage.Configuration;
|
||||
import com.qiniu.storage.UploadManager;
|
||||
import com.qiniu.util.Auth;
|
||||
import io.renren.common.exception.RRException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 七牛云存储
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class QiniuCloudStorageService extends CloudStorageService {
|
||||
private UploadManager uploadManager;
|
||||
private String token;
|
||||
|
||||
public QiniuCloudStorageService(CloudStorageConfig config){
|
||||
this.config = config;
|
||||
|
||||
//初始化
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
uploadManager = new UploadManager(new Configuration(Zone.autoZone()));
|
||||
token = Auth.create(config.getQiniuAccessKey(), config.getQiniuSecretKey()).
|
||||
uploadToken(config.getQiniuBucketName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(byte[] data, String path) {
|
||||
try {
|
||||
Response res = uploadManager.put(data, path, token);
|
||||
if (!res.isOK()) {
|
||||
throw new RuntimeException("上传七牛出错:" + res.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RRException("上传文件失败,请核对七牛配置信息", e);
|
||||
}
|
||||
|
||||
return config.getQiniuDomain() + "/" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(InputStream inputStream, String path) {
|
||||
try {
|
||||
byte[] data = IOUtils.toByteArray(inputStream);
|
||||
return this.upload(data, path);
|
||||
} catch (IOException e) {
|
||||
throw new RRException("上传文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadSuffix(byte[] data, String suffix) {
|
||||
return upload(data, getPath(config.getQiniuPrefix(), suffix));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadSuffix(InputStream inputStream, String suffix) {
|
||||
return upload(inputStream, getPath(config.getQiniuPrefix(), suffix));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.controller;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.renren.common.exception.RRException;
|
||||
import io.renren.common.utils.ConfigConstant;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.common.validator.group.AliyunGroup;
|
||||
import io.renren.common.validator.group.QcloudGroup;
|
||||
import io.renren.common.validator.group.QiniuGroup;
|
||||
import io.renren.modules.oss.cloud.CloudStorageConfig;
|
||||
import io.renren.modules.oss.cloud.OSSFactory;
|
||||
import io.renren.modules.oss.entity.SysOssEntity;
|
||||
import io.renren.modules.oss.service.SysOssService;
|
||||
import io.renren.modules.sys.service.SysConfigService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("sys/oss")
|
||||
public class SysOssController {
|
||||
@Autowired
|
||||
private SysOssService sysOssService;
|
||||
@Autowired
|
||||
private SysConfigService sysConfigService;
|
||||
|
||||
private final static String KEY = ConfigConstant.CLOUD_STORAGE_CONFIG_KEY;
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@RequiresPermissions("sys:oss:all")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
PageUtils page = sysOssService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 云存储配置信息
|
||||
*/
|
||||
@GetMapping("/config")
|
||||
@RequiresPermissions("sys:oss:all")
|
||||
public R config(){
|
||||
CloudStorageConfig config = sysConfigService.getConfigObject(KEY, CloudStorageConfig.class);
|
||||
|
||||
return R.ok().put("config", config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存云存储配置信息
|
||||
*/
|
||||
@PostMapping("/saveConfig")
|
||||
@RequiresPermissions("sys:oss:all")
|
||||
public R saveConfig(@RequestBody CloudStorageConfig config){
|
||||
//校验类型
|
||||
ValidatorUtils.validateEntity(config);
|
||||
|
||||
if(config.getType() == Constant.CloudService.QINIU.getValue()){
|
||||
//校验七牛数据
|
||||
ValidatorUtils.validateEntity(config, QiniuGroup.class);
|
||||
}else if(config.getType() == Constant.CloudService.ALIYUN.getValue()){
|
||||
//校验阿里云数据
|
||||
ValidatorUtils.validateEntity(config, AliyunGroup.class);
|
||||
}else if(config.getType() == Constant.CloudService.QCLOUD.getValue()){
|
||||
//校验腾讯云数据
|
||||
ValidatorUtils.validateEntity(config, QcloudGroup.class);
|
||||
}
|
||||
|
||||
sysConfigService.updateValueByKey(KEY, new Gson().toJson(config));
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
@PostMapping("/upload")
|
||||
@RequiresPermissions("sys:oss:all")
|
||||
public R upload(@RequestParam("file") MultipartFile file) throws Exception {
|
||||
if (file.isEmpty()) {
|
||||
throw new RRException("上传文件不能为空");
|
||||
}
|
||||
|
||||
//上传文件
|
||||
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
|
||||
String url = OSSFactory.build().uploadSuffix(file.getBytes(), suffix);
|
||||
|
||||
//保存文件信息
|
||||
SysOssEntity ossEntity = new SysOssEntity();
|
||||
ossEntity.setUrl(url);
|
||||
ossEntity.setCreateDate(new Date());
|
||||
sysOssService.save(ossEntity);
|
||||
|
||||
return R.ok().put("url", url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
@RequiresPermissions("sys:oss:all")
|
||||
public R delete(@RequestBody Long[] ids){
|
||||
sysOssService.removeByIds(Arrays.asList(ids));
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.oss.entity.SysOssEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysOssDao extends BaseMapper<SysOssEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_oss")
|
||||
public class SysOssEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
//URL地址
|
||||
private String url;
|
||||
//创建时间
|
||||
private Date createDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.oss.entity.SysOssEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysOssService extends IService<SysOssEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.oss.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.Query;
|
||||
import io.renren.modules.oss.dao.SysOssDao;
|
||||
import io.renren.modules.oss.entity.SysOssEntity;
|
||||
import io.renren.modules.oss.service.SysOssService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Service("sysOssService")
|
||||
public class SysOssServiceImpl extends ServiceImpl<SysOssDao, SysOssEntity> implements SysOssService {
|
||||
|
||||
@Override
|
||||
public PageUtils queryPage(Map<String, Object> params) {
|
||||
IPage<SysOssEntity> page = this.page(
|
||||
new Query<SysOssEntity>().getPage(params)
|
||||
);
|
||||
|
||||
return new PageUtils(page);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Controller公共组件
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public abstract class AbstractController {
|
||||
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected SysUserEntity getUser() {
|
||||
return (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
|
||||
}
|
||||
|
||||
protected Long getUserId() {
|
||||
return getUser().getUserId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
|
||||
import io.renren.common.annotation.SysLog;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.modules.sys.entity.SysConfigEntity;
|
||||
import io.renren.modules.sys.service.SysConfigService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统配置信息
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sys/config")
|
||||
public class SysConfigController extends AbstractController {
|
||||
@Autowired
|
||||
private SysConfigService sysConfigService;
|
||||
|
||||
/**
|
||||
* 所有配置列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@RequiresPermissions("sys:config:list")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
PageUtils page = sysConfigService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置信息
|
||||
*/
|
||||
@GetMapping("/info/{id}")
|
||||
@RequiresPermissions("sys:config:info")
|
||||
public R info(@PathVariable("id") Long id){
|
||||
SysConfigEntity config = sysConfigService.getById(id);
|
||||
|
||||
return R.ok().put("config", config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存配置
|
||||
*/
|
||||
@SysLog("保存配置")
|
||||
@PostMapping("/save")
|
||||
@RequiresPermissions("sys:config:save")
|
||||
public R save(@RequestBody SysConfigEntity config){
|
||||
ValidatorUtils.validateEntity(config);
|
||||
|
||||
sysConfigService.saveConfig(config);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改配置
|
||||
*/
|
||||
@SysLog("修改配置")
|
||||
@PostMapping("/update")
|
||||
@RequiresPermissions("sys:config:update")
|
||||
public R update(@RequestBody SysConfigEntity config){
|
||||
ValidatorUtils.validateEntity(config);
|
||||
|
||||
sysConfigService.update(config);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配置
|
||||
*/
|
||||
@SysLog("删除配置")
|
||||
@PostMapping("/delete")
|
||||
@RequiresPermissions("sys:config:delete")
|
||||
public R delete(@RequestBody Long[] ids){
|
||||
sysConfigService.deleteBatch(ids);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.modules.sys.service.SysLogService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/sys/log")
|
||||
public class SysLogController {
|
||||
@Autowired
|
||||
private SysLogService sysLogService;
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/list")
|
||||
@RequiresPermissions("sys:log:list")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
PageUtils page = sysLogService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import io.renren.modules.sys.form.SysLoginForm;
|
||||
import io.renren.modules.sys.service.SysCaptchaService;
|
||||
import io.renren.modules.sys.service.SysUserService;
|
||||
import io.renren.modules.sys.service.SysUserTokenService;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.shiro.crypto.hash.Sha256Hash;
|
||||
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.RestController;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 登录相关
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
public class SysLoginController extends AbstractController {
|
||||
@Autowired
|
||||
private SysUserService sysUserService;
|
||||
@Autowired
|
||||
private SysUserTokenService sysUserTokenService;
|
||||
@Autowired
|
||||
private SysCaptchaService sysCaptchaService;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@GetMapping("captcha.jpg")
|
||||
public void captcha(HttpServletResponse response, String uuid)throws IOException {
|
||||
response.setHeader("Cache-Control", "no-store, no-cache");
|
||||
response.setContentType("image/jpeg");
|
||||
|
||||
//获取图片验证码
|
||||
BufferedImage image = sysCaptchaService.getCaptcha(uuid);
|
||||
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
ImageIO.write(image, "jpg", out);
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
@PostMapping("/sys/login")
|
||||
public Map<String, Object> login(@RequestBody SysLoginForm form)throws IOException {
|
||||
boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
|
||||
if(!captcha){
|
||||
return R.error("验证码不正确");
|
||||
}
|
||||
|
||||
//用户信息
|
||||
SysUserEntity user = sysUserService.queryByUserName(form.getUsername());
|
||||
|
||||
//账号不存在、密码错误
|
||||
if(user == null || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
|
||||
return R.error("账号或密码不正确");
|
||||
}
|
||||
|
||||
//账号锁定
|
||||
if(user.getStatus() == 0){
|
||||
return R.error("账号已被锁定,请联系管理员");
|
||||
}
|
||||
|
||||
//生成token,并保存到数据库
|
||||
R r = sysUserTokenService.createToken(user.getUserId());
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出
|
||||
*/
|
||||
@PostMapping("/sys/logout")
|
||||
public R logout() {
|
||||
sysUserTokenService.logout(getUserId());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
import io.renren.common.annotation.SysLog;
|
||||
import io.renren.common.exception.RRException;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.modules.sys.entity.SysMenuEntity;
|
||||
import io.renren.modules.sys.service.ShiroService;
|
||||
import io.renren.modules.sys.service.SysMenuService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 系统菜单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sys/menu")
|
||||
public class SysMenuController extends AbstractController {
|
||||
@Autowired
|
||||
private SysMenuService sysMenuService;
|
||||
@Autowired
|
||||
private ShiroService shiroService;
|
||||
|
||||
/**
|
||||
* 导航菜单
|
||||
*/
|
||||
@GetMapping("/nav")
|
||||
public R nav(){
|
||||
List<SysMenuEntity> menuList = sysMenuService.getUserMenuList(getUserId());
|
||||
Set<String> permissions = shiroService.getUserPermissions(getUserId());
|
||||
return R.ok().put("menuList", menuList).put("permissions", permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有菜单列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@RequiresPermissions("sys:menu:list")
|
||||
public List<SysMenuEntity> list(){
|
||||
List<SysMenuEntity> menuList = sysMenuService.list();
|
||||
for(SysMenuEntity sysMenuEntity : menuList){
|
||||
SysMenuEntity parentMenuEntity = sysMenuService.getById(sysMenuEntity.getParentId());
|
||||
if(parentMenuEntity != null){
|
||||
sysMenuEntity.setParentName(parentMenuEntity.getName());
|
||||
}
|
||||
}
|
||||
|
||||
return menuList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择菜单(添加、修改菜单)
|
||||
*/
|
||||
@GetMapping("/select")
|
||||
@RequiresPermissions("sys:menu:select")
|
||||
public R select(){
|
||||
//查询列表数据
|
||||
List<SysMenuEntity> menuList = sysMenuService.queryNotButtonList();
|
||||
|
||||
//添加顶级菜单
|
||||
SysMenuEntity root = new SysMenuEntity();
|
||||
root.setMenuId(0L);
|
||||
root.setName("一级菜单");
|
||||
root.setParentId(-1L);
|
||||
root.setOpen(true);
|
||||
menuList.add(root);
|
||||
|
||||
return R.ok().put("menuList", menuList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单信息
|
||||
*/
|
||||
@GetMapping("/info/{menuId}")
|
||||
@RequiresPermissions("sys:menu:info")
|
||||
public R info(@PathVariable("menuId") Long menuId){
|
||||
SysMenuEntity menu = sysMenuService.getById(menuId);
|
||||
return R.ok().put("menu", menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
@SysLog("保存菜单")
|
||||
@PostMapping("/save")
|
||||
@RequiresPermissions("sys:menu:save")
|
||||
public R save(@RequestBody SysMenuEntity menu){
|
||||
//数据校验
|
||||
verifyForm(menu);
|
||||
|
||||
sysMenuService.save(menu);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
@SysLog("修改菜单")
|
||||
@PostMapping("/update")
|
||||
@RequiresPermissions("sys:menu:update")
|
||||
public R update(@RequestBody SysMenuEntity menu){
|
||||
//数据校验
|
||||
verifyForm(menu);
|
||||
|
||||
sysMenuService.updateById(menu);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
@SysLog("删除菜单")
|
||||
@PostMapping("/delete/{menuId}")
|
||||
@RequiresPermissions("sys:menu:delete")
|
||||
public R delete(@PathVariable("menuId") long menuId){
|
||||
if(menuId <= 31){
|
||||
return R.error("系统菜单,不能删除");
|
||||
}
|
||||
|
||||
//判断是否有子菜单或按钮
|
||||
List<SysMenuEntity> menuList = sysMenuService.queryListParentId(menuId);
|
||||
if(menuList.size() > 0){
|
||||
return R.error("请先删除子菜单或按钮");
|
||||
}
|
||||
|
||||
sysMenuService.delete(menuId);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证参数是否正确
|
||||
*/
|
||||
private void verifyForm(SysMenuEntity menu){
|
||||
if(StringUtils.isBlank(menu.getName())){
|
||||
throw new RRException("菜单名称不能为空");
|
||||
}
|
||||
|
||||
if(menu.getParentId() == null){
|
||||
throw new RRException("上级菜单不能为空");
|
||||
}
|
||||
|
||||
//菜单
|
||||
if(menu.getType() == Constant.MenuType.MENU.getValue()){
|
||||
if(StringUtils.isBlank(menu.getUrl())){
|
||||
throw new RRException("菜单URL不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
//上级菜单类型
|
||||
int parentType = Constant.MenuType.CATALOG.getValue();
|
||||
if(menu.getParentId() != 0){
|
||||
SysMenuEntity parentMenu = sysMenuService.getById(menu.getParentId());
|
||||
parentType = parentMenu.getType();
|
||||
}
|
||||
|
||||
//目录、菜单
|
||||
if(menu.getType() == Constant.MenuType.CATALOG.getValue() ||
|
||||
menu.getType() == Constant.MenuType.MENU.getValue()){
|
||||
if(parentType != Constant.MenuType.CATALOG.getValue()){
|
||||
throw new RRException("上级菜单只能为目录类型");
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
//按钮
|
||||
if(menu.getType() == Constant.MenuType.BUTTON.getValue()){
|
||||
if(parentType != Constant.MenuType.MENU.getValue()){
|
||||
throw new RRException("上级菜单只能为菜单类型");
|
||||
}
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
import io.renren.common.annotation.SysLog;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.modules.sys.entity.SysRoleEntity;
|
||||
import io.renren.modules.sys.service.SysRoleMenuService;
|
||||
import io.renren.modules.sys.service.SysRoleService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 角色管理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sys/role")
|
||||
public class SysRoleController extends AbstractController {
|
||||
@Autowired
|
||||
private SysRoleService sysRoleService;
|
||||
@Autowired
|
||||
private SysRoleMenuService sysRoleMenuService;
|
||||
|
||||
/**
|
||||
* 角色列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@RequiresPermissions("sys:role:list")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
//如果不是超级管理员,则只查询自己创建的角色列表
|
||||
if(getUserId() != Constant.SUPER_ADMIN){
|
||||
params.put("createUserId", getUserId());
|
||||
}
|
||||
|
||||
PageUtils page = sysRoleService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色列表
|
||||
*/
|
||||
@GetMapping("/select")
|
||||
@RequiresPermissions("sys:role:select")
|
||||
public R select(){
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
//如果不是超级管理员,则只查询自己所拥有的角色列表
|
||||
if(getUserId() != Constant.SUPER_ADMIN){
|
||||
map.put("create_user_id", getUserId());
|
||||
}
|
||||
List<SysRoleEntity> list = (List<SysRoleEntity>) sysRoleService.listByMap(map);
|
||||
|
||||
return R.ok().put("list", list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色信息
|
||||
*/
|
||||
@GetMapping("/info/{roleId}")
|
||||
@RequiresPermissions("sys:role:info")
|
||||
public R info(@PathVariable("roleId") Long roleId){
|
||||
SysRoleEntity role = sysRoleService.getById(roleId);
|
||||
|
||||
//查询角色对应的菜单
|
||||
List<Long> menuIdList = sysRoleMenuService.queryMenuIdList(roleId);
|
||||
role.setMenuIdList(menuIdList);
|
||||
|
||||
return R.ok().put("role", role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存角色
|
||||
*/
|
||||
@SysLog("保存角色")
|
||||
@PostMapping("/save")
|
||||
@RequiresPermissions("sys:role:save")
|
||||
public R save(@RequestBody SysRoleEntity role){
|
||||
ValidatorUtils.validateEntity(role);
|
||||
|
||||
role.setCreateUserId(getUserId());
|
||||
sysRoleService.saveRole(role);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改角色
|
||||
*/
|
||||
@SysLog("修改角色")
|
||||
@PostMapping("/update")
|
||||
@RequiresPermissions("sys:role:update")
|
||||
public R update(@RequestBody SysRoleEntity role){
|
||||
ValidatorUtils.validateEntity(role);
|
||||
|
||||
role.setCreateUserId(getUserId());
|
||||
sysRoleService.update(role);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
*/
|
||||
@SysLog("删除角色")
|
||||
@PostMapping("/delete")
|
||||
@RequiresPermissions("sys:role:delete")
|
||||
public R delete(@RequestBody Long[] roleIds){
|
||||
sysRoleService.deleteBatch(roleIds);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.controller;
|
||||
|
||||
import io.renren.common.annotation.SysLog;
|
||||
import io.renren.common.utils.Constant;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.common.validator.Assert;
|
||||
import io.renren.common.validator.ValidatorUtils;
|
||||
import io.renren.common.validator.group.AddGroup;
|
||||
import io.renren.common.validator.group.UpdateGroup;
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import io.renren.modules.sys.form.PasswordForm;
|
||||
import io.renren.modules.sys.service.SysUserRoleService;
|
||||
import io.renren.modules.sys.service.SysUserService;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.crypto.hash.Sha256Hash;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sys/user")
|
||||
public class SysUserController extends AbstractController {
|
||||
@Autowired
|
||||
private SysUserService sysUserService;
|
||||
@Autowired
|
||||
private SysUserRoleService sysUserRoleService;
|
||||
|
||||
|
||||
/**
|
||||
* 所有用户列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@RequiresPermissions("sys:user:list")
|
||||
public R list(@RequestParam Map<String, Object> params){
|
||||
//只有超级管理员,才能查看所有管理员列表
|
||||
if(getUserId() != Constant.SUPER_ADMIN){
|
||||
params.put("createUserId", getUserId());
|
||||
}
|
||||
PageUtils page = sysUserService.queryPage(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录的用户信息
|
||||
*/
|
||||
@GetMapping("/info")
|
||||
public R info(){
|
||||
return R.ok().put("user", getUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改登录用户密码
|
||||
*/
|
||||
@SysLog("修改密码")
|
||||
@PostMapping("/password")
|
||||
public R password(@RequestBody PasswordForm form){
|
||||
Assert.isBlank(form.getNewPassword(), "新密码不为能空");
|
||||
|
||||
//sha256加密
|
||||
String password = new Sha256Hash(form.getPassword(), getUser().getSalt()).toHex();
|
||||
//sha256加密
|
||||
String newPassword = new Sha256Hash(form.getNewPassword(), getUser().getSalt()).toHex();
|
||||
|
||||
//更新密码
|
||||
boolean flag = sysUserService.updatePassword(getUserId(), password, newPassword);
|
||||
if(!flag){
|
||||
return R.error("原密码不正确");
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
@GetMapping("/info/{userId}")
|
||||
@RequiresPermissions("sys:user:info")
|
||||
public R info(@PathVariable("userId") Long userId){
|
||||
SysUserEntity user = sysUserService.getById(userId);
|
||||
|
||||
//获取用户所属的角色列表
|
||||
List<Long> roleIdList = sysUserRoleService.queryRoleIdList(userId);
|
||||
user.setRoleIdList(roleIdList);
|
||||
|
||||
return R.ok().put("user", user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存用户
|
||||
*/
|
||||
@SysLog("保存用户")
|
||||
@PostMapping("/save")
|
||||
@RequiresPermissions("sys:user:save")
|
||||
public R save(@RequestBody SysUserEntity user){
|
||||
ValidatorUtils.validateEntity(user, AddGroup.class);
|
||||
|
||||
user.setCreateUserId(getUserId());
|
||||
sysUserService.saveUser(user);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
*/
|
||||
@SysLog("修改用户")
|
||||
@PostMapping("/update")
|
||||
@RequiresPermissions("sys:user:update")
|
||||
public R update(@RequestBody SysUserEntity user){
|
||||
ValidatorUtils.validateEntity(user, UpdateGroup.class);
|
||||
|
||||
user.setCreateUserId(getUserId());
|
||||
sysUserService.update(user);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
@SysLog("删除用户")
|
||||
@PostMapping("/delete")
|
||||
@RequiresPermissions("sys:user:delete")
|
||||
public R delete(@RequestBody Long[] userIds){
|
||||
if(ArrayUtils.contains(userIds, 1L)){
|
||||
return R.error("系统管理员不能删除");
|
||||
}
|
||||
|
||||
if(ArrayUtils.contains(userIds, getUserId())){
|
||||
return R.error("当前用户不能删除");
|
||||
}
|
||||
|
||||
sysUserService.deleteBatch(userIds);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysCaptchaEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysCaptchaDao extends BaseMapper<SysCaptchaEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysConfigEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 系统配置信息
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysConfigDao extends BaseMapper<SysConfigEntity> {
|
||||
|
||||
/**
|
||||
* 根据key,查询value
|
||||
*/
|
||||
SysConfigEntity queryByKey(String paramKey);
|
||||
|
||||
/**
|
||||
* 根据key,更新value
|
||||
*/
|
||||
int updateValueByKey(@Param("paramKey") String paramKey, @Param("paramValue") String paramValue);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysLogEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysLogDao extends BaseMapper<SysLogEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysMenuEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单管理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysMenuDao extends BaseMapper<SysMenuEntity> {
|
||||
|
||||
/**
|
||||
* 根据父菜单,查询子菜单
|
||||
* @param parentId 父菜单ID
|
||||
*/
|
||||
List<SysMenuEntity> queryListParentId(Long parentId);
|
||||
|
||||
/**
|
||||
* 获取不包含按钮的菜单列表
|
||||
*/
|
||||
List<SysMenuEntity> queryNotButtonList();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysRoleEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色管理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysRoleDao extends BaseMapper<SysRoleEntity> {
|
||||
|
||||
/**
|
||||
* 查询用户创建的角色ID列表
|
||||
*/
|
||||
List<Long> queryRoleIdList(Long createUserId);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysRoleMenuEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色与菜单对应关系
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysRoleMenuDao extends BaseMapper<SysRoleMenuEntity> {
|
||||
|
||||
/**
|
||||
* 根据角色ID,获取菜单ID列表
|
||||
*/
|
||||
List<Long> queryMenuIdList(Long roleId);
|
||||
|
||||
/**
|
||||
* 根据角色ID数组,批量删除
|
||||
*/
|
||||
int deleteBatch(Long[] roleIds);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserDao extends BaseMapper<SysUserEntity> {
|
||||
|
||||
/**
|
||||
* 查询用户的所有权限
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
List<String> queryAllPerms(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户的所有菜单ID
|
||||
*/
|
||||
List<Long> queryAllMenuId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户名,查询系统用户
|
||||
*/
|
||||
SysUserEntity queryByUserName(String username);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysUserRoleEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户与角色对应关系
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserRoleDao extends BaseMapper<SysUserRoleEntity> {
|
||||
|
||||
/**
|
||||
* 根据用户ID,获取角色ID列表
|
||||
*/
|
||||
List<Long> queryRoleIdList(Long userId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据角色ID数组,批量删除
|
||||
*/
|
||||
int deleteBatch(Long[] roleIds);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import io.renren.modules.sys.entity.SysUserTokenEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 系统用户Token
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserTokenDao extends BaseMapper<SysUserTokenEntity> {
|
||||
|
||||
SysUserTokenEntity queryByToken(String token);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 系统验证码
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_captcha")
|
||||
public class SysCaptchaEntity {
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String uuid;
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Date expireTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 系统配置信息
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_config")
|
||||
public class SysConfigEntity {
|
||||
@TableId
|
||||
private Long id;
|
||||
@NotBlank(message="参数名不能为空")
|
||||
private String paramKey;
|
||||
@NotBlank(message="参数值不能为空")
|
||||
private String paramValue;
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_log")
|
||||
public class SysLogEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@TableId
|
||||
private Long id;
|
||||
//用户名
|
||||
private String username;
|
||||
//用户操作
|
||||
private String operation;
|
||||
//请求方法
|
||||
private String method;
|
||||
//请求参数
|
||||
private String params;
|
||||
//执行时长(毫秒)
|
||||
private Long time;
|
||||
//IP地址
|
||||
private String ip;
|
||||
//创建时间
|
||||
private Date createDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单管理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_menu")
|
||||
public class SysMenuEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
@TableId
|
||||
private Long menuId;
|
||||
|
||||
/**
|
||||
* 父菜单ID,一级菜单为0
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 父菜单名称
|
||||
*/
|
||||
@TableField(exist=false)
|
||||
private String parentName;
|
||||
|
||||
/**
|
||||
* 菜单名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 菜单URL
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 授权(多个用逗号分隔,如:user:list,user:create)
|
||||
*/
|
||||
private String perms;
|
||||
|
||||
/**
|
||||
* 类型 0:目录 1:菜单 2:按钮
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 菜单图标
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer orderNum;
|
||||
|
||||
/**
|
||||
* ztree属性
|
||||
*/
|
||||
@TableField(exist=false)
|
||||
private Boolean open;
|
||||
|
||||
@TableField(exist=false)
|
||||
private List<?> list;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_role")
|
||||
public class SysRoleEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
@TableId
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 角色名称
|
||||
*/
|
||||
@NotBlank(message="角色名称不能为空")
|
||||
private String roleName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 创建者ID
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
@TableField(exist=false)
|
||||
private List<Long> menuIdList;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 角色与菜单对应关系
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_role_menu")
|
||||
public class SysRoleMenuEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
private Long menuId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.renren.common.validator.group.AddGroup;
|
||||
import io.renren.common.validator.group.UpdateGroup;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user")
|
||||
public class SysUserEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@TableId
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@NotBlank(message="用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@NotBlank(message="密码不能为空", groups = AddGroup.class)
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 盐
|
||||
*/
|
||||
private String salt;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@NotBlank(message="邮箱不能为空", groups = {AddGroup.class, UpdateGroup.class})
|
||||
@Email(message="邮箱格式不正确", groups = {AddGroup.class, UpdateGroup.class})
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 状态 0:禁用 1:正常
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 角色ID列表
|
||||
*/
|
||||
@TableField(exist=false)
|
||||
private List<Long> roleIdList;
|
||||
|
||||
/**
|
||||
* 创建者ID
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 用户与角色对应关系
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user_role")
|
||||
public class SysUserRoleEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 系统用户Token
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user_token")
|
||||
public class SysUserTokenEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
//用户ID
|
||||
@TableId(type = IdType.INPUT)
|
||||
private Long userId;
|
||||
//token
|
||||
private String token;
|
||||
//过期时间
|
||||
private Date expireTime;
|
||||
//更新时间
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.form;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 密码表单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
public class PasswordForm {
|
||||
/**
|
||||
* 原密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 新密码
|
||||
*/
|
||||
private String newPassword;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.form;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 登录表单
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Data
|
||||
public class SysLoginForm {
|
||||
private String username;
|
||||
private String password;
|
||||
private String captcha;
|
||||
private String uuid;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.oauth2;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.renren.common.utils.HttpContextUtils;
|
||||
import io.renren.common.utils.R;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* oauth2过滤器
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class OAuth2Filter extends AuthenticatingFilter {
|
||||
|
||||
@Override
|
||||
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
|
||||
//获取请求token
|
||||
String token = getRequestToken((HttpServletRequest) request);
|
||||
|
||||
if(StringUtils.isBlank(token)){
|
||||
return null;
|
||||
}
|
||||
|
||||
return new OAuth2Token(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||
if(((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
|
||||
//获取请求token,如果token不存在,直接返回401
|
||||
String token = getRequestToken((HttpServletRequest) request);
|
||||
if(StringUtils.isBlank(token)){
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
|
||||
|
||||
String json = new Gson().toJson(R.error(HttpStatus.SC_UNAUTHORIZED, "invalid token"));
|
||||
|
||||
httpResponse.getWriter().print(json);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return executeLogin(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
httpResponse.setContentType("application/json;charset=utf-8");
|
||||
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
|
||||
try {
|
||||
//处理登录失败的异常
|
||||
Throwable throwable = e.getCause() == null ? e : e.getCause();
|
||||
R r = R.error(HttpStatus.SC_UNAUTHORIZED, throwable.getMessage());
|
||||
|
||||
String json = new Gson().toJson(r);
|
||||
httpResponse.getWriter().print(json);
|
||||
} catch (IOException e1) {
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求的token
|
||||
*/
|
||||
private String getRequestToken(HttpServletRequest httpRequest){
|
||||
//从header中获取token
|
||||
String token = httpRequest.getHeader("token");
|
||||
|
||||
//如果header中不存在token,则从参数中获取token
|
||||
if(StringUtils.isBlank(token)){
|
||||
token = httpRequest.getParameter("token");
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.oauth2;
|
||||
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import io.renren.modules.sys.entity.SysUserTokenEntity;
|
||||
import io.renren.modules.sys.service.ShiroService;
|
||||
import org.apache.shiro.authc.*;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 认证
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class OAuth2Realm extends AuthorizingRealm {
|
||||
@Autowired
|
||||
private ShiroService shiroService;
|
||||
|
||||
@Override
|
||||
public boolean supports(AuthenticationToken token) {
|
||||
return token instanceof OAuth2Token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权(验证权限时调用)
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
|
||||
SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();
|
||||
Long userId = user.getUserId();
|
||||
|
||||
//用户权限列表
|
||||
Set<String> permsSet = shiroService.getUserPermissions(userId);
|
||||
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
info.setStringPermissions(permsSet);
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证(登录时调用)
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
|
||||
String accessToken = (String) token.getPrincipal();
|
||||
|
||||
//根据accessToken,查询用户信息
|
||||
SysUserTokenEntity tokenEntity = shiroService.queryByToken(accessToken);
|
||||
//token失效
|
||||
if(tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis()){
|
||||
throw new IncorrectCredentialsException("token失效,请重新登录");
|
||||
}
|
||||
|
||||
//查询用户信息
|
||||
SysUserEntity user = shiroService.queryUser(tokenEntity.getUserId());
|
||||
//账号锁定
|
||||
if(user.getStatus() == 0){
|
||||
throw new LockedAccountException("账号已被锁定,请联系管理员");
|
||||
}
|
||||
|
||||
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, getName());
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.oauth2;
|
||||
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
/**
|
||||
* token
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class OAuth2Token implements AuthenticationToken {
|
||||
private String token;
|
||||
|
||||
public OAuth2Token(String token){
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrincipal() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.oauth2;
|
||||
|
||||
import io.renren.common.exception.RRException;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class TokenGenerator {
|
||||
|
||||
public static String generateValue() {
|
||||
return generateValue(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
private static final char[] hexCode = "0123456789abcdef".toCharArray();
|
||||
|
||||
public static String toHexString(byte[] data) {
|
||||
if(data == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder r = new StringBuilder(data.length*2);
|
||||
for ( byte b : data) {
|
||||
r.append(hexCode[(b >> 4) & 0xF]);
|
||||
r.append(hexCode[(b & 0xF)]);
|
||||
}
|
||||
return r.toString();
|
||||
}
|
||||
|
||||
public static String generateValue(String param) {
|
||||
try {
|
||||
MessageDigest algorithm = MessageDigest.getInstance("MD5");
|
||||
algorithm.reset();
|
||||
algorithm.update(param.getBytes());
|
||||
byte[] messageDigest = algorithm.digest();
|
||||
return toHexString(messageDigest);
|
||||
} catch (Exception e) {
|
||||
throw new RRException("生成Token失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.redis;
|
||||
|
||||
|
||||
import io.renren.common.utils.RedisKeys;
|
||||
import io.renren.common.utils.RedisUtils;
|
||||
import io.renren.modules.sys.entity.SysConfigEntity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 系统配置Redis
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class SysConfigRedis {
|
||||
@Autowired
|
||||
private RedisUtils redisUtils;
|
||||
|
||||
public void saveOrUpdate(SysConfigEntity config) {
|
||||
if(config == null){
|
||||
return ;
|
||||
}
|
||||
String key = RedisKeys.getSysConfigKey(config.getParamKey());
|
||||
redisUtils.set(key, config);
|
||||
}
|
||||
|
||||
public void delete(String configKey) {
|
||||
String key = RedisKeys.getSysConfigKey(configKey);
|
||||
redisUtils.delete(key);
|
||||
}
|
||||
|
||||
public SysConfigEntity get(String configKey){
|
||||
String key = RedisKeys.getSysConfigKey(configKey);
|
||||
return redisUtils.get(key, SysConfigEntity.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
import io.renren.modules.sys.entity.SysUserTokenEntity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* shiro相关接口
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface ShiroService {
|
||||
/**
|
||||
* 获取用户权限列表
|
||||
*/
|
||||
Set<String> getUserPermissions(long userId);
|
||||
|
||||
SysUserTokenEntity queryByToken(String token);
|
||||
|
||||
/**
|
||||
* 根据用户ID,查询用户
|
||||
* @param userId
|
||||
*/
|
||||
SysUserEntity queryUser(Long userId);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.modules.sys.entity.SysCaptchaEntity;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysCaptchaService extends IService<SysCaptchaEntity> {
|
||||
|
||||
/**
|
||||
* 获取图片验证码
|
||||
*/
|
||||
BufferedImage getCaptcha(String uuid);
|
||||
|
||||
/**
|
||||
* 验证码效验
|
||||
* @param uuid uuid
|
||||
* @param code 验证码
|
||||
* @return true:成功 false:失败
|
||||
*/
|
||||
boolean validate(String uuid, String code);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.sys.entity.SysConfigEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统配置信息
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysConfigService extends IService<SysConfigEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 保存配置信息
|
||||
*/
|
||||
public void saveConfig(SysConfigEntity config);
|
||||
|
||||
/**
|
||||
* 更新配置信息
|
||||
*/
|
||||
public void update(SysConfigEntity config);
|
||||
|
||||
/**
|
||||
* 根据key,更新value
|
||||
*/
|
||||
public void updateValueByKey(String key, String value);
|
||||
|
||||
/**
|
||||
* 删除配置信息
|
||||
*/
|
||||
public void deleteBatch(Long[] ids);
|
||||
|
||||
/**
|
||||
* 根据key,获取配置的value值
|
||||
*
|
||||
* @param key key
|
||||
*/
|
||||
public String getValue(String key);
|
||||
|
||||
/**
|
||||
* 根据key,获取value的Object对象
|
||||
* @param key key
|
||||
* @param clazz Object对象
|
||||
*/
|
||||
public <T> T getConfigObject(String key, Class<T> clazz);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.sys.entity.SysLogEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysLogService extends IService<SysLogEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.modules.sys.entity.SysMenuEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 菜单管理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysMenuService extends IService<SysMenuEntity> {
|
||||
|
||||
/**
|
||||
* 根据父菜单,查询子菜单
|
||||
* @param parentId 父菜单ID
|
||||
* @param menuIdList 用户菜单ID
|
||||
*/
|
||||
List<SysMenuEntity> queryListParentId(Long parentId, List<Long> menuIdList);
|
||||
|
||||
/**
|
||||
* 根据父菜单,查询子菜单
|
||||
* @param parentId 父菜单ID
|
||||
*/
|
||||
List<SysMenuEntity> queryListParentId(Long parentId);
|
||||
|
||||
/**
|
||||
* 获取不包含按钮的菜单列表
|
||||
*/
|
||||
List<SysMenuEntity> queryNotButtonList();
|
||||
|
||||
/**
|
||||
* 获取用户菜单列表
|
||||
*/
|
||||
List<SysMenuEntity> getUserMenuList(Long userId);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
void delete(Long menuId);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.modules.sys.entity.SysRoleMenuEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 角色与菜单对应关系
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysRoleMenuService extends IService<SysRoleMenuEntity> {
|
||||
|
||||
void saveOrUpdate(Long roleId, List<Long> menuIdList);
|
||||
|
||||
/**
|
||||
* 根据角色ID,获取菜单ID列表
|
||||
*/
|
||||
List<Long> queryMenuIdList(Long roleId);
|
||||
|
||||
/**
|
||||
* 根据角色ID数组,批量删除
|
||||
*/
|
||||
int deleteBatch(Long[] roleIds);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.sys.entity.SysRoleEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysRoleService extends IService<SysRoleEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
void saveRole(SysRoleEntity role);
|
||||
|
||||
void update(SysRoleEntity role);
|
||||
|
||||
void deleteBatch(Long[] roleIds);
|
||||
|
||||
|
||||
/**
|
||||
* 查询用户创建的角色ID列表
|
||||
*/
|
||||
List<Long> queryRoleIdList(Long createUserId);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.modules.sys.entity.SysUserRoleEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 用户与角色对应关系
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysUserRoleService extends IService<SysUserRoleEntity> {
|
||||
|
||||
void saveOrUpdate(Long userId, List<Long> roleIdList);
|
||||
|
||||
/**
|
||||
* 根据用户ID,获取角色ID列表
|
||||
*/
|
||||
List<Long> queryRoleIdList(Long userId);
|
||||
|
||||
/**
|
||||
* 根据角色ID数组,批量删除
|
||||
*/
|
||||
int deleteBatch(Long[] roleIds);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.PageUtils;
|
||||
import io.renren.modules.sys.entity.SysUserEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysUserService extends IService<SysUserEntity> {
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 查询用户的所有权限
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
List<String> queryAllPerms(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户的所有菜单ID
|
||||
*/
|
||||
List<Long> queryAllMenuId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户名,查询系统用户
|
||||
*/
|
||||
SysUserEntity queryByUserName(String username);
|
||||
|
||||
/**
|
||||
* 保存用户
|
||||
*/
|
||||
void saveUser(SysUserEntity user);
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
*/
|
||||
void update(SysUserEntity user);
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
void deleteBatch(Long[] userIds);
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param userId 用户ID
|
||||
* @param password 原密码
|
||||
* @param newPassword 新密码
|
||||
*/
|
||||
boolean updatePassword(Long userId, String password, String newPassword);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package io.renren.modules.sys.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import io.renren.common.utils.R;
|
||||
import io.renren.modules.sys.entity.SysUserTokenEntity;
|
||||
|
||||
/**
|
||||
* 用户Token
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface SysUserTokenService extends IService<SysUserTokenEntity> {
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
R createToken(long userId);
|
||||
|
||||
/**
|
||||
* 退出,修改token值
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void logout(long userId);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user