New file |
| | |
| | | package com.mes.common.config; |
| | | |
| | | import com.mes.common.utils.FastJsonRedisSerializer; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.data.redis.connection.RedisConnectionFactory; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.data.redis.serializer.StringRedisSerializer; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/9 19:13 |
| | | * @Description: |
| | | */ |
| | | @Configuration |
| | | public class RedisConfig { |
| | | |
| | | @Bean |
| | | @SuppressWarnings(value = {"unchecked", "rawtypes"}) |
| | | public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { |
| | | RedisTemplate<Object, Object> template = new RedisTemplate<>(); |
| | | template.setConnectionFactory(connectionFactory); |
| | | |
| | | FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class); |
| | | |
| | | // 使用StringRedisSerializer来序列化和反序列化redis的key值 |
| | | template.setKeySerializer(new StringRedisSerializer()); |
| | | template.setValueSerializer(serializer); |
| | | |
| | | // Hash的key也采用StringRedisSerializer的序列化方式 |
| | | template.setHashKeySerializer(new StringRedisSerializer()); |
| | | template.setHashValueSerializer(serializer); |
| | | |
| | | template.afterPropertiesSet(); |
| | | return template; |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.config; |
| | | |
| | | |
| | | import com.mes.common.filter.JwtAuthenticationTokenFilter; |
| | | import com.mes.common.handler.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.security.authentication.AuthenticationManager; |
| | | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; |
| | | import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
| | | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
| | | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
| | | import org.springframework.security.config.http.SessionCreationPolicy; |
| | | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
| | | import org.springframework.security.crypto.password.PasswordEncoder; |
| | | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
| | | |
| | | @Configuration |
| | | @EnableWebSecurity |
| | | @EnableGlobalMethodSecurity(prePostEnabled = true) |
| | | public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter { |
| | | @Autowired |
| | | private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; |
| | | @Autowired |
| | | LoginFailureHandler loginFailureHandler; |
| | | |
| | | @Autowired |
| | | LoginSuccessHandler loginSuccessHandler; |
| | | |
| | | @Autowired |
| | | JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; |
| | | |
| | | @Autowired |
| | | JwtAccessDeniedHandler jwtAccessDeniedHandler; |
| | | |
| | | @Autowired |
| | | JwtLogoutSuccessHandler jwtLogoutSuccessHandler; |
| | | |
| | | @Bean |
| | | public PasswordEncoder passwordEncoder() { |
| | | return new BCryptPasswordEncoder(); |
| | | } |
| | | |
| | | /** |
| | | * 配置过滤规则 |
| | | */ |
| | | @Override |
| | | protected void configure(HttpSecurity http) throws Exception { |
| | | |
| | | http.cors().and().csrf().disable() |
| | | |
| | | // 登录配置 |
| | | .formLogin() |
| | | .successHandler(loginSuccessHandler) |
| | | .failureHandler(loginFailureHandler) |
| | | |
| | | .and() |
| | | .logout() |
| | | .logoutSuccessHandler(jwtLogoutSuccessHandler) |
| | | |
| | | // 禁用session |
| | | .and() |
| | | .sessionManagement() |
| | | .sessionCreationPolicy(SessionCreationPolicy.STATELESS) |
| | | |
| | | // 配置拦截规则 |
| | | .and() |
| | | .authorizeRequests() |
| | | .antMatchers("/sys/user/login").anonymous() |
| | | .antMatchers("/swagger-ui.html").permitAll() |
| | | .antMatchers("/webjars/**").permitAll() |
| | | .antMatchers("/v2/**").permitAll() |
| | | .antMatchers("/swagger-resources/**").permitAll() |
| | | .antMatchers("/**").permitAll() |
| | | .anyRequest().authenticated() |
| | | |
| | | // 异常处理器 |
| | | .and() |
| | | .exceptionHandling() |
| | | .authenticationEntryPoint(jwtAuthenticationEntryPoint) |
| | | .accessDeniedHandler(jwtAccessDeniedHandler) |
| | | |
| | | // 配置自定义的过滤器 |
| | | .and() |
| | | .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); |
| | | } |
| | | |
| | | @Bean |
| | | @Override |
| | | public AuthenticationManager authenticationManagerBean() throws Exception { |
| | | return super.authenticationManagerBean(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.filter; |
| | | |
| | | import com.mes.common.utils.JwtUtil; |
| | | import com.mes.common.utils.RedisUtil; |
| | | import com.mes.common.utils.UserInfoUtils; |
| | | import com.mes.userinfo.entity.LoginUser; |
| | | import com.mes.userinfo.service.SysUserService; |
| | | import io.jsonwebtoken.Claims; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| | | import org.springframework.security.core.GrantedAuthority; |
| | | import org.springframework.security.core.authority.SimpleGrantedAuthority; |
| | | import org.springframework.security.core.context.SecurityContextHolder; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.web.filter.OncePerRequestFilter; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.FilterChain; |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/10 9:42 |
| | | * @Description: |
| | | */ |
| | | @Component |
| | | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { |
| | | // 此处解释为什么不去实现Filter接口,因为在某些情况下会过滤两次,执行两次Filter里面的方法,所以我们选择继承SpringSecurity中的OncePerRequestFilter |
| | | @Autowired |
| | | private RedisUtil redisUtil; |
| | | |
| | | @Resource |
| | | private SysUserService sysUserService; |
| | | |
| | | @Override |
| | | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { |
| | | //获取token |
| | | String token = request.getHeader("token"); |
| | | if (!StringUtils.hasText(token)) { |
| | | //放行 |
| | | filterChain.doFilter(request, response); |
| | | return; // 此处加上return好处是后面结果返回的时候就不会再走一遍此过滤器的方法了 |
| | | } |
| | | //解析token |
| | | String userid; |
| | | try { |
| | | Claims claims = JwtUtil.getClaimByToken(token); |
| | | userid = claims.getSubject(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | throw new RuntimeException("token非法"); |
| | | } |
| | | //从redis中获取用户信息 |
| | | String redisKey = "login:" + userid; |
| | | LoginUser loginUser = redisUtil.getCacheObject(redisKey); |
| | | if (Objects.isNull(loginUser)) { |
| | | response.setHeader("token", ""); |
| | | throw new RuntimeException("用户未登录"); |
| | | } |
| | | //将用户信息放入当前线程 |
| | | UserInfoUtils.set(loginUser.getUser()); |
| | | //存入SecurityContextHolder,以供后面的过滤器使用 |
| | | List<String> permissionKeyList = sysUserService.getUserAuthorityInfo(Long.parseLong(userid)); |
| | | List<GrantedAuthority> authorities = permissionKeyList.stream(). |
| | | map(SimpleGrantedAuthority::new) |
| | | .collect(Collectors.toList()); |
| | | UsernamePasswordAuthenticationToken authenticationToken = |
| | | new UsernamePasswordAuthenticationToken(loginUser, null, authorities); |
| | | SecurityContextHolder.getContext().setAuthentication(authenticationToken); |
| | | //放行 |
| | | filterChain.doFilter(request, response); |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.handler; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.mes.utils.Result; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.security.access.AccessDeniedException; |
| | | import org.springframework.security.web.access.AccessDeniedHandler; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Component |
| | | public class JwtAccessDeniedHandler implements AccessDeniedHandler { |
| | | |
| | | @Override |
| | | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { |
| | | |
| | | response.setContentType("application/json;charset=UTF-8"); |
| | | response.setStatus(HttpServletResponse.SC_FORBIDDEN); |
| | | |
| | | ServletOutputStream outputStream = response.getOutputStream(); |
| | | |
| | | Result result = Result.error(HttpStatus.FORBIDDEN.value(), "权限不足"); |
| | | |
| | | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); |
| | | |
| | | outputStream.flush(); |
| | | outputStream.close(); |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.handler; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.mes.utils.Result; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.security.core.AuthenticationException; |
| | | import org.springframework.security.web.AuthenticationEntryPoint; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Component |
| | | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { |
| | | |
| | | @Override |
| | | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { |
| | | |
| | | response.setContentType("application/json;charset=UTF-8"); |
| | | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); |
| | | ServletOutputStream outputStream = response.getOutputStream(); |
| | | |
| | | Result result = Result.error(HttpStatus.UNAUTHORIZED.value(), "认证失败请重新登录"); |
| | | |
| | | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); |
| | | |
| | | outputStream.flush(); |
| | | outputStream.close(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.handler; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.mes.utils.Result; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; |
| | | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Component |
| | | public class JwtLogoutSuccessHandler implements LogoutSuccessHandler { |
| | | |
| | | private static final String header = "Authorization"; |
| | | |
| | | @Override |
| | | public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { |
| | | |
| | | if (authentication != null) { |
| | | new SecurityContextLogoutHandler().logout(request, response, authentication); |
| | | } |
| | | |
| | | response.setContentType("application/json;charset=UTF-8"); |
| | | ServletOutputStream outputStream = response.getOutputStream(); |
| | | |
| | | response.setHeader(header, ""); |
| | | |
| | | Result result = Result.success(""); |
| | | |
| | | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); |
| | | |
| | | outputStream.flush(); |
| | | outputStream.close(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.handler; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.mes.utils.Result; |
| | | import org.springframework.security.core.AuthenticationException; |
| | | import org.springframework.security.web.authentication.AuthenticationFailureHandler; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Component |
| | | public class LoginFailureHandler implements AuthenticationFailureHandler { |
| | | |
| | | @Override |
| | | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { |
| | | |
| | | response.setContentType("application/json;charset=UTF-8"); |
| | | ServletOutputStream outputStream = response.getOutputStream(); |
| | | |
| | | Result result = Result.error("用户名或密码错误"); |
| | | |
| | | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); |
| | | |
| | | outputStream.flush(); |
| | | outputStream.close(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.handler; |
| | | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.mes.common.utils.JwtUtil; |
| | | import com.mes.utils.Result; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletOutputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Component |
| | | public class LoginSuccessHandler implements AuthenticationSuccessHandler { |
| | | |
| | | private static final String header = "Authorization"; |
| | | |
| | | @Override |
| | | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { |
| | | response.setContentType("application/json;charset=UTF-8"); |
| | | ServletOutputStream outputStream = response.getOutputStream(); |
| | | |
| | | // 生成jwt,并放置到请求头中 |
| | | String jwt = JwtUtil.generateToken(authentication.getName()); |
| | | response.setHeader(header, jwt); |
| | | |
| | | Result result = Result.success(""); |
| | | |
| | | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); |
| | | |
| | | outputStream.flush(); |
| | | outputStream.close(); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.common.utils; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.parser.ParserConfig; |
| | | import com.alibaba.fastjson.serializer.SerializerFeature; |
| | | import com.fasterxml.jackson.databind.JavaType; |
| | | import com.fasterxml.jackson.databind.type.TypeFactory; |
| | | import org.springframework.data.redis.serializer.RedisSerializer; |
| | | import org.springframework.data.redis.serializer.SerializationException; |
| | | |
| | | import java.nio.charset.Charset; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/11 15:28 |
| | | * @Description: |
| | | */ |
| | | public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { |
| | | |
| | | public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); |
| | | |
| | | private Class<T> clazz; |
| | | |
| | | static { |
| | | ParserConfig.getGlobalInstance().setAutoTypeSupport(true); |
| | | } |
| | | |
| | | public FastJsonRedisSerializer(Class<T> clazz) { |
| | | super(); |
| | | this.clazz = clazz; |
| | | } |
| | | |
| | | @Override |
| | | public byte[] serialize(T t) throws SerializationException { |
| | | if (t == null) { |
| | | return new byte[0]; |
| | | } |
| | | return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); |
| | | } |
| | | |
| | | @Override |
| | | public T deserialize(byte[] bytes) throws SerializationException { |
| | | if (bytes == null || bytes.length <= 0) { |
| | | return null; |
| | | } |
| | | String str = new String(bytes, DEFAULT_CHARSET); |
| | | |
| | | return JSON.parseObject(str, clazz); |
| | | } |
| | | |
| | | |
| | | protected JavaType getJavaType(Class<?> clazz) { |
| | | return TypeFactory.defaultInstance().constructType(clazz); |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.utils; |
| | | |
| | | |
| | | import io.jsonwebtoken.Claims; |
| | | import io.jsonwebtoken.Jwts; |
| | | import io.jsonwebtoken.SignatureAlgorithm; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/9 19:15 |
| | | * @Description: |
| | | */ |
| | | @Data |
| | | public class JwtUtil { |
| | | |
| | | private static final long expire = 60 * 60 * 1000L; |
| | | private static final String secret = "beibo"; |
| | | private static final String header = "Authorization"; |
| | | |
| | | // 生成jwt |
| | | public static String generateToken(String username) { |
| | | |
| | | Date nowDate = new Date(); |
| | | Date expireDate = new Date(nowDate.getTime() + 1000 * expire); |
| | | |
| | | return Jwts.builder() |
| | | .setHeaderParam("typ", "JWT") |
| | | .setSubject(username) |
| | | .setIssuedAt(nowDate) |
| | | .setExpiration(expireDate)// 7天過期 |
| | | .signWith(SignatureAlgorithm.HS512, secret) |
| | | .compact(); |
| | | } |
| | | |
| | | // 解析jwt |
| | | public static Claims getClaimByToken(String jwt) { |
| | | try { |
| | | return Jwts.parser() |
| | | .setSigningKey(secret) |
| | | .parseClaimsJws(jwt) |
| | | .getBody(); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | // jwt是否过期 |
| | | public boolean isTokenExpired(Claims claims) { |
| | | return claims.getExpiration().before(new Date()); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.common.utils; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.BoundSetOperations; |
| | | import org.springframework.data.redis.core.HashOperations; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.data.redis.core.ValueOperations; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * spring redis 工具类 |
| | | **/ |
| | | @Component |
| | | public class RedisUtil { |
| | | @Autowired |
| | | public RedisTemplate redisTemplate; |
| | | |
| | | /** |
| | | * 缓存基本的对象,Integer、String、实体类等 |
| | | * |
| | | * @param key 缓存的键值 |
| | | * @param value 缓存的值 |
| | | */ |
| | | public <T> void setCacheObject(final String key, final T value) { |
| | | redisTemplate.opsForValue().set(key, value); |
| | | } |
| | | |
| | | /** |
| | | * 缓存基本的对象,Integer、String、实体类等 |
| | | * |
| | | * @param key 缓存的键值 |
| | | * @param value 缓存的值 |
| | | * @param timeout 时间 |
| | | * @param timeUnit 时间颗粒度 |
| | | */ |
| | | public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { |
| | | redisTemplate.opsForValue().set(key, value, timeout, timeUnit); |
| | | } |
| | | |
| | | /** |
| | | * 设置有效时间 |
| | | * |
| | | * @param key Redis键 |
| | | * @param timeout 超时时间 |
| | | * @return true=设置成功;false=设置失败 |
| | | */ |
| | | public boolean expire(final String key, final long timeout) { |
| | | return expire(key, timeout, TimeUnit.SECONDS); |
| | | } |
| | | |
| | | /** |
| | | * 设置有效时间 |
| | | * |
| | | * @param key Redis键 |
| | | * @param timeout 超时时间 |
| | | * @param unit 时间单位 |
| | | * @return true=设置成功;false=设置失败 |
| | | */ |
| | | public boolean expire(final String key, final long timeout, final TimeUnit unit) { |
| | | return redisTemplate.expire(key, timeout, unit); |
| | | } |
| | | |
| | | /** |
| | | * 获得缓存的基本对象。 |
| | | * |
| | | * @param key 缓存键值 |
| | | * @return 缓存键值对应的数据 |
| | | */ |
| | | public <T> T getCacheObject(final String key) { |
| | | ValueOperations<String, T> operation = redisTemplate.opsForValue(); |
| | | return operation.get(key); |
| | | } |
| | | |
| | | /** |
| | | * 删除单个对象 |
| | | * |
| | | * @param key |
| | | */ |
| | | public boolean deleteObject(final String key) { |
| | | return redisTemplate.delete(key); |
| | | } |
| | | |
| | | /** |
| | | * 删除集合对象 |
| | | * |
| | | * @param collection 多个对象 |
| | | * @return |
| | | */ |
| | | public long deleteObject(final Collection collection) { |
| | | return redisTemplate.delete(collection); |
| | | } |
| | | |
| | | /** |
| | | * 缓存List数据 |
| | | * |
| | | * @param key 缓存的键值 |
| | | * @param dataList 待缓存的List数据 |
| | | * @return 缓存的对象 |
| | | */ |
| | | public <T> long setCacheList(final String key, final List<T> dataList) { |
| | | Long count = redisTemplate.opsForList().rightPushAll(key, dataList); |
| | | return count == null ? 0 : count; |
| | | } |
| | | |
| | | /** |
| | | * 获得缓存的list对象 |
| | | * |
| | | * @param key 缓存的键值 |
| | | * @return 缓存键值对应的数据 |
| | | */ |
| | | public <T> List<T> getCacheList(final String key) { |
| | | return redisTemplate.opsForList().range(key, 0, -1); |
| | | } |
| | | |
| | | /** |
| | | * 缓存Set |
| | | * |
| | | * @param key 缓存键值 |
| | | * @param dataSet 缓存的数据 |
| | | * @return 缓存数据的对象 |
| | | */ |
| | | public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) { |
| | | BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key); |
| | | Iterator<T> it = dataSet.iterator(); |
| | | while (it.hasNext()) { |
| | | setOperation.add(it.next()); |
| | | } |
| | | return setOperation; |
| | | } |
| | | |
| | | /** |
| | | * 获得缓存的set |
| | | * |
| | | * @param key |
| | | * @return |
| | | */ |
| | | public <T> Set<T> getCacheSet(final String key) { |
| | | return redisTemplate.opsForSet().members(key); |
| | | } |
| | | |
| | | /** |
| | | * 缓存Map |
| | | * |
| | | * @param key |
| | | * @param dataMap |
| | | */ |
| | | public <T> void setCacheMap(final String key, final Map<String, T> dataMap) { |
| | | if (dataMap != null) { |
| | | redisTemplate.opsForHash().putAll(key, dataMap); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获得缓存的Map |
| | | * |
| | | * @param key |
| | | * @return |
| | | */ |
| | | public <T> Map<String, T> getCacheMap(final String key) { |
| | | return redisTemplate.opsForHash().entries(key); |
| | | } |
| | | |
| | | /** |
| | | * 往Hash中存入数据 |
| | | * |
| | | * @param key Redis键 |
| | | * @param hKey Hash键 |
| | | * @param value 值 |
| | | */ |
| | | public <T> void setCacheMapValue(final String key, final String hKey, final T value) { |
| | | redisTemplate.opsForHash().put(key, hKey, value); |
| | | } |
| | | |
| | | /** |
| | | * 获取Hash中的数据 |
| | | * |
| | | * @param key Redis键 |
| | | * @param hKey Hash键 |
| | | * @return Hash中的对象 |
| | | */ |
| | | public <T> T getCacheMapValue(final String key, final String hKey) { |
| | | HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); |
| | | return opsForHash.get(key, hKey); |
| | | } |
| | | |
| | | /** |
| | | * 删除Hash中的数据 |
| | | * |
| | | * @param key |
| | | * @param hkey |
| | | */ |
| | | public void delCacheMapValue(final String key, final String hkey) { |
| | | HashOperations hashOperations = redisTemplate.opsForHash(); |
| | | hashOperations.delete(key, hkey); |
| | | } |
| | | |
| | | /** |
| | | * 获取多个Hash中的数据 |
| | | * |
| | | * @param key Redis键 |
| | | * @param hKeys Hash键集合 |
| | | * @return Hash对象集合 |
| | | */ |
| | | public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) { |
| | | return redisTemplate.opsForHash().multiGet(key, hKeys); |
| | | } |
| | | |
| | | /** |
| | | * 获得缓存的基本对象列表 |
| | | * |
| | | * @param pattern 字符串前缀 |
| | | * @return 对象列表 |
| | | */ |
| | | public Collection<String> keys(final String pattern) { |
| | | return redisTemplate.keys(pattern); |
| | | } |
| | | |
| | | /** |
| | | * 判断key是否存在 |
| | | * |
| | | * @param key 键 |
| | | * @return true 存在 false不存在 |
| | | */ |
| | | public boolean hasKey(String key) { |
| | | try { |
| | | return redisTemplate.hasKey(key); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.utils; |
| | | |
| | | import com.mes.userinfo.entity.SysUser; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/25 15:41 |
| | | * @Description: |
| | | */ |
| | | public class UserInfoUtils { |
| | | private static InheritableThreadLocal<SysUser> tokenPool = new InheritableThreadLocal<SysUser>(); |
| | | |
| | | public static SysUser get() { |
| | | return tokenPool.get(); |
| | | } |
| | | |
| | | public static void set(SysUser user) { |
| | | tokenPool.set(user); |
| | | } |
| | | |
| | | public static void remove() { |
| | | if (get() != null) { |
| | | tokenPool.remove(); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.common.utils; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/9 19:16 |
| | | * @Description: |
| | | */ |
| | | public class WebUtils { |
| | | /** |
| | | * 将字符串渲染到客户端 |
| | | * |
| | | * @param response 渲染对象 |
| | | * @param string 待渲染的字符串 |
| | | * @return null |
| | | */ |
| | | public static String renderString(HttpServletResponse response, String string) { |
| | | try { |
| | | response.setStatus(200); |
| | | response.setContentType("application/json"); |
| | | response.setCharacterEncoding("utf-8"); |
| | | response.getWriter().print(string); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.mes.menu.controller; |
| | | |
| | | import com.mes.entity.request.GeneralRequest; |
| | | import com.mes.menu.entity.SysMenu; |
| | | import com.mes.menu.service.SysMenuService; |
| | | import com.mes.utils.Result; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Api(description = "菜单管理") |
| | | @RestController |
| | | @RequestMapping("/sys/menu") |
| | | public class SysMenuController { |
| | | |
| | | @Autowired |
| | | private SysMenuService sysMenuService; |
| | | |
| | | @ApiOperation("新增菜单") |
| | | @PostMapping("/save") |
| | | // @PreAuthorize("hasAuthority('sys:menu:save')") |
| | | public Result save(@Validated @RequestBody SysMenu sysMenu) { |
| | | return Result.success(sysMenuService.save(sysMenu)); |
| | | } |
| | | |
| | | @ApiOperation("修改菜单信息") |
| | | @PostMapping("/updateMenu") |
| | | // @PreAuthorize("hasAuthority('sys:menu:update')") |
| | | public Result updateMenu(@Validated @RequestBody SysMenu sysMenu) { |
| | | sysMenuService.updateMenu(sysMenu); |
| | | return Result.success(sysMenu); |
| | | } |
| | | |
| | | @ApiOperation("获取用户有权限的所有菜单") |
| | | @GetMapping("/getMenuTree") |
| | | public Result<List<SysMenu>> getMenuTree(GeneralRequest request) { |
| | | return Result.success(sysMenuService.getMenuTree(request)); |
| | | } |
| | | |
| | | @ApiOperation("获取用户的权限") |
| | | @GetMapping("/getAuthorityInfo") |
| | | public Result<List<String>> getAuthorityInfo() { |
| | | return Result.success(sysMenuService.getAuthorityInfo()); |
| | | } |
| | | |
| | | |
| | | @ApiOperation("用户当前用户的菜单和权限信息") |
| | | @GetMapping("/nav") |
| | | public Result<Map<Object, Object>> nav() { |
| | | return Result.success(sysMenuService.nav()); |
| | | } |
| | | |
| | | @ApiOperation("删除菜单") |
| | | @PostMapping("/deleteMenu") |
| | | // @PreAuthorize("hasAuthority('sys:menu:delete')") |
| | | public Result<String> deleteMenu(Long menuId) { |
| | | return Result.success(sysMenuService.deleteMenu(menuId)); |
| | | } |
| | | |
| | | @ApiOperation("批量删除菜单") |
| | | @PostMapping("/batchDeleteMenu") |
| | | // @PreAuthorize("hasAuthority('sys:menu:delete')") |
| | | public Result<String> batchDeleteMenu(@RequestBody List<Long> menuIds) { |
| | | return Result.success(sysMenuService.batchDeleteMenu(menuIds)); |
| | | } |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.mes.menu.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-13 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @Accessors(chain = true) |
| | | public class SysMenu implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 自增id |
| | | */ |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | /** |
| | | * 父id |
| | | */ |
| | | private Long parentId; |
| | | |
| | | /** |
| | | * 模块名称 |
| | | */ |
| | | private String menuName; |
| | | |
| | | /** |
| | | * 图标 |
| | | */ |
| | | private String icon; |
| | | |
| | | /** |
| | | * 地址 |
| | | */ |
| | | private String url; |
| | | |
| | | /** |
| | | * 语言类型 |
| | | */ |
| | | private String languageType; |
| | | |
| | | /** |
| | | * 状态 |
| | | */ |
| | | private Integer status; |
| | | |
| | | /** |
| | | * 排序 |
| | | */ |
| | | private String listSort; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | private Date createTime; |
| | | |
| | | /** |
| | | * 权限 |
| | | */ |
| | | private String perms; |
| | | |
| | | /** |
| | | * 子菜单 |
| | | */ |
| | | @TableField(exist = false) |
| | | private List<SysMenu> children; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.menu.mapper; |
| | | |
| | | import com.github.yulichang.base.MPJBaseMapper; |
| | | import com.mes.menu.entity.SysMenu; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * 菜单表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Mapper |
| | | public interface SysMenuMapper extends MPJBaseMapper<SysMenu> { |
| | | |
| | | List<String> selectPermsByUserId(long parseLong); |
| | | } |
New file |
| | |
| | | package com.mes.menu.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.mes.entity.request.GeneralRequest; |
| | | import com.mes.menu.entity.SysMenu; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * <p> |
| | | * 菜单表 服务类 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | public interface SysMenuService extends IService<SysMenu> { |
| | | |
| | | /** |
| | | * 更新菜单信息 |
| | | * |
| | | * @param menu |
| | | * @return |
| | | */ |
| | | SysMenu updateMenu(SysMenu menu); |
| | | |
| | | /** |
| | | * 获取用户有权限的菜单树 |
| | | * |
| | | * @return |
| | | */ |
| | | List<SysMenu> getMenuTree(GeneralRequest request); |
| | | |
| | | /** |
| | | * 获取用户的权限 |
| | | * |
| | | * @return |
| | | */ |
| | | List<String> getAuthorityInfo(); |
| | | |
| | | |
| | | /** |
| | | * 获取用户菜单及权限信息 |
| | | * |
| | | * @return |
| | | */ |
| | | Map<Object, Object> nav(); |
| | | |
| | | /** |
| | | * 删除菜单信息 |
| | | * |
| | | * @param menuId |
| | | * @return |
| | | */ |
| | | String deleteMenu(Long menuId); |
| | | |
| | | /** |
| | | * 批量删除菜单信息 |
| | | * |
| | | * @param menuIds |
| | | * @return |
| | | */ |
| | | String batchDeleteMenu(List<Long> menuIds); |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.menu.service.impl; |
| | | |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import com.mes.common.utils.UserInfoUtils; |
| | | import com.mes.entity.request.GeneralRequest; |
| | | import com.mes.menu.entity.SysMenu; |
| | | import com.mes.menu.mapper.SysMenuMapper; |
| | | import com.mes.menu.service.SysMenuService; |
| | | import com.mes.role.entity.SysRoleMenu; |
| | | import com.mes.role.service.SysRoleMenuService; |
| | | import com.mes.userinfo.entity.SysUser; |
| | | import com.mes.userinfo.entity.SysUserRole; |
| | | import com.mes.userinfo.mapper.SysUserRoleMapper; |
| | | import com.mes.userinfo.service.SysUserService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | | * 菜单表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService { |
| | | |
| | | @Autowired |
| | | SysUserService sysUserService; |
| | | |
| | | @Autowired |
| | | SysUserRoleMapper sysUserRoleMapper; |
| | | |
| | | @Autowired |
| | | SysRoleMenuService sysRoleMenuService; |
| | | |
| | | @Override |
| | | public SysMenu updateMenu(SysMenu menu) { |
| | | baseMapper.updateById(menu); |
| | | // 清除所有与该菜单相关的权限缓存 |
| | | sysUserService.clearUserAuthorityInfoByMenuId(menu.getId()); |
| | | return menu; |
| | | } |
| | | |
| | | @Override |
| | | public List<SysMenu> getMenuTree(GeneralRequest request) { |
| | | //todo:需要先获取用户的角色,角色下的菜单权限,拿到菜单id获取所有菜单 |
| | | SysUser user = UserInfoUtils.get(); |
| | | MPJLambdaWrapper<SysUserRole> wrapper = new MPJLambdaWrapper<>(); |
| | | |
| | | wrapper.selectAll(SysMenu.class).distinct() |
| | | .innerJoin(SysUser.class, SysUser::getId, SysUserRole::getUserId) |
| | | .innerJoin(SysRoleMenu.class, SysRoleMenu::getRoleId, SysUserRole::getRoleId) |
| | | .innerJoin(SysMenu.class, SysMenu::getId, SysRoleMenu::getMenuId) |
| | | .eq(SysUser::getId, user.getId()) |
| | | .like(StringUtils.isNotBlank(request.getKey()), SysMenu::getMenuName, request.getKey()); |
| | | |
| | | // |
| | | List<SysMenu> menuList = sysUserRoleMapper.selectJoinList(SysMenu.class, wrapper); |
| | | log.info("userinfos:{}",menuList); |
| | | return create(menuList); |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getAuthorityInfo() { |
| | | SysUser user = UserInfoUtils.get(); |
| | | log.info("获取用户信息,用户名为{}", user); |
| | | // 获取权限信息 |
| | | // ROLE_admin,ROLE_normal,sys:user:list,.... |
| | | return sysUserService.getUserAuthorityInfo(user.getId()); |
| | | } |
| | | |
| | | @Override |
| | | public Map<Object, Object> nav() { |
| | | List<SysMenu> menuTree = getMenuTree(new GeneralRequest()); |
| | | List<String> authorityInfo = getAuthorityInfo(); |
| | | return MapUtil.builder().put("authoritys", authorityInfo) |
| | | .put("tree", menuTree).map(); |
| | | } |
| | | |
| | | @Override |
| | | public String deleteMenu(Long menuId) { |
| | | int count = this.count(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, menuId)); |
| | | if (count > 0) { |
| | | return "无法删除,请先删除子菜单"; |
| | | } |
| | | |
| | | // 清除所有与该菜单相关的权限缓存 |
| | | sysUserService.clearUserAuthorityInfoByMenuId(menuId); |
| | | |
| | | this.removeById(menuId); |
| | | |
| | | // 同步删除中间关联表 |
| | | sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getMenuId, menuId)); |
| | | return "删除成功"; |
| | | } |
| | | |
| | | @Override |
| | | public String batchDeleteMenu(List<Long> menuIds) { |
| | | menuIds.stream().forEach(e -> deleteMenu(e)); |
| | | return "批量删除成功"; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将数据库中查询出来的list集合传入此方法即可获得排成树形结构的list集合 |
| | | * |
| | | * @param lists |
| | | * @return |
| | | */ |
| | | public List<SysMenu> create(List<SysMenu> lists) { |
| | | List<SysMenu> deptTreeList = lists.stream() |
| | | .filter(item -> item.getParentId() == 0) |
| | | .map(item -> { |
| | | item.setChildren(getChildren(item, lists)); |
| | | return item; |
| | | }).collect(Collectors.toList()); |
| | | return deptTreeList; |
| | | } |
| | | |
| | | /** |
| | | * 此方法将被递归调用 |
| | | * |
| | | * @param menu |
| | | * @param menus |
| | | * @return |
| | | */ |
| | | private List<SysMenu> getChildren(SysMenu menu, List<SysMenu> menus) { |
| | | List<SysMenu> res = menus.stream() |
| | | .filter(item -> item.getParentId().equals(menu.getId())) |
| | | .collect(Collectors.toList()); |
| | | log.info("菜单树:{}", JSONUtil.toJsonStr(res)); |
| | | return res; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.controller; |
| | | |
| | | |
| | | import com.mes.entity.request.GeneralRequest; |
| | | import com.mes.role.entity.SysRole; |
| | | import com.mes.role.entity.vo.SysRoleVO; |
| | | import com.mes.role.service.SysRoleService; |
| | | import com.mes.utils.Result; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | 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.List; |
| | | |
| | | /** |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Api(description = "角色管理") |
| | | @RestController |
| | | @RequestMapping("/sys/role") |
| | | public class SysRoleController { |
| | | |
| | | @Autowired |
| | | private SysRoleService sysRoleService; |
| | | |
| | | @ApiOperation("新增角色及角色下的权限信息") |
| | | @PostMapping("/saveRole") |
| | | // @PreAuthorize("hasAuthority('sys:role:save')") |
| | | public Result<SysRole> saveRole(@Validated @RequestBody SysRoleVO sysRoleVO) { |
| | | return Result.success(sysRoleService.saveRole(sysRoleVO)); |
| | | } |
| | | |
| | | @ApiOperation("编辑角色及角色下的权限信息") |
| | | @PostMapping("/updateRole") |
| | | // @PreAuthorize("hasAuthority('sys:role:save')") |
| | | public Result<String> updateRole(@Validated @RequestBody SysRoleVO sysRoleVO) { |
| | | return Result.success(sysRoleService.updateRole(sysRoleVO)); |
| | | } |
| | | |
| | | @ApiOperation("查询角色及角色下的权限信息") |
| | | @PostMapping("/queryRole") |
| | | // @PreAuthorize("hasAuthority('sys:role:save')") |
| | | public Result<List<SysRoleVO>> queryRole(@Validated @RequestBody GeneralRequest request) { |
| | | return Result.success(sysRoleService.queryRole(request)); |
| | | } |
| | | |
| | | |
| | | @ApiOperation("删除角色及角色下的权限信息") |
| | | @PostMapping("/delete") |
| | | // @PreAuthorize("hasAuthority('sys:role:delete')") |
| | | @Transactional |
| | | public Result<String> deleteRole(@RequestBody List<Long> ids) { |
| | | return Result.success(sysRoleService.deleteRole(ids)); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * 角色表 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | public class SysRole implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | private String name; |
| | | |
| | | /** |
| | | * 角色权限字符串 |
| | | */ |
| | | private String roleKey; |
| | | |
| | | /** |
| | | * 角色状态(0正常 1停用) |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * 删除标志 |
| | | */ |
| | | private Integer delFlag; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | private String remark; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | public class SysRoleMenu implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 角色ID |
| | | */ |
| | | @TableId(type = IdType.NONE) |
| | | private Long roleId; |
| | | |
| | | /** |
| | | * 菜单id |
| | | */ |
| | | private Long menuId; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.entity.vo; |
| | | |
| | | import com.mes.menu.entity.SysMenu; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @Author : zhoush |
| | | * @Date: 2024/4/26 13:57 |
| | | * @Description: |
| | | */ |
| | | @Api(description = "角色信息") |
| | | @Data |
| | | public class SysRoleVO implements Serializable { |
| | | |
| | | @ApiModelProperty(hidden = true) |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "角色ID", position = 2) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "角色名称", position = 3) |
| | | private String name; |
| | | |
| | | @ApiModelProperty(value = "角色权限字符串", position = 4) |
| | | private String roleKey; |
| | | |
| | | @ApiModelProperty(value = "角色状态(0正常 1停用)", position = 5) |
| | | private String status; |
| | | |
| | | @ApiModelProperty(value = "删除标志", position = 6) |
| | | private Integer delFlag; |
| | | |
| | | @ApiModelProperty(value = "备注", position = 7) |
| | | private String remark; |
| | | |
| | | @ApiModelProperty(value = "角色菜单信息", position = 8) |
| | | private List<SysMenu> menuList; |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.mapper; |
| | | |
| | | import com.github.yulichang.base.MPJBaseMapper; |
| | | import com.mes.role.entity.SysRole; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * <p> |
| | | * 角色表 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Mapper |
| | | public interface SysRoleMapper extends MPJBaseMapper<SysRole> { |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.mes.role.entity.SysRoleMenu; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * <p> |
| | | * Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Mapper |
| | | public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenu> { |
| | | |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.mes.role.mapper.SysRoleMapper"> |
| | | |
| | | </mapper> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.mes.role.mapper.SysRoleMenuMapper"> |
| | | |
| | | </mapper> |
New file |
| | |
| | | package com.mes.role.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.mes.role.entity.SysRoleMenu; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务类 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | public interface SysRoleMenuService extends IService<SysRoleMenu> { |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.mes.entity.request.GeneralRequest; |
| | | import com.mes.role.entity.SysRole; |
| | | import com.mes.role.entity.vo.SysRoleVO; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * 角色表 服务类 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | public interface SysRoleService extends IService<SysRole> { |
| | | |
| | | /** |
| | | * 创建角色信息 |
| | | * |
| | | * @param sysRoleVO |
| | | * @return |
| | | */ |
| | | SysRole saveRole(SysRoleVO sysRoleVO); |
| | | |
| | | /** |
| | | * 修改角色信息及权限 |
| | | * |
| | | * @param sysRoleVO |
| | | * @return |
| | | */ |
| | | String updateRole(SysRoleVO sysRoleVO); |
| | | |
| | | /** |
| | | * 按照角色名查询角色信息 |
| | | * |
| | | * @param request |
| | | * @return |
| | | */ |
| | | List<SysRoleVO> queryRole(GeneralRequest request); |
| | | |
| | | /** |
| | | * 查询角色及角色下的权限信息 |
| | | * |
| | | * @param ids |
| | | * @return |
| | | */ |
| | | String deleteRole(List<Long> ids); |
| | | } |
New file |
| | |
| | | package com.mes.role.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.mes.role.entity.SysRoleMenu; |
| | | import com.mes.role.mapper.SysRoleMenuMapper; |
| | | import com.mes.role.service.SysRoleMenuService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Service |
| | | public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> implements SysRoleMenuService { |
| | | |
| | | } |
New file |
| | |
| | | package com.mes.role.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import com.mes.entity.request.GeneralRequest; |
| | | import com.mes.menu.entity.SysMenu; |
| | | import com.mes.role.entity.SysRole; |
| | | import com.mes.role.entity.SysRoleMenu; |
| | | import com.mes.role.entity.vo.SysRoleVO; |
| | | import com.mes.role.mapper.SysRoleMapper; |
| | | import com.mes.role.service.SysRoleMenuService; |
| | | import com.mes.role.service.SysRoleService; |
| | | import com.mes.userinfo.entity.SysUserRole; |
| | | import com.mes.userinfo.service.SysUserRoleService; |
| | | import com.mes.userinfo.service.SysUserService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | | * 角色表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author zhoush |
| | | * @since 2024-04-11 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService { |
| | | |
| | | @Autowired |
| | | SysRoleMenuService sysRoleMenuService; |
| | | |
| | | @Autowired |
| | | SysUserService sysUserService; |
| | | |
| | | @Autowired |
| | | SysUserRoleService sysUserRoleService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public SysRole saveRole(SysRoleVO sysRoleVO) { |
| | | log.info("保存角色信息,生成对应的角色id"); |
| | | SysRole sysRole = new SysRole(); |
| | | BeanUtils.copyProperties(sysRoleVO, sysRole); |
| | | this.save(sysRole); |
| | | //保存角色权限信息 |
| | | saveRoleMenu(sysRole.getId(), sysRoleVO.getMenuList()); |
| | | return sysRole; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String updateRole(SysRoleVO sysRoleVO) { |
| | | log.info("保存角色信息,生成对应的角色id"); |
| | | SysRole sysRole = new SysRole(); |
| | | BeanUtils.copyProperties(sysRoleVO, sysRole); |
| | | this.updateById(sysRole); |
| | | //保存角色权限信息 |
| | | return saveRoleMenu(sysRole.getId(), sysRoleVO.getMenuList()); |
| | | } |
| | | |
| | | @Override |
| | | public List<SysRoleVO> queryRole(GeneralRequest request) { |
| | | MPJLambdaWrapper<SysRole> wrapper = new MPJLambdaWrapper<>(); |
| | | wrapper.selectAll(SysRole.class) |
| | | .selectCollection(SysMenu.class, SysRoleVO::getMenuList) |
| | | .leftJoin(SysRoleMenu.class, SysRoleMenu::getRoleId, SysRole::getId) |
| | | .leftJoin(SysMenu.class, SysMenu::getId, SysRoleMenu::getMenuId) |
| | | .like(StringUtils.hasText(request.getKey()), SysRole::getName, request.getKey()); |
| | | return baseMapper.selectJoinList(SysRoleVO.class, wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String deleteRole(List<Long> ids) { |
| | | log.info("删除角色信息"); |
| | | this.removeByIds(ids); |
| | | |
| | | log.info("删除中间表信息"); |
| | | sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, ids)); |
| | | sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, ids)); |
| | | |
| | | log.info("清空缓存中的权限信息"); |
| | | ids.stream().forEach(id -> sysUserService.clearUserAuthorityInfoByRoleId(id)); |
| | | return "success"; |
| | | } |
| | | |
| | | /** |
| | | * 保存角色权限信息 |
| | | * |
| | | * @param roleId |
| | | * @param menuList |
| | | * @return |
| | | */ |
| | | private String saveRoleMenu(Long roleId, List<SysMenu> menuList) { |
| | | log.info("配置角色菜单关心"); |
| | | List<SysRoleMenu> roleMenuList = menuList.stream().map(menu -> { |
| | | SysRoleMenu roleMenu = new SysRoleMenu(); |
| | | roleMenu.setRoleId(roleId); |
| | | roleMenu.setMenuId(menu.getId()); |
| | | return roleMenu; |
| | | }).collect(Collectors.toList()); |
| | | log.info("清空角色权限表中该角色信息"); |
| | | |
| | | |
| | | // 先删除原来的记录,再保存新的 |
| | | sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId)); |
| | | sysRoleMenuService.saveBatch(roleMenuList); |
| | | |
| | | // 删除缓存 |
| | | sysUserService.clearUserAuthorityInfoByRoleId(roleId); |
| | | return "success"; |
| | | } |
| | | } |