登录验证

This commit is contained in:
TinyAnts 2022-03-29 18:54:41 +08:00
parent 5009482aac
commit 70035875a3
43 changed files with 1460 additions and 539 deletions

View File

@ -28,11 +28,6 @@
<artifactId>like-common</artifactId>
<version>${like-common}</version>
</dependency>
<!-- Shiro鉴权依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</dependency>
</dependencies>
<!-- 插件管理 -->

View File

@ -4,15 +4,19 @@ import com.github.yulichang.injector.MPJSqlInjector;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 启动器
*/
@Configuration
@ComponentScan(basePackages = {"com.hxkj"})
@MapperScan(basePackages = {"com.hxkj.*.mapper"})
@EnableTransactionManagement
@SpringBootApplication(exclude = {MPJSqlInjector.class})
@SpringBootApplication(exclude = {MPJSqlInjector.class, RedisRepositoriesAutoConfiguration.class})
public class LikeAdminApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,118 @@
package com.hxkj.admin;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hxkj.admin.config.SystemConfig;
import com.hxkj.admin.service.ISysAdminService;
import com.hxkj.admin.service.ISysRoleMenuService;
import com.hxkj.common.core.AjaxResult;
import com.hxkj.common.enums.HttpEnum;
import com.hxkj.common.utils.RedisUtil;
import com.hxkj.common.utils.ToolsUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 拦截器
*/
@Component
public class LikeAdminInterceptor implements HandlerInterceptor {
@Resource
ISysAdminService iSysAdminService;
@Resource
ISysRoleMenuService iSysRoleMenuService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断请求接口
if (!(handler instanceof HandlerMethod)) {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
// 免登录接口
List<String> notLoginUri = Arrays.asList(SystemConfig.notLoginUri);
if (notLoginUri.contains(request.getRequestURI())) {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
// Token是否为空
response.setContentType("application/json;charset=utf-8");
String token = request.getHeader("token");
if (StringUtils.isBlank(token)) {
AjaxResult result = AjaxResult.failed(HttpEnum.TOKEN_EMPTY.getCode(), HttpEnum.TOKEN_EMPTY.getMsg());
response.getWriter().print(JSON.toJSONString(result));
return false;
}
// Token是否过期
token = SystemConfig.backstageTokenKey + token;
if (!RedisUtil.exists(token)) {
AjaxResult result = AjaxResult.failed(HttpEnum.TOKEN_INVALID.getCode(), HttpEnum.TOKEN_INVALID.getMsg());
response.getWriter().print(JSON.toJSONString(result));
return false;
}
// 用户信息缓存
String uid = RedisUtil.get(token).toString();
if (!RedisUtil.hExists(SystemConfig.backstageManageKey, uid)) {
iSysAdminService.cacheAdminUserByUid(Integer.parseInt(uid));
}
// 校验用户是否被删除
Map<String, Object> map = ToolsUtil.jsonToMap(RedisUtil.hGet(SystemConfig.backstageManageKey, uid).toString());
if (map == null || map.get("isDelete").toString().equals("1")) {
AjaxResult result = AjaxResult.failed(HttpEnum.TOKEN_INVALID.getCode(), HttpEnum.TOKEN_INVALID.getMsg());
response.getWriter().print(JSON.toJSONString(result));
return false;
}
// 校验用户是否被禁用
if (map.get("isDisable").toString().equals("1")) {
AjaxResult result = AjaxResult.failed(HttpEnum.LOGIN_DISABLE_ERROR.getCode(), HttpEnum.LOGIN_DISABLE_ERROR.getMsg());
response.getWriter().print(JSON.toJSONString(result));
return false;
}
// 免权限验证接口
List<String> notAuthUri = Arrays.asList(SystemConfig.notLoginUri);
if (notAuthUri.contains(request.getRequestURI())) {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
// 校验角色权限是否存在
String roleId = map.get("role").toString();
if (!RedisUtil.hExists(SystemConfig.backstageRolesKey, roleId)) {
iSysRoleMenuService.cacheRoleMenusByRoleId(Integer.parseInt(roleId));
}
// 验证是否有权限操作
String menus = RedisUtil.hGet(SystemConfig.backstageRolesKey, roleId).toString();
if (menus.equals("") || !Arrays.asList(menus.split(",")).contains(request.getRequestURI())) {
AjaxResult result = AjaxResult.failed(HttpEnum.NO_PERMISSION.getCode(), HttpEnum.NO_PERMISSION.getMsg());
response.getWriter().print(JSON.toJSONString(result));
return false;
}
// 写入本地线程
LikeAdminThreadLocal.put("adminId", uid);
// 验证通过继续操作
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LikeAdminThreadLocal.remove();
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

View File

@ -0,0 +1,52 @@
package com.hxkj.admin;
import java.util.LinkedHashMap;
public class LikeAdminThreadLocal {
/**
* 构造方法
*/
public LikeAdminThreadLocal() {}
/**
* 取得本地线程对象
*/
private static final java.lang.ThreadLocal<LinkedHashMap<String, Object>> MY_LOCAL = new java.lang.ThreadLocal<>();
/**
* 写入本地线程
*/
public static void put(String key, String val) {
LinkedHashMap<String, Object> map = MY_LOCAL.get();
map.put(key, val);
MY_LOCAL.set(map);
}
/**
* 获取本地线程
*/
public static Object get(String key) {
return MY_LOCAL.get().getOrDefault(key, "");
}
/**
* 获取管理员ID
*/
public static Integer getAdminId() {
String adminId = LikeAdminThreadLocal.get("adminId").toString();
if (adminId.equals("")) {
return 0;
}
return Integer.parseInt(adminId);
}
/**
* 删除本地线程
*/
public static void remove() {
MY_LOCAL.remove();
}
}

View File

@ -0,0 +1,25 @@
package com.hxkj.admin.config;
/**
* 系统配置
*/
public class SystemConfig {
// 管理缓存键
public static final String backstageManageKey = "backstage:manage";
// 角色缓存键
public static final String backstageRolesKey = "backstage:roles";
// 令牌缓存键
public static final String backstageTokenKey = "backstage:token:";
// 免登录验证
public static String[] notLoginUri = new String[]{
"/api/system/login"
};
// 免权限验证
public static String[] notAuthUri = new String[]{};
}

View File

@ -0,0 +1,47 @@
package com.hxkj.admin.config;
import com.hxkj.admin.LikeAdminInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Resource
LikeAdminInterceptor likeAdminInterceptor;
/**
* 配置允许跨域
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
/**
* 登录拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(likeAdminInterceptor).addPathPatterns("/**");
}
/**
* 资源目录映射
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:" + "");
}
}

View File

@ -1,83 +0,0 @@
package com.hxkj.admin.config.shiro;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.http.HttpStatus;
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;
public class JwtFilter extends BasicHttpAuthenticationFilter {
/**
* 对跨域提供支持
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
/**
* 判断用户是否想要登入
* 检测header里面是否包含Authorization字段即可
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String authorization = req.getHeader("Authorization");
return authorization != null;
}
/**
* 执行登录认证
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginAttempt(request, response)) {
try {
executeLogin(request, response);
return true;
} catch (Exception e) {
this.responseUnAuth(response);
return false;
}
}
return true;
}
/**
* 将非法请求跳转到 401
*/
private void responseUnAuth(ServletResponse resp) {
try {
HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
httpServletResponse.sendRedirect("/user/unauthorized");
} catch (Exception ignored) {
}
}
/**
* 过滤器,每次登陆的时候,都从Header的Authorization,
* 获取到token,然后执行登陆的操作
*/
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("Authorization");
JwtToken jwtToken = new JwtToken(token);
getSubject(request, response).login(jwtToken);
return true;
}
}

View File

@ -1,47 +0,0 @@
package com.hxkj.admin.config.shiro;
import org.apache.shiro.authc.AuthenticationToken;
/**
* 主要是为了将用户信息改为Token传递
* 重写Token,通过token方式进行验证
*/
public class JwtToken implements AuthenticationToken {
/**
* 令牌
*/
private final String token;
/**
* 构造方法
*/
public JwtToken(String token) {
super();
this.token = token;
}
/**
* 获取Token
*/
public String getToken() {
return token;
}
/**
* 获取账号
*/
@Override
public Object getPrincipal() {
return token;
}
/**
* 获取密码
*/
@Override
public Object getCredentials() {
return token;
}
}

View File

@ -1,123 +0,0 @@
package com.hxkj.admin.config.shiro;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
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.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
/**
* 过滤器注册
*/
@Bean
public FilterRegistrationBean<Filter> doFilterRegistrationBean() {
FilterRegistrationBean<Filter> filterRegistration = new FilterRegistrationBean<>();
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/");
return filterRegistration;
}
/**
* 生命周期对象
*/
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor doLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 添加注解支持
*/
@Bean
public DefaultAdvisorAutoProxyCreator doDefaultAdvisorAutoProxyCreator() {
// // 强制使用cglib防止重复代理和可能引起代理出错的问题
DefaultAdvisorAutoProxyCreator dap = new DefaultAdvisorAutoProxyCreator();
dap.setProxyTargetClass(true);
return dap;
}
/**
* 自定realm
*/
@Bean
public ShiroRealm shiroRealm() {
return new ShiroRealm();
}
/**
* 安全管理器
*/
@Bean
public DefaultWebSecurityManager doDefaultWebSecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(this.shiroRealm());
securityManager.setCacheManager(new MemoryConstrainedCacheManager());
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator evaluator = new DefaultSessionStorageEvaluator();
evaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(evaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
/**
* 权限源切面
*/
@Bean
public AuthorizationAttributeSourceAdvisor doAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
/**
* 拦截过滤器配置
* anon: 无需认证就可以访问
* authc: 必须认证了才能访问
* perms: 拥有某个资源权限才能访问
* role: 拥有某个角色权限才能访问
* @return ShiroFilterFactoryBean
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean doShiroFactoryFilterBean(DefaultWebSecurityManager securityManager) {
// 设定认证管理
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager);
// 添加自定过滤器
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("jwt", new JwtFilter());
bean.setFilters(filterMap);
// 添加授权链接
Map<String,String> chainMap = new LinkedHashMap<>();
chainMap.put("/user/add", "authc");
// chainMap.put("/user/update", "jwt");
chainMap.put("/user/login", "anon");
chainMap.put("/**", "jwt");
bean.setFilterChainDefinitionMap(chainMap);
// 返回构建配置
return bean;
}
}

View File

@ -1,73 +0,0 @@
package com.hxkj.admin.config.shiro;
import com.hxkj.admin.service.ISysAdminService;
import com.hxkj.common.utils.JwtUtil;
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 javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ShiroRealm extends AuthorizingRealm {
@Resource
ISysAdminService iSysAdminService;
/**
* 重写判断token是否是JwtToke
*
* @param token AuthenticationToken
* @return boolean
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
/**
* 授权: 根据认证数据验证用户权限
*
* @param principals 包含了所有已认证的安全数据
* @return AuthorizationInfo 授权数据
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("————权限认证————");
Set<String> perms = new HashSet<>();
Set<String> roles = new HashSet<>();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(perms);
info.addRoles(roles);
return info;
}
/**
* 认证: 校验用户名和密码是否一致
*
* @param authenticationToken token
* @return AuthenticationInfo
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
JwtToken jwtToken = (JwtToken) authenticationToken;
String token = jwtToken.getToken();
Integer userId = JwtUtil.getAudience(token);
if (userId == null || userId <= 0) {
throw new AuthenticationException("用户异常");
}
return new SimpleAuthenticationInfo(token, token, "shiroRealm");
}
}

View File

@ -3,11 +3,7 @@ package com.hxkj.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hxkj.common.entity.system.SysAdmin;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import com.hxkj.common.utils.YmlUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -18,8 +14,7 @@ public class IndexController {
@GetMapping("/user/add")
public void index() {
QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("id = 1");
System.out.println(YmlUtil.get("server.port"));
}
@ -29,24 +24,4 @@ public class IndexController {
System.out.println("小红");
}
@RequestMapping("/login")
public String login(String username, String password) {
System.out.println(username);
// 获取当前用户
Subject subject = SecurityUtils.getSubject();
// 用户登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// 执行登录方法
try {
subject.login(token);
return "登录成功";
} catch (UnknownAccountException e) {
return "用户名错误";
} catch (IncorrectCredentialsException e) {
return "密码错误";
}
}
}

View File

@ -1,13 +1,10 @@
package com.hxkj.admin.controller.system;
import com.hxkj.admin.config.shiro.JwtToken;
import com.hxkj.admin.service.ISysAdminService;
import com.hxkj.admin.service.ISysLoginService;
import com.hxkj.admin.validate.SysLoginParam;
import com.hxkj.common.core.AjaxResult;
import com.hxkj.common.entity.system.SysAdmin;
import com.hxkj.common.utils.JwtUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import com.hxkj.common.exception.LoginException;
import com.hxkj.common.exception.OperateException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -15,7 +12,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@RestController
@ -23,7 +20,7 @@ import java.util.Map;
public class SysLoginController {
@Resource
ISysAdminService iSysAdminService;
ISysLoginService iSysLoginService;
/**
* 登录系统
@ -34,24 +31,31 @@ public class SysLoginController {
*/
@PostMapping("/login")
public Object login(@Validated() @RequestBody SysLoginParam sysLoginParam) {
String username = sysLoginParam.getUsername();
String password = sysLoginParam.getPassword();
// 查询用户
SysAdmin sysAdmin = iSysAdminService.findByUsername(username);
if (sysAdmin == null || sysAdmin.getIsDelete() == 1) {
return AjaxResult.failed("账号或密码错误");
try {
Map<String, Object> map = iSysLoginService.login(sysLoginParam);
return AjaxResult.success(map);
} catch (LoginException e) {
return AjaxResult.failed(e.getCode(), e.getMsg());
} catch (OperateException e) {
return AjaxResult.failed(e.getMsg());
}
}
// 生成令牌
String tokenStr = JwtUtil.createToken(sysAdmin.getId());
JwtToken token = new JwtToken(tokenStr);
// 登录用户
Subject subject = SecurityUtils.getSubject();
subject.login(token);
return AjaxResult.success("登录成功", tokenStr);
/**
* 退出登录
*
* @author fzr
* @param request 请求接口
* @return Object
*/
@PostMapping("/logout")
public Object logout(HttpServletRequest request) {
try {
iSysLoginService.logout(request.getHeader("token"));
return AjaxResult.success();
} catch (Exception e) {
return AjaxResult.failed(e.getMessage());
}
}
}

View File

@ -10,6 +10,9 @@ import com.hxkj.common.entity.system.SysAdmin;
import java.util.Map;
/**
* 系统管理员服务
*/
public interface ISysAdminService extends BaseService<SysAdmin> {
/**
@ -63,4 +66,9 @@ public interface ISysAdminService extends BaseService<SysAdmin> {
*/
void del(Integer id);
/**
* 缓存管理员
*/
void cacheAdminUserByUid(Integer id);
}

View File

@ -0,0 +1,30 @@
package com.hxkj.admin.service;
import com.hxkj.admin.validate.SysLoginParam;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 系统登录服务
*/
public interface ISysLoginService {
/**
* 登录
*
* @author fzr
* @param sysLoginParam 登录参数
* @return token
*/
Map<String, Object> login(SysLoginParam sysLoginParam);
/**
* 退出
*
* @author fzr
* @param token 令牌
*/
void logout(String token);
}

View File

@ -5,6 +5,9 @@ import com.hxkj.admin.validate.SysMenuParam;
import com.hxkj.common.basics.BaseService;
import com.hxkj.common.entity.system.SysMenu;
/**
* 系统菜单服务
*/
public interface ISysMenuService extends BaseService<SysMenu> {
/**

View File

@ -3,6 +3,9 @@ package com.hxkj.admin.service;
import com.hxkj.common.basics.BaseService;
import com.hxkj.common.entity.system.SysRoleMenu;
/**
* 系统角色菜单服务
*/
public interface ISysRoleMenuService extends BaseService<SysRoleMenu> {
/**
@ -23,4 +26,12 @@ public interface ISysRoleMenuService extends BaseService<SysRoleMenu> {
*/
void batchDeleteByRoleId(Integer roleId);
/**
* 缓存角色菜单
*
* @author fzr
* @param roleId 角色ID
*/
void cacheRoleMenusByRoleId(Integer roleId);
}

View File

@ -8,6 +8,9 @@ import com.hxkj.common.core.PageResult;
import com.hxkj.common.entity.system.SysRole;
import org.springframework.validation.annotation.Validated;
/**
* 系统角色服务
*/
public interface ISysRoleService extends BaseService<SysRole> {
/**

View File

@ -1,10 +1,12 @@
package com.hxkj.admin.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.hxkj.admin.config.SystemConfig;
import com.hxkj.admin.service.ISysAdminService;
import com.hxkj.admin.service.ISysRoleService;
import com.hxkj.admin.validate.PageParam;
@ -14,6 +16,7 @@ import com.hxkj.admin.vo.system.SysAdminListVo;
import com.hxkj.common.core.PageResult;
import com.hxkj.common.entity.system.SysAdmin;
import com.hxkj.common.mapper.system.SysAdminMapper;
import com.hxkj.common.utils.RedisUtil;
import com.hxkj.common.utils.TimeUtil;
import com.hxkj.common.utils.ToolsUtil;
import com.hxkj.common.utils.UrlUtil;
@ -78,9 +81,9 @@ public class ISysAdminServiceImpl extends MPJBaseServiceImpl<SysAdminMapper, Sys
BeanUtils.copyProperties(sysAdmin, vo);
vo.setRole(iSysRoleService.getRoleNameById(sysAdmin.getRole()));
vo.setCreateTime(TimeUtil.timeToDate(sysAdmin.getCreateTime()));
vo.setUpdateTime(TimeUtil.timeToDate(sysAdmin.getUpdateTime()));
vo.setLastLoginTime(TimeUtil.timeToDate(sysAdmin.getLastLoginTime()));
vo.setCreateTime(TimeUtil.timestampToDate(sysAdmin.getCreateTime()));
vo.setUpdateTime(TimeUtil.timestampToDate(sysAdmin.getUpdateTime()));
vo.setLastLoginTime(TimeUtil.timestampToDate(sysAdmin.getLastLoginTime()));
adminVoArrayList.add(vo);
}
@ -218,4 +221,29 @@ public class ISysAdminServiceImpl extends MPJBaseServiceImpl<SysAdminMapper, Sys
this.updateById(model);
}
/**
* 缓存管理员
*/
@Override
public void cacheAdminUserByUid(Integer id) {
SysAdmin sysAdmin = this.getById(id);
Map<String, Object> user = new LinkedHashMap<>();
Map<String, Object> map = new LinkedHashMap<>();
user.put("id", sysAdmin.getId());
user.put("role", sysAdmin.getRole());
user.put("username", sysAdmin.getUsername());
user.put("nickname", sysAdmin.getNickname());
user.put("avatar", sysAdmin.getAvatar());
user.put("isDisable", sysAdmin.getIsDisable());
user.put("isDelete", sysAdmin.getIsDelete());
user.put("lastLoginIp", sysAdmin.getLastLoginIp());
user.put("lastLoginTime", TimeUtil.timestampToDate(sysAdmin.getLastLoginTime()));
user.put("createTime", TimeUtil.timestampToDate(sysAdmin.getCreateTime()));
user.put("updateTime", TimeUtil.timestampToDate(sysAdmin.getUpdateTime()));
map.put(String.valueOf(sysAdmin.getId()), JSON.toJSONString(user));
RedisUtil.hmSet(SystemConfig.backstageManageKey, map);
}
}

View File

@ -0,0 +1,90 @@
package com.hxkj.admin.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.hxkj.admin.config.SystemConfig;
import com.hxkj.admin.service.ISysAdminService;
import com.hxkj.admin.service.ISysLoginService;
import com.hxkj.admin.validate.SysLoginParam;
import com.hxkj.common.entity.system.SysAdmin;
import com.hxkj.common.enums.HttpEnum;
import com.hxkj.common.exception.LoginException;
import com.hxkj.common.exception.OperateException;
import com.hxkj.common.mapper.system.SysAdminMapper;
import com.hxkj.common.utils.HttpUtil;
import com.hxkj.common.utils.RedisUtil;
import com.hxkj.common.utils.TimeUtil;
import com.hxkj.common.utils.ToolsUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Service
public class ISysLoginServiceImpl implements ISysLoginService {
@Resource
SysAdminMapper sysAdminMapper;
@Resource
ISysAdminService iSysAdminService;
/**
* 登录
*
* @author fzr
* @param sysLoginParam 登录参数
* @return token
*/
@Override
public Map<String, Object> login(SysLoginParam sysLoginParam) {
String username = sysLoginParam.getUsername();
String password = sysLoginParam.getPassword();
SysAdmin sysAdmin = iSysAdminService.findByUsername(username);
if (sysAdmin == null || sysAdmin.getIsDelete() == 1) {
throw new LoginException(HttpEnum.LOGIN_ACCOUNT_ERROR.getCode(), HttpEnum.LOGIN_ACCOUNT_ERROR.getMsg());
}
if (sysAdmin.getIsDisable() == 1) {
throw new LoginException(HttpEnum.LOGIN_DISABLE_ERROR.getCode(), HttpEnum.LOGIN_DISABLE_ERROR.getMsg());
}
String newPWd = password + sysAdmin.getId() + sysAdmin.getSalt();
String md5Pwd = ToolsUtil.makeMd5(newPWd);
if (!md5Pwd.equals(sysAdmin.getPassword())) {
throw new LoginException(HttpEnum.LOGIN_ACCOUNT_ERROR.getCode(), HttpEnum.LOGIN_ACCOUNT_ERROR.getMsg());
}
try {
sysAdmin.setLastLoginIp(HttpUtil.ip());
sysAdmin.setLastLoginTime(System.currentTimeMillis() / 1000);
sysAdminMapper.updateById(sysAdmin);
String token = ToolsUtil.makeToken();
RedisUtil.set(SystemConfig.backstageTokenKey+token, sysAdmin.getId(), 7200);
iSysAdminService.cacheAdminUserByUid(sysAdmin.getId());
Map<String, Object> response = new LinkedHashMap<>();
response.put("token", token);
return response;
} catch (Exception e) {
throw new OperateException(e.getMessage());
}
}
/**
* 退出
*
* @author fzr
* @param token 令牌
*/
@Override
public void logout(String token) {
RedisUtil.del(SystemConfig.backstageTokenKey + token);
}
}

View File

@ -43,8 +43,8 @@ public class ISysMenuServiceImpl extends MPJBaseServiceImpl<SysMenuMapper, SysMe
SysMenuListVo vo = new SysMenuListVo();
BeanUtils.copyProperties(sysMenu, vo);
vo.setCreateTime(TimeUtil.timeToDate(sysMenu.getCreateTime()));
vo.setUpdateTime(TimeUtil.timeToDate(sysMenu.getUpdateTime()));
vo.setCreateTime(TimeUtil.timestampToDate(sysMenu.getCreateTime()));
vo.setUpdateTime(TimeUtil.timestampToDate(sysMenu.getUpdateTime()));
lists.add(vo);
}

View File

@ -2,17 +2,27 @@ package com.hxkj.admin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.hxkj.admin.config.SystemConfig;
import com.hxkj.admin.service.ISysRoleMenuService;
import com.hxkj.common.entity.system.SysMenu;
import com.hxkj.common.entity.system.SysRoleMenu;
import com.hxkj.common.mapper.system.SysMenuMapper;
import com.hxkj.common.mapper.system.SysRoleMenuMapper;
import com.hxkj.common.utils.RedisUtil;
import com.hxkj.common.utils.ToolsUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@Service
public class ISysRoleMenuServiceImpl extends MPJBaseServiceImpl<SysRoleMenuMapper, SysRoleMenu> implements ISysRoleMenuService {
@Resource
SysMenuMapper sysMenuMapper;
/**
* 批量写入角色菜单
*
@ -46,4 +56,34 @@ public class ISysRoleMenuServiceImpl extends MPJBaseServiceImpl<SysRoleMenuMappe
this.remove(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
}
/**
* 缓存角色菜单
*
* @author fzr
* @param roleId 角色ID
*/
@Override
public void cacheRoleMenusByRoleId(Integer roleId) {
List<Integer> menuIds = new LinkedList<>();
List<String> menuArray = new LinkedList<>();
List<SysRoleMenu> sysRoleMenus = this.list(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
for (SysRoleMenu sysRoleMenu : sysRoleMenus) {
menuIds.add(sysRoleMenu.getMenuId());
}
if (menuIds.size() > 0) {
List<SysMenu> sysMenus = sysMenuMapper.selectList(new QueryWrapper<SysMenu>()
.select("id,perms")
.in("id", menuIds)
.eq("is_disable", 0));
for (SysMenu sysMenu : sysMenus) {
menuArray.add(sysMenu.getPerms().trim());
}
}
RedisUtil.hSet(SystemConfig.backstageRolesKey, String.valueOf(roleId), ToolsUtil.listStrToString(menuArray, ","));
}
}

View File

@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.hxkj.admin.service.ISysMenuService;
import com.hxkj.admin.service.ISysRoleMenuService;
import com.hxkj.admin.service.ISysRoleService;
import com.hxkj.admin.validate.PageParam;
@ -13,7 +12,6 @@ import com.hxkj.admin.validate.SysRoleParam;
import com.hxkj.admin.vo.system.SysRoleListVo;
import com.hxkj.common.core.PageResult;
import com.hxkj.common.entity.system.SysRole;
import com.hxkj.common.mapper.system.SysMenuMapper;
import com.hxkj.common.mapper.system.SysRoleMapper;
import com.hxkj.common.utils.TimeUtil;
import org.springframework.beans.BeanUtils;
@ -79,8 +77,8 @@ public class ISysRoleServiceImpl extends MPJBaseServiceImpl<SysRoleMapper, SysRo
SysRoleListVo vo = new SysRoleListVo();
BeanUtils.copyProperties(sysRole, vo);
vo.setCreateTime(TimeUtil.timeToDate(sysRole.getCreateTime()));
vo.setUpdateTime(TimeUtil.timeToDate(sysRole.getUpdateTime()));
vo.setCreateTime(TimeUtil.timestampToDate(sysRole.getCreateTime()));
vo.setUpdateTime(TimeUtil.timestampToDate(sysRole.getUpdateTime()));
roleVoArrayList.add(vo);
}

View File

@ -28,6 +28,19 @@ spring:
max-file-size: 100MB # 文件上传大小限制
max-request-size: 100MB # 文件最大请求限制
enabled: true
# Redis配置
redis:
host: localhost # Redis服务地址
port: 6379 # Redis端口
password: # Redis密码
database: 0 # 数据库索引
timeout: 5000 # 连接超时
lettuce:
pool:
max-wait: 30000 # 连接池最大阻塞等待时间(使用负数表示没有限制,默认-1)
max-active: 100 # 连接池最大连接数(使用负数表示没有限制,默认8)
max-idle: 20 # 连接池中的最大空闲连接(默认8)
min-idle: 0 # 连接池中的最小空闲连接(默认0)
# Mybatis-plus配置
mybatis-plus:

View File

@ -22,6 +22,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- Processor依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -37,6 +42,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Mysql连接依赖 -->
<dependency>
<groupId>mysql</groupId>
@ -67,10 +77,17 @@
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- JWT -->
<!-- 通用池 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.10.0</version>
</dependency>
<!-- gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>

View File

@ -0,0 +1,23 @@
package com.hxkj.common.config;
/**
* 全局配置
*/
public class GlobalConfig {
// 开启调试模式
public static Boolean debug = true;
// 当前代码版本
public static String version = "v1.1.0";
// 系统加密字符
public static String secret = "UVTIyzCy";
// Redis键前缀
public static String redisPrefix = "Like:";
// 资源访问前缀
public static String publicPrefix = "uploads";
}

View File

@ -0,0 +1,31 @@
package com.hxkj.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis配置
*/
@Configuration
public class RedisConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setValueSerializer(JsonRedisSerializer);
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(JsonRedisSerializer);
return redisTemplate;
}
}

View File

@ -16,10 +16,7 @@ public class SysRoleMenu implements Serializable {
private static final long serialVersionUID = 1L;
// 角色ID
private Integer roleId;
// 菜单ID
private Integer menuId;
}

View File

@ -5,14 +5,19 @@ public enum HttpEnum {
SUCCESS(200, "成功"),
FAILED(300, "失败"),
PARAMS_VALID_ERROR(310, "参数校验错误"),
PARAMS_TYPE_ERROR(320, "参数类型错误"),
REQUEST_METHOD_ERROR(330, "请求方法错误"),
ASSERT_ARGUMENT_ERROR(340, "断言参数错误"),
ASSERT_MYBATIS_ERROR(350, "断言Mybatis错误"),
NO_TOKEN(401, "token参数为空"),
NO_LOGIN(402, "token参数无效"),
PARAMS_TYPE_ERROR(311, "参数类型错误"),
REQUEST_METHOD_ERROR(312, "请求方法错误"),
ASSERT_ARGUMENT_ERROR(313, "断言参数错误"),
ASSERT_MYBATIS_ERROR(314, "断言Mybatis错误"),
LOGIN_ACCOUNT_ERROR(330, "登录账号或密码错误"),
LOGIN_DISABLE_ERROR(331, "登录账号已被禁用了"),
TOKEN_EMPTY(332, "token参数为空"),
TOKEN_INVALID(333, "token参数无效"),
NO_PERMISSION(403, "无相关权限"),
NOT_DATA(404, "无相关数据"),
SYSTEM_ERROR(500, "系统错误");
/**

View File

@ -0,0 +1,21 @@
package com.hxkj.common.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 异常基类
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class BaseException extends RuntimeException {
private Integer code;
private String msg;
public BaseException(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}

View File

@ -3,7 +3,6 @@ package com.hxkj.common.exception;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.hxkj.common.core.AjaxResult;
import com.hxkj.common.enums.HttpEnum;
import com.hxkj.common.utils.ThrowableUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;

View File

@ -0,0 +1,12 @@
package com.hxkj.common.exception;
/**
* 登录异常类
*/
public class LoginException extends BaseException {
public LoginException(Integer code, String msg) {
super(code, msg);
}
}

View File

@ -0,0 +1,14 @@
package com.hxkj.common.exception;
import com.hxkj.common.enums.HttpEnum;
/**
* 操作系统异常
*/
public class OperateException extends BaseException {
public OperateException(String msg) {
super(HttpEnum.FAILED.getCode(), msg);
}
}

View File

@ -3,6 +3,9 @@ package com.hxkj.common.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
/**
* 数组工具类
*/
public class ArrayUtil {
/**

View File

@ -1,4 +1,7 @@
package com.hxkj.common.utils;
/**
* 数据库配置操作工具
*/
public class ConfigUtil {
}

View File

@ -41,6 +41,20 @@ public class HttpUtil {
return null;
}
/**
* 获取请求路由
*
* @author fzr
* @return String
*/
public static String route() {
HttpServletRequest request = HttpUtil.obj();
if (request != null) {
return request.getRequestURI();
}
return null;
}
/**
* 获取请求域名
*

View File

@ -1,94 +0,0 @@
package com.hxkj.common.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
public class JwtUtil {
/**
* 过期时间()
*/
private static final Integer expire = 7200;
/**
* 加密密钥
*/
private static final String secret = "EEE";
/**
* 请求头字段名
*/
private static final String header = "token";
/**
* 创建token
*
* @author fzr
* @param userId 用户ID
*/
public static String createToken(Integer userId) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, expire);
return JWT.create()
.withAudience(String.valueOf(userId)) // 签发对象
.withIssuedAt(new Date()) // 发行时间
.withExpiresAt(instance.getTime()) // 有效时间
.withClaim("userId", userId) // 载荷
.sign(Algorithm.HMAC256(secret)); // 加密
}
/**
* 检验合法性
*
* @param token 令牌
*/
public static void verifyToken(String token) {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
verifier.verify(token);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 获取签发对象
*
* @param token 令牌
* @return userId
*/
public static Integer getAudience(String token) {
Integer audience = null;
try {
audience = Integer.parseInt(JWT.decode(token).getAudience().get(0));
} catch (JWTDecodeException j) {
System.out.println(j.getMessage());
}
return audience;
}
/**
* 通过载荷名字获取载荷的值
*
* @param token 令牌
* @param name 载荷名称
* @return Claim
*/
public static Claim getClaimByName(String token, String name){
return JWT.decode(token).getClaim(name);
}
}

View File

@ -1,4 +1,634 @@
package com.hxkj.common.utils;
import com.hxkj.common.config.GlobalConfig;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
private static RedisTemplate<String, Object> redisTemplate;
private static final String redisPrefix = GlobalConfig.redisPrefix;
/**
* 注入Redis
*
* @author fzr
* @param redisTemplate Redis对象
*/
@Resource
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
RedisUtil.redisTemplate = redisTemplate;
}
/**
* 对象句柄
*
* @author fzr
* @return RedisTemplate
*/
public static RedisTemplate<String, Object> handler() {
return redisTemplate;
}
/**
* 指定缓存失效时间
*
* @author fzr
* @param key
* @param second 时间()
*/
public static void expire(String key, Long second) {
key = redisPrefix + key;
redisTemplate.expire(key, second, TimeUnit.SECONDS);
}
/**
* 指定缓存失效时间
*
* @author fzr
* @param key
* @param millisecond 时间(毫秒)
*/
public static void pExpire(String key, Long millisecond) {
key = redisPrefix + key;
redisTemplate.expire(key, millisecond, TimeUnit.MILLISECONDS);
}
/**
* 指定缓存永久有效
*
* @author fzr
* @param key
*/
public static void persist(String key) {
key = redisPrefix + key;
redisTemplate.persist(key);
}
/**
* 根据key获取过期时间
*
* @author fzr
* @param key 键不能为null
* @return 返回0代表为永久有效()
*/
public static Long ttl(String key) {
key = redisPrefix + key;
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 根据key获取过期时间
*
* @author fzr
* @param key 键不能为null
* @return 返回0代表为永久有效(毫秒)
*/
public static Long pTtl(String key) {
key = redisPrefix + key;
return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
}
/**
* 判断key是否存在
*
* @author fzr
* @param key
* @return true=存在,false=不存在
*/
public static Boolean exists(String key) {
key = redisPrefix + key;
return redisTemplate.hasKey(key);
}
/**
* 删除1个或多个键
*
* @author fzr
* @param key (一个或多个)
*/
@SuppressWarnings("unchecked")
public static void del(String... key) {
if (key.length == 1) {
key[0] = redisPrefix + key[0];
redisTemplate.delete(key[0]);
} else {
for (int i=0; key.length > i; i++) {
key[i] = redisPrefix + key[i];
}
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
/**
* 给key赋值一个新的key名
*
* @author fzr
* @param oldKey 旧的key
* @param newKey 新的key
*/
public static void rename(String oldKey, String newKey) {
oldKey = redisPrefix + oldKey;
newKey = redisPrefix + newKey;
redisTemplate.rename(oldKey, newKey);
}
/**
* 将当前数据库的key移动到给定的数据库db当中
*
* @author fzr
* @param key
* @param db
* @return Boolean
*/
public static Boolean move(String key, int db) {
key = redisPrefix + key;
return redisTemplate.move(key, db);
}
/**
* 获取匹配的key值
*
* @author fzr
* @author fzr
* @param pattern 通配符(*, ?, [])
* @return Set
*/
public static Set<String> keys(String pattern) {
return redisTemplate.keys(pattern);
}
/**
* 随机返回一个key
*
* @author fzr
* @author fzr
* @return String
*/
public static String randomKey() {
return redisTemplate.randomKey();
}
/* ***************** common end *************** */
/**
* 获取key的值
*
* @author fzr
* @param key
* @return Object
*/
public static Object get(String key) {
key = redisPrefix + key;
return redisTemplate.opsForValue().get(key);
}
/**
* 获取旧值并设置新值
*
* @author fzr
* @param key
* @param newVal 新值
* @return Object
*/
public static Object getSet(String key, Object newVal) {
key = redisPrefix + key;
return redisTemplate.opsForValue().getAndSet(key, newVal);
}
/**
* 设置键值对
*
* @author fzr
* @param key
* @param value
*/
public static void set(String key, Object value) {
key = redisPrefix + key;
redisTemplate.opsForValue().set(key, value);
}
/**
* 设置键值对并设置时间
*
* @author fzr
* @param key
* @param value
* @param time time要大于0 如果time小于等于0 将设置无限期
*/
public static void set(String key, Object value, long time) {
key = redisPrefix + key;
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
}
/**
* 递增
*
* @author fzr
* @param key
* @param delta 要增加几(大于0)
* @return Long
*/
public static Long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
key = redisPrefix + key;
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @author fzr
* @param key
* @param delta 要减少几(小于0)
* @return Long
*/
public static Long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
key = redisPrefix + key;
return redisTemplate.opsForValue().increment(key, -delta);
}
/* ***************** String end *************** */
/**
* 获取key中field域的值
*
* @author fzr
* @param key 不能为null
* @param field 不能为null
* @return
*/
public static Object hGet(String key, String field) {
key = redisPrefix + key;
return redisTemplate.opsForHash().get(key, field);
}
/**
* 判断key中有没有field域名
*
* @author fzr
* @param key
* @param field 字段
* @return Boolean
*/
public static Boolean hExists(String key, Object field) {
key = redisPrefix + key;
return redisTemplate.opsForHash().hasKey(key, field);
}
/**
* 获取hashKey对应的所有键值
*
* @author fzr
* @param key
* @return 对应的多个键值
*/
public Map<Object, Object> hmGet(String key) {
key = redisPrefix + key;
return redisTemplate.opsForHash().entries(key);
}
/**
* 设置field1->N个域,对应的值是value1->N
*
* @author fzr
* @param key
* @param map 对应多个键值
*/
public static void hmSet(String key, Map<String, Object> map) {
key = redisPrefix + key;
redisTemplate.opsForHash().putAll(key, map);
}
/**
* HashSet 并设置时间
*
* @author fzr
* @param key
* @param map 对应多个键值
* @param time 时间()
*/
public static void hmSet(String key, Map<String, Object> map, long time) {
key = redisPrefix + key;
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @author fzr
* @param key
* @param item
* @param value
* @return true 成功 false失败
*/
public static void hSet(String key, String item, Object value) {
key = redisPrefix + key;
redisTemplate.opsForHash().put(key, item, value);
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @author fzr
* @param key
* @param item
* @param value
* @param time 时间() 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public static boolean hSet(String key, String item, Object value, long time) {
key = redisPrefix + key;
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
}
/**
* 删除hash表中的值
*
* @author fzr
* @param key 不能为null
* @param item 可以使多个 不能为null
*/
public static void hDel(String key, Object... item) {
key = redisPrefix + key;
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @author fzr
* @param key 不能为null
* @param item 不能为null
* @return true 存在 false不存在
*/
public static boolean hHasKey(String key, String item) {
key = redisPrefix + key;
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个并把新增后的值返回
*
* @author fzr
* @param key
* @param item
* @param by 要增加几(大于0)
* @return double
*/
public static double hIncr(String key, String item, long by) {
key = redisPrefix + key;
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @author fzr
* @param key
* @param item
* @param by 要减少记(小于0)
* @return double
*/
public static double hDecr(String key, String item, long by) {
key = redisPrefix + key;
return redisTemplate.opsForHash().increment(key, item, -by);
}
/* ***************** Map end *************** */
/**
* 根据key获取Set中的所有值
*
* @author fzr
* @param key
* @return Set
*/
public static Set<Object> sGet(String key) {
key = redisPrefix + key;
return redisTemplate.opsForSet().members(key);
}
/**
* 根据value从一个set中查询,是否存在
*
* @author fzr
* @param key
* @param value
* @return true 存在 false不存在
*/
public Boolean sHasKey(String key, Object value) {
key = redisPrefix + key;
return redisTemplate.opsForSet().isMember(key, value);
}
/**
* 将数据放入set缓存
*
* @author fzr
* @param key
* @param values 可以是多个
* @return 成功个数
*/
public Long sSet(String key, Object... values) {
key = redisPrefix + key;
return redisTemplate.opsForSet().add(key, values);
}
/**
* 将set数据放入缓存
*
* @author fzr
* @param key
* @param time 时间()
* @param values 可以是多个
* @return 成功个数
*/
public Long sSetAndTime(String key, long time, Object... values) {
key = redisPrefix + key;
return redisTemplate.opsForSet().add(key, values);
}
/**
* 获取set缓存的长度
*
* @author fzr
* @param key
* @return Long
*/
public Long sGetSetSize(String key) {
key = redisPrefix + key;
return redisTemplate.opsForSet().size(key);
}
/**
* 移除值为value的
*
* @author fzr
* @param key
* @param values 可以是多个
* @return 移除的个数
*/
public Long setRemove(String key, Object... values) {
key = redisPrefix + key;
return redisTemplate.opsForSet().remove(key, values);
}
/* ***************** Set end *************** */
/**
* 获取list缓存的内容
*
* @author fzr
* @param key
* @param start 开始
* @param end 结束 0 -1代表所有值
* @return List
*/
public List<Object> lGet(String key, long start, long end) {
key = redisPrefix + key;
return redisTemplate.opsForList().range(key, start, end);
}
/**
* 获取list缓存的长度
*
* @author fzr
* @param key
* @return Long
*/
public Long lGetListSize(String key) {
key = redisPrefix + key;
return redisTemplate.opsForList().size(key);
}
/**
* 通过索引获取list中的值
*
* @author fzr
* @param key
* @param index 索引 index>=0时,0 表头1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素依次类推
* @return Object
*/
public Object lGetIndex(String key, long index) {
key = redisPrefix + key;
return redisTemplate.opsForList().index(key, index);
}
/**
* 将list放入缓存
*
* @author fzr
* @param key
* @param value
* @return boolean
*/
public boolean lSet(String key, Object value) {
key = redisPrefix + key;
redisTemplate.opsForList().rightPush(key, value);
return true;
}
/**
* 将list放入缓存
*
* @author fzr
* @param key
* @param value
* @param second 时间()
* @return boolean
*/
public boolean lSet(String key, Object value, long second) {
key = redisPrefix + key;
redisTemplate.opsForList().rightPush(key, value);
if (second > 0)
expire(key, second);
return true;
}
/**
* 将list放入缓存
*
* @author fzr
* @param key
* @param value
* @return boolean
*/
public boolean lSet(String key, List<Object> value) {
key = redisPrefix + key;
redisTemplate.opsForList().rightPushAll(key, value);
return true;
}
/**
* 将list放入缓存
*
* @author fzr
* @param key
* @param value
* @param time 时间()
* @return boolean
*/
public boolean lSet(String key, List<Object> value, Long time) {
key = redisPrefix + key;
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
}
/**
* 根据索引修改list中的某条数据
*
* @author fzr
* @param key
* @param index 索引
* @param value
* @return boolean
*/
public boolean lUpdateIndex(String key, Long index, Object value) {
key = redisPrefix + key;
redisTemplate.opsForList().set(key, index, value);
return true;
}
/**
* 移除N个值为value
*
* @author fzr
* @param key
* @param count 移除多少个
* @param value
* @return 移除的个数
*/
public Long lRemove(String key, Long count, Object value) {
key = redisPrefix + key;
return redisTemplate.opsForList().remove(key, count, value);
}
}

View File

@ -1,26 +0,0 @@
package com.hxkj.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 异常工具类
*/
public class ThrowableUtil {
/**
* 获取堆栈信息
*
* @author fzr
* @param throwable 异常
* @return String
*/
public static String getStackTrace(Throwable throwable) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
throwable.printStackTrace(pw);
return sw.toString();
}
}
}

View File

@ -11,19 +11,23 @@ public class TimeUtil {
/**
* 时间戳转日期(默认格式)
*
* @author fzr
* @param time 时间戳
* @return String
*/
public static String timeToDate(long time) {
public static String timestampToDate(Long time) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000));
}
/**
* 时间戳转日期(默认格式)
*
* @author fzr
* @param time 时间戳
* @return String
*/
public static String timeToDate(String time) {
public static String timestampToDate(String time) {
if (time == null) {
time = "0";
}
@ -33,36 +37,45 @@ public class TimeUtil {
/**
* 时间戳转日期(指定格式)
*
* @author fzr
* @param time 时间戳
* @param format 格式串
* @return String
*/
public static String timeToDate(long time, String format) {
public static String timestampToDate(Long time, String format) {
return new SimpleDateFormat(format).format(new Date(time * 1000));
}
/**
* 时间戳转日期(指定格式)
*
* @author fzr
* @param time 时间戳
* @param format 格式串
* @return String
*/
public static String timeToDate(String time, String format) {
public static String timestampToDate(String time, String format) {
long longTime = Long.parseLong(time);
return new SimpleDateFormat(format).format(new Date(longTime * 1000));
}
/**
* 日期转时间戳
*
* @author fzr
* @param date 日期
* @return Long
*/
public static Long dateToTime(String date) {
public static Long dateToTimestamp(String date) {
String dateTime = TimeUtil.formatDate(date);
return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(dateTime, new ParsePosition(0)).getTime() / 1000;
}
/**
* 毫秒转日期时间
*
* @author fzr
* @param time 毫秒
* @return String
*/
@ -74,6 +87,8 @@ public class TimeUtil {
/**
* 毫秒转日期时间
*
* @author fzr
* @param time 毫秒
* @return String
*/
@ -85,7 +100,10 @@ public class TimeUtil {
/**
* 毫秒转日期时间
*
* @author fzr
* @param time 毫秒
* @param format 格式串
* @return String
*/
public static String millisecondToDate(Long time, String format) {
@ -96,7 +114,10 @@ public class TimeUtil {
/**
* 毫秒转日期时间
*
* @author fzr
* @param time 毫秒
* @param format 格式串
* @return String
*/
public static String millisecondToDate(String time, String format) {
@ -107,6 +128,7 @@ public class TimeUtil {
/**
* 日期转固定格式 yyyy-MM-dd HH:mm:ss
*
* @author fzr
* @param dateStr 日期时间
* @return String
@ -159,15 +181,17 @@ public class TimeUtil {
/**
* 返回当前时间戳
*
* @author fzr
* @return Long
*/
public static Long time() {
public static Long timestamp() {
return System.currentTimeMillis() / 1000;
}
/**
* 返回今日开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -194,6 +218,7 @@ public class TimeUtil {
/**
* 返回昨日开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -207,6 +232,7 @@ public class TimeUtil {
/**
* 返回本周开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -224,6 +250,7 @@ public class TimeUtil {
/**
* 返回上周开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -237,6 +264,7 @@ public class TimeUtil {
/**
* 返回今天是周几
*
* @author fzr
* @return Long
*/
@ -254,6 +282,7 @@ public class TimeUtil {
/**
* 返回本月开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -276,6 +305,7 @@ public class TimeUtil {
/**
* 返回上个月开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -301,6 +331,7 @@ public class TimeUtil {
/**
* 返回今年开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -334,6 +365,7 @@ public class TimeUtil {
/**
* 返回去年开始和结束的时间戳
*
* @author fzr
* @return List
*/
@ -364,6 +396,7 @@ public class TimeUtil {
/**
* 获取几天前零点到现在/昨日结束的时间戳
*
* @author fzr
* @return List
*/
@ -377,6 +410,7 @@ public class TimeUtil {
/**
* 返回几天前的时间戳
*
* @author fzr
* @param day ()
* @return Long
@ -388,6 +422,7 @@ public class TimeUtil {
/**
* 返回几天后的时间戳
*
* @author fzr
* @param day ()
* @return Long
@ -399,6 +434,7 @@ public class TimeUtil {
/**
* 返回月份第几天
*
* @author fzr
* @return int
*/

View File

@ -1,10 +1,23 @@
package com.hxkj.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.reflect.TypeToken;
import com.hxkj.common.config.GlobalConfig;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Random;
import java.util.UUID;
import java.util.*;
/**
* 常用工具集合
*/
public class ToolsUtil {
/**
@ -33,12 +46,25 @@ public class ToolsUtil {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
}catch (Exception e){
} catch (Exception e) {
e.printStackTrace();
}
return null;
return "";
}
/**
* 生成唯一Token
*
* @author fzr
* @return String
*/
public static String makeToken() {
long millisecond = System.currentTimeMillis();
String randStr = ToolsUtil.randomString(8);
String secret = GlobalConfig.secret;
String token = ToolsUtil.makeMd5(ToolsUtil.makeUUID() + millisecond + randStr);
return ToolsUtil.makeMd5(token + secret) + ToolsUtil.randomString(6);
}
/**
* 返回随机字符串
@ -77,4 +103,48 @@ public class ToolsUtil {
return stringBuffer.toString();
}
/**
* JSON转map
*
* @author fzr
* @param json 对象
* @return Map
*/
public static Map<String, Object> jsonToMap(String json){
Type type = new TypeToken<Map<String, Object>>() {}.getType();
return JSON.parseObject(json, type);
}
/**
* 列表转字符串
*
* @author fzr
* @param list 列表
* @param separator 分割符号
* @return String
*/
public static String listToString(List<Long> list, String separator) {
StringBuilder sb = new StringBuilder();
for (Object o : list) {
sb.append(o).append(separator);
}
return list.isEmpty() ? "" : sb.substring(0, sb.toString().length() - 1);
}
/**
* 列表转字符串
*
* @author fzr
* @param list 列表
* @param separator 分割符号
* @return String
*/
public static String listStrToString(List<String> list, String separator) {
StringBuilder sb = new StringBuilder();
for (Object o : list) {
sb.append(o).append(separator);
}
return list.isEmpty() ? "" : sb.substring(0, sb.toString().length() - 1);
}
}

View File

@ -1,5 +1,8 @@
package com.hxkj.common.utils;
/**
* 文件路径处理工具
*/
public class UrlUtil {
/**

View File

@ -0,0 +1,37 @@
package com.hxkj.common.utils;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
/**
* 系统文件配置操作工具
*/
@Component
public class YmlUtil implements EnvironmentAware {
private static Environment env;
/**
* 设置环境变量
*
* @author fzr
* @param environment 环境变量
*/
@Override
public void setEnvironment(Environment environment) {
YmlUtil.env = environment;
}
/**
* 根据Key获取值
*
* @author fzr
* @param key
* @return String
*/
public static String get(String key) {
return env.getProperty(key);
}
}

16
pom.xml
View File

@ -30,6 +30,8 @@
<lombok.version>1.18.22</lombok.version>
<fastJson.version>1.2.78</fastJson.version>
<java-jwt.version>3.18.2</java-jwt.version>
<apache-commons.version>2.10.0</apache-commons.version>
<gson.version>2.9.0</gson.version>
</properties>
<!-- 依赖声明 -->
@ -85,11 +87,17 @@
<artifactId>fastjson</artifactId>
<version>${fastJson.version}</version>
</dependency>
<!-- Jwt -->
<!-- 通用池 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${java-jwt.version}</version>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${apache-commons.version}</version>
</dependency>
<!-- gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>