springboot与redis
该项目已上传至GitHub:https://github.com/xiaostudy/springboot_redis
用到的框架技术有:springboot、mybatis、shiro、redis
前端有:layui、jqGrid
这里先不讲redis在Windows安装,比较简单,百度看一下其他文章就可以了,有空这里也可以补一个教程。
1、先看项目目录
2、下面放源码
实体类,权限PermissionEntity.java
1 package com.xiaostudy.shiro_test1.entity; 2 3 import java.io.Serializable; 4 5 /** 6 * 权限实体类 7 * Created with IntelliJ IDEA. 8 * User: Administrator 9 * Date: 2019/6/8 10 * Time: 14:21 11 * Description: No Description 12 */ 13 public class PermissionEntity implements Serializable { 14 private String id; 15 private String name; 16 private String url; 17 18 public String getId() { 19 return id; 20 } 21 22 public void setId(String id) { 23 this.id = id; 24 } 25 26 public String getName() { 27 return name; 28 } 29 30 public void setName(String name) { 31 this.name = name; 32 } 33 34 public String getUrl() { 35 return url; 36 } 37 38 public void setUrl(String url) { 39 this.url = url; 40 } 41 }
实体类,角色RoleEntity.java
1 package com.xiaostudy.shiro_test1.entity; 2 3 import java.io.Serializable; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 /** 8 * 角色实体类 9 * Created with IntelliJ IDEA. 10 * User: Administrator 11 * Date: 2019/6/8 12 * Time: 14:24 13 * Description: No Description 14 */ 15 public class RoleEntity implements Serializable { 16 private String id; 17 private String name; 18 private Set<PermissionEntity> permissions = new HashSet<>(); 19 20 public String getId() { 21 return id; 22 } 23 24 public void setId(String id) { 25 this.id = id; 26 } 27 28 public String getName() { 29 return name; 30 } 31 32 public void setName(String name) { 33 this.name = name; 34 } 35 36 public Set<PermissionEntity> getPermissions() { 37 return permissions; 38 } 39 40 public void setPermissions(Set<PermissionEntity> permissions) { 41 this.permissions = permissions; 42 } 43 }
实体类,用户UserEntity.java
1 package com.xiaostudy.shiro_test1.entity; 2 3 import java.io.Serializable; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 /** 8 * 用户实体类 9 * Created with IntelliJ IDEA. 10 * User: Administrator 11 * Date: 2019/6/8 12 * Time: 14:26 13 * Description: No Description 14 */ 15 public class UserEntity implements Serializable { 16 private String id; 17 private String name; 18 private String password; 19 private Set<RoleEntity> roles = new HashSet<>(); 20 21 public String getId() { 22 return id; 23 } 24 25 public void setId(String id) { 26 this.id = id; 27 } 28 29 public String getName() { 30 return name; 31 } 32 33 public void setName(String name) { 34 this.name = name; 35 } 36 37 public String getPassword() { 38 return password; 39 } 40 41 public void setPassword(String password) { 42 this.password = password; 43 } 44 45 public Set<RoleEntity> getRoles() { 46 return roles; 47 } 48 49 public void setRoles(Set<RoleEntity> roles) { 50 this.roles = roles; 51 } 52 }
实体类,测试redis实体类TestRedisEntity.java
1 package com.xiaostudy.shiro_test1.entity; 2 3 import java.io.Serializable; 4 5 /** 6 * Created with IntelliJ IDEA. 7 * User: Administrator 8 * Date: 2019/6/8 9 * Time: 22:04 10 * Description: No Description 11 */ 12 public class TestRedisEntity implements Serializable { 13 private int id; 14 private String name; 15 private String password; 16 17 public int getId() { 18 return id; 19 } 20 21 public void setId(int id) { 22 this.id = id; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public String getPassword() { 34 return password; 35 } 36 37 public void setPassword(String password) { 38 this.password = password; 39 } 40 }
自定义Realm类,UserRealm.java
1 package com.xiaostudy.shiro_test1.realm; 2 3 import com.xiaostudy.shiro_test1.entity.PermissionEntity; 4 import com.xiaostudy.shiro_test1.entity.RoleEntity; 5 import com.xiaostudy.shiro_test1.entity.UserEntity; 6 import com.xiaostudy.shiro_test1.service.UserService; 7 import org.apache.shiro.SecurityUtils; 8 import org.apache.shiro.authc.*; 9 import org.apache.shiro.authz.AuthorizationInfo; 10 import org.apache.shiro.authz.SimpleAuthorizationInfo; 11 import org.apache.shiro.realm.AuthorizingRealm; 12 import org.apache.shiro.subject.PrincipalCollection; 13 import org.apache.shiro.subject.Subject; 14 import org.apache.shiro.util.ByteSource; 15 import org.springframework.beans.factory.annotation.Autowired; 16 17 import java.util.Collection; 18 import java.util.HashSet; 19 import java.util.Set; 20 21 /** 22 * 自定义Realm,实现授权与认证 23 * Created with IntelliJ IDEA. 24 * User: Administrator 25 * Date: 2019/6/8 26 * Time: 15:01 27 * Description: No Description 28 */ 29 public class UserRealm extends AuthorizingRealm { 30 31 @Autowired 32 private UserService userService; 33 34 /** 35 * 用户授权 36 **/ 37 @Override 38 protected AuthorizationInfo doGetAuthorizationInfo( 39 PrincipalCollection principalCollection) { 40 41 System.out.println("===执行授权==="); 42 43 Subject subject = SecurityUtils.getSubject(); 44 UserEntity user = (UserEntity)subject.getPrincipal(); 45 if(user != null){ 46 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 47 // 角色字符串集合 48 Collection<String> rolesCollection = new HashSet<>(); 49 // 权限字符串集合 50 Collection<String> premissionCollection = new HashSet<>(); 51 // 读取并赋值用户角色与权限 52 Set<RoleEntity> roles = user.getRoles(); 53 for(RoleEntity role : roles){ 54 rolesCollection.add(role.getName()); 55 Set<PermissionEntity> permissions = role.getPermissions(); 56 for (PermissionEntity permission : permissions){ 57 // 权限名称为PermissionEntity为字段url 58 premissionCollection.add(permission.getUrl()); 59 } 60 info.addStringPermissions(premissionCollection); 61 } 62 info.addRoles(rolesCollection); 63 return info; 64 } 65 return null; 66 } 67 68 /** 69 * 用户认证 70 **/ 71 @Override 72 protected AuthenticationInfo doGetAuthenticationInfo( 73 AuthenticationToken authenticationToken) throws AuthenticationException { 74 75 System.out.println("===执行认证==="); 76 77 UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; 78 UserEntity bean = userService.findByName(token.getUsername()); 79 80 if(bean == null){ 81 // 用户不存在 82 throw new UnknownAccountException(); 83 } else { 84 bean = userService.findById(bean.getId()); 85 if(null == bean) { 86 // 认证失败 87 throw new AuthenticationException(); 88 } 89 } 90 91 ByteSource credentialsSalt = ByteSource.Util.bytes(bean.getName()); 92 93 return new SimpleAuthenticationInfo(bean, bean.getPassword(), 94 credentialsSalt, getName()); 95 } 96 }
处理没权限异常,NoPermissionException.java
1 package com.xiaostudy.shiro_test1.exception; 2 3 import org.apache.shiro.authz.AuthorizationException; 4 import org.apache.shiro.authz.UnauthorizedException; 5 import org.springframework.stereotype.Component; 6 import org.springframework.web.bind.annotation.ControllerAdvice; 7 import org.springframework.web.bind.annotation.ExceptionHandler; 8 import org.springframework.web.bind.annotation.ResponseBody; 9 10 /** 11 * Created with IntelliJ IDEA. 12 * User: Administrator 13 * Date: 2019/6/8 14 * Time: 15:13 15 * Description: No Description 16 */ 17 @ControllerAdvice 18 public class NoPermissionException { 19 // 授权失败,就是说没有该权限 20 @ExceptionHandler(UnauthorizedException.class) 21 public String handleShiroException(Exception ex) { 22 return "/error/unAuth"; 23 } 24 25 @ResponseBody 26 @ExceptionHandler(AuthorizationException.class) 27 public String AuthorizationException(Exception ex) { 28 return "权限认证失败"; 29 } 30 }
shiro配置类,ShiroConfig.java
1 package com.xiaostudy.shiro_test1.config; 2 3 import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 4 import com.xiaostudy.shiro_test1.realm.UserRealm; 5 import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 6 import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 7 import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 8 import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; 9 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 import org.springframework.context.annotation.Bean; 11 import org.springframework.context.annotation.Configuration; 12 13 import java.util.HashMap; 14 import java.util.LinkedHashMap; 15 import java.util.Map; 16 17 /** 18 * Shiro配置类 19 * Created with IntelliJ IDEA. 20 * User: Administrator 21 * Date: 2019/6/8 22 * Time: 15:06 23 * Description: No Description 24 */ 25 @Configuration 26 public class ShiroConfig { 27 28 // 创建自定义 realm 29 @Bean 30 public UserRealm userRealm() { 31 UserRealm userRealm = new UserRealm(); 32 return userRealm; 33 } 34 35 // 创建 SecurityManager 对象 36 @Bean 37 public DefaultWebSecurityManager securityManager() { 38 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 39 securityManager.setRealm(userRealm()); 40 return securityManager; 41 } 42 43 // Filter工厂,设置对应的过滤条件和跳转条件 44 @Bean 45 public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { 46 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 47 shiroFilterFactoryBean.setSecurityManager(securityManager); 48 /** 49 * anon:匿名用户可访问 50 * authc:认证用户可访问 51 * user:使用rememberMe可访问 52 * perms:对应权限可访问 53 * role:对应角色权限可访问 54 */ 55 LinkedHashMap<String, String> map = new LinkedHashMap<>(); 56 // map.put("/resources/**", "anon");//匿名访问静态资源 57 map.put("/static/**", "anon");//匿名访问静态资源 58 map.put("/statics/**", "anon");//匿名访问静态资源 59 map.put("/jquery.jqGrid-4.6.0/**", "anon");//匿名访问静态资源 60 map.put("/jquery-ui-1.12.0-rc.2/**", "anon");//匿名访问静态资源 61 map.put("/layui/**", "anon");//匿名访问静态资源 62 map.put("/external/**", "anon");//匿名访问静态资源 63 map.put("/jquery/**", "anon");//匿名访问静态资源 64 map.put("/js/**", "anon");//匿名访问静态资源 65 map.put("/css/**", "anon");//匿名访问静态资源 66 map.put("/images/**", "anon");//匿名访问静态资源 67 // 开放登录接口 68 map.put("/login", "anon"); 69 // map.put("/login", "authc"); 70 // 对登录跳转接口进行释放 71 map.put("/error", "anon"); 72 // 对所有用户认证 73 map.put("/**", "authc"); 74 // 登出 75 map.put("/logout", "logout"); 76 // 登录 77 // 注意:这里配置的 /login 是指到 @RequestMapping(value="/login")中的 /login 78 shiroFilterFactoryBean.setLoginUrl("/login"); 79 // 首页 80 shiroFilterFactoryBean.setSuccessUrl("/index"); 81 // 错误页面,认证不通过跳转 82 shiroFilterFactoryBean.setUnauthorizedUrl("/error/unAuth"); 83 shiroFilterFactoryBean.setFilterChainDefinitionMap(map); 84 return shiroFilterFactoryBean; 85 } 86 87 // 加入注解的使用,不加这个,注解不生效 88 @Bean 89 public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { 90 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 91 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 92 return authorizationAttributeSourceAdvisor; 93 } 94 95 // 跟上面的注解配置搭配使用,有时候加了上面的配置后注解不生效,需要加入下面的配置 96 @Bean 97 @ConditionalOnMissingBean 98 public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { 99 DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator(); 100 app.setProxyTargetClass(true); 101 return app; 102 } 103 104 @Bean 105 public ShiroDialect shiroDialect() { 106 return new ShiroDialect(); 107 } 108 }
静态资源过滤配置类【告诉shiro不要拦截】,WebMvcConfig.java
1 package com.xiaostudy.shiro_test1.config; 2 3 import org.springframework.context.annotation.Configuration; 4 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 7 /** 8 * Created with IntelliJ IDEA. 9 * User: Administrator 10 * Date: 2019/6/9 11 * Time: 0:51 12 * Description: No Description 13 */ 14 @Configuration 15 public class WebMvcConfig implements WebMvcConfigurer { 16 17 /** 18 * @author xiaobu 19 * @date 2019/1/18 13:51 20 * @param registry registry 21 * @descprition 等价于 http://localhost:9001/1.txt 依次在static upload目录下找1.txt文件 22 * @version 1.0 23 */ 24 @Override 25 public void addResourceHandlers(ResourceHandlerRegistry registry) { 26 registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); 27 registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); 28 } 29 30 }
用户mapper,UserMapper.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <mapper namespace="com.xiaostudy.shiro_test1.mapper.UserMapper"> 4 5 <resultMap id="userMap" type="com.xiaostudy.shiro_test1.entity.UserEntity"> 6 <id property="id" column="id"/> 7 <result property="name" column="name"/> 8 <result property="password" column="password"/> 9 <collection property="roles" ofType="com.xiaostudy.shiro_test1.entity.RoleEntity"> 10 <id property="id" column="roleId"/> 11 <result property="name" column="roleName"/> 12 <collection property="permissions" ofType="com.xiaostudy.shiro_test1.entity.PermissionEntity"> 13 <id property="id" column="permissionId"/> 14 <result property="name" column="permissionName"/> 15 <result property="url" column="permissionUrl"/> 16 </collection> 17 </collection> 18 </resultMap> 19 20 <select id="findByName" parameterType="java.lang.String" resultType="com.xiaostudy.shiro_test1.entity.UserEntity"> 21 SELECT id, name, password 22 FROM user 23 WHERE name = #{name} 24 </select> 25 26 <select id="findById" parameterType="java.lang.String" resultMap="userMap"> 27 SELECT user.id, user.name, user.password, 28 role.id as roleId, role.name as roleName, 29 permission.id as permissionId, 30 permission.name as permissionName, 31 permission.url as permissionUrl 32 FROM user, user_role, role, role_permission, permission 33 WHERE user.id = #{id} 34 AND user.id = user_role.user_id 35 AND user_role.role_id = role.id 36 AND role.id = role_permission.role_id 37 AND role_permission.permission_id = permission.id 38 </select> 39 40 </mapper>
测试redis的mapper,TestRedisMapper.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <mapper namespace="com.xiaostudy.shiro_test1.mapper.TestRedisMapper"> 4 5 <select id="selectAll" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" > 6 SELECT id, name, password 7 FROM test_redis; 8 </select> 9 10 <select id="selectPages" parameterType="java.lang.Integer" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" > 11 SELECT id, name, password 12 FROM test_redis limit #{page}, #{rows}; 13 </select> 14 15 <select id="selectTotal" resultType="java.lang.Integer" > 16 SELECT COUNT(*) as total FROM test_redis; 17 </select> 18 19 <select id="selectById" parameterType="java.lang.Integer" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity"> 20 SELECT id, name, password 21 FROM test_redis 22 WHERE id = #{id}; 23 </select> 24 25 <select id="selectByName" parameterType="java.lang.String" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity"> 26 SELECT id, name, password 27 FROM test_redis 28 WHERE name = #{name}; 29 </select> 30 31 <insert id="insert" parameterType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" > 32 insert into test_redis (name, password) value (#{name}, #{password}); 33 </insert> 34 35 <update id="update" parameterType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" > 36 update test_redis 37 set 38 name = #{name}, 39 password = #{password} 40 where 41 id = #{id}; 42 </update> 43 44 <delete id="deleteById" parameterType="java.lang.Integer" > 45 delete from test_redis 46 where 47 id = #{id}; 48 </delete> 49 50 <delete id="deleteByName" parameterType="java.lang.String" > 51 delete from test_redis 52 where 53 name = #{name}; 54 </delete> 55 56 </mapper>
用户mapper,UserMapper.java
1 package com.xiaostudy.shiro_test1.mapper; 2 3 import com.xiaostudy.shiro_test1.entity.UserEntity; 4 import org.apache.ibatis.annotations.Mapper; 5 6 /** 7 * Created with IntelliJ IDEA. 8 * User: Administrator 9 * Date: 2019/6/8 10 * Time: 14:45 11 * Description: No Description 12 */ 13 @Mapper 14 public interface UserMapper { 15 16 // 根据用户名称,查询用户信息 17 public UserEntity findByName(String name); 18 19 // 根据用户id,查询用户信息、角色、权限 20 public UserEntity findById(String id); 21 }
测试redis的mapper,TestRedisMapper.java
1 package com.xiaostudy.shiro_test1.mapper; 2 3 import com.xiaostudy.shiro_test1.entity.TestRedisEntity; 4 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Param; 6 7 import java.util.List; 8 9 /** 10 * Created with IntelliJ IDEA. 11 * User: Administrator 12 * Date: 2019/6/8 13 * Time: 22:07 14 * Description: No Description 15 */ 16 @Mapper 17 public interface TestRedisMapper { 18 19 public List<TestRedisEntity> selectAll(); 20 21 /** 22 * 简单分页 23 * <p>@Param的作用是告诉mapper他的参数名,因为存在多个参数</p> 24 * @param page 25 * @param rows 26 * @return 27 */ 28 public List<TestRedisEntity> selectPages(@Param("page") int page, @Param("rows") int rows); 29 30 public int selectTotal(); 31 32 public TestRedisEntity selectById(int id); 33 34 public TestRedisEntity selectByName(String name); 35 36 public int insert(TestRedisEntity testRedisEntity); 37 38 public int update(TestRedisEntity testRedisEntity); 39 40 public int deleteById(int id); 41 42 public int deleteByName(String name); 43 }
用户service,UserService.java
1 package com.xiaostudy.shiro_test1.service; 2 3 import com.xiaostudy.shiro_test1.entity.UserEntity; 4 5 /** 6 * Created with IntelliJ IDEA. 7 * User: Administrator 8 * Date: 2019/6/8 9 * Time: 14:55 10 * Description: No Description 11 */ 12 public interface UserService { 13 14 UserEntity findByName(String name); 15 16 UserEntity findById(String id); 17 }
测试redis的service,TestRedisService.java
1 package com.xiaostudy.shiro_test1.service; 2 3 import com.xiaostudy.shiro_test1.entity.TestRedisEntity; 4 import com.xiaostudy.shiro_test1.entity.UserEntity; 5 6 import java.util.List; 7 8 /** 9 * Created with IntelliJ IDEA. 10 * User: Administrator 11 * Date: 2019/6/8 12 * Time: 14:55 13 * Description: No Description 14 */ 15 public interface TestRedisService { 16 17 public List<TestRedisEntity> selectAll(); 18 19 public List<TestRedisEntity> selectPages(int page, int rows); 20 21 public int selectTotal(); 22 23 public TestRedisEntity selectById(int id); 24 25 public TestRedisEntity selectByName(String name); 26 27 public int insert(TestRedisEntity testRedisEntity); 28 29 public int update(TestRedisEntity testRedisEntity); 30 31 public int deleteById(int id); 32 33 public int deleteByName(String name); 34 }
用户service实现类,UserServiceImpl.java
1 package com.xiaostudy.shiro_test1.service.impl; 2 3 import com.xiaostudy.shiro_test1.entity.UserEntity; 4 import com.xiaostudy.shiro_test1.mapper.UserMapper; 5 import com.xiaostudy.shiro_test1.service.UserService; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.stereotype.Service; 8 9 /** 10 * Created with IntelliJ IDEA. 11 * User: Administrator 12 * Date: 2019/6/8 13 * Time: 14:56 14 * Description: No Description 15 */ 16 @Service 17 public class UserServiceImpl implements UserService { 18 19 @Autowired 20 private UserMapper userMapper; 21 22 @Override 23 public UserEntity findByName(String name) { 24 return userMapper.findByName(name); 25 } 26 27 @Override 28 public UserEntity findById(String id) { 29 return userMapper.findById(id); 30 } 31 }
测试redis的service实现类,TestRedisServiceImpl.java
package com.xiaostudy.shiro_test1.service.impl; import com.xiaostudy.shiro_test1.entity.TestRedisEntity; import com.xiaostudy.shiro_test1.entity.UserEntity; import com.xiaostudy.shiro_test1.mapper.TestRedisMapper; import com.xiaostudy.shiro_test1.mapper.UserMapper; import com.xiaostudy.shiro_test1.service.TestRedisService; import com.xiaostudy.shiro_test1.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.List; /** * Created with IntelliJ IDEA. * User: Administrator * Date: 2019/6/8 * Time: 14:56 * Description: No Description */ @Service public class TestRedisServiceImpl implements TestRedisService { @Autowired private TestRedisMapper testRedisMapper; @Autowired private RedisTemplate<Object,Object> redisTemplate; @Override public List<TestRedisEntity> selectAll() { List<TestRedisEntity> redisEntityList = (List<TestRedisEntity>) redisTemplate.opsForValue().get("testRedisAll"); if(null == redisEntityList) { redisEntityList = testRedisMapper.selectAll(); redisTemplate.opsForValue().set("testRedisAll", redisEntityList); } return redisEntityList; } @Override public List<TestRedisEntity> selectPages(int page, int rows) { int current = (page-1)*rows; List<TestRedisEntity> redisEntityList = (List<TestRedisEntity>) redisTemplate.opsForValue().get("testRedisByPages_page" + page + "_rows" + rows); if(null == redisEntityList) { redisEntityList = testRedisMapper.selectPages(current, rows); redisTemplate.opsForValue().set("testRedisByPages_page" + page + "_rows" + rows, redisEntityList); } return redisEntityList; } @Override public int selectTotal() { String strTotal = (String) redisTemplate.opsForValue().get("testRedisTotal"); int total; if(null == strTotal) { total = testRedisMapper.selectTotal(); redisTemplate.opsForValue().set("testRedisTotal",String.valueOf(total)); } else { total = Integer.parseInt(strTotal); } return total; } @Override public TestRedisEntity selectById(int id) { TestRedisEntity testRedisEntity = (TestRedisEntity) redisTemplate.opsForValue().get("testRedisById_" + id); if(null == testRedisEntity) { testRedisEntity = testRedisMapper.selectById(id); redisTemplate.opsForValue().set("testRedisById_" + id, testRedisEntity); } return testRedisEntity; } @Override public TestRedisEntity selectByName(String name) { TestRedisEntity testRedisEntity = (TestRedisEntity) redisTemplate.opsForValue().get("testRedisByName_" + name); if(null == testRedisEntity) { testRedisEntity = testRedisMapper.selectByName(name); redisTemplate.opsForValue().set("testRedisByName_" + name, testRedisEntity); } return testRedisEntity; } @Override public int insert(TestRedisEntity testRedisEntity) { int insert = testRedisMapper.insert(testRedisEntity); this.closeRedis(insert, "testRedisByPages"); redisTemplate.opsForValue().set("testRedisTotal",String.valueOf(testRedisMapper.selectTotal())); return insert; } @Override public int update(TestRedisEntity testRedisEntity) { int update = testRedisMapper.update(testRedisEntity); this.closeRedis(update, "testRedisByPages"); redisTemplate.opsForValue().set("testRedisById_" + testRedisEntity.getId(), testRedisEntity); redisTemplate.opsForValue().set("testRedisByName_" + testRedisEntity.getName(), testRedisEntity); return update; } @Override public int deleteById(int id) { TestRedisEntity testRedisEntity = this.selectById(id); int deleteById = testRedisMapper.deleteById(id); this.closeRedis(deleteById, "testRedisByPages"); this.closeRedis(deleteById, "testRedisTotal"); this.closeRedis(deleteById, "testRedisById_" + id); this.closeRedis(deleteById, "testRedisByName_" + testRedisEntity.getName()); return deleteById; } @Override public int deleteByName(String name) { TestRedisEntity testRedisEntity1 = this.selectByName(name); int deleteByName = testRedisMapper.deleteByName(name); this.closeRedis(deleteByName, "testRedisByPages"); this.closeRedis(deleteByName, "testRedisTotal"); this.closeRedis(deleteByName, "testRedisByName_" + name); this.closeRedis(deleteByName, "testRedisById_" + testRedisEntity1.getId()); return deleteByName; } /** * 清空对应实体的缓存 * @param count */ private void closeRedis(int count, String str) { if(0 != count) { redisTemplate.delete(redisTemplate.keys(str + "*")); } } }
用户登录controller,MainController.java
1 package com.xiaostudy.shiro_test1.web.controller; 2 3 import org.apache.shiro.SecurityUtils; 4 import org.apache.shiro.authc.AuthenticationException; 5 import org.apache.shiro.authc.IncorrectCredentialsException; 6 import org.apache.shiro.authc.UnknownAccountException; 7 import org.apache.shiro.authc.UsernamePasswordToken; 8 import org.apache.shiro.subject.Subject; 9 import org.springframework.stereotype.Controller; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 15 /** 16 * 用户登录、登出、错误页面跳转控制器 17 * Created with IntelliJ IDEA. 18 * User: Administrator 19 * Date: 2019/6/8 20 * Time: 15:15 21 * Description: No Description 22 */ 23 @Controller 24 public class MainController { 25 26 @RequestMapping("/index") 27 public String index(HttpServletRequest request, HttpServletResponse response){ 28 response.setHeader("root", request.getContextPath()); 29 return "index"; 30 } 31 32 @RequestMapping("/login") 33 public String login(HttpServletRequest request, HttpServletResponse response){ 34 response.setHeader("root", request.getContextPath()); 35 String userName = request.getParameter("username"); 36 String password = request.getParameter("password"); 37 38 // 等于null说明用户没有登录,只是拦截所有请求到这里,那就直接让用户去登录页面,就不认证了。 39 // 如果这里不处理,那个会返回用户名不存在,逻辑上不合理,用户还没登录怎么就用户名不存在? 40 if(null == userName) { 41 return "login"; 42 } 43 44 // 1.获取Subject 45 Subject subject = SecurityUtils.getSubject(); 46 // 2.封装用户数据 47 UsernamePasswordToken token = new UsernamePasswordToken(userName, password); 48 // 3.执行登录方法 49 try{ 50 subject.login(token); 51 return "redirect:/index"; 52 } catch (UnknownAccountException e){ 53 // 这里是捕获自定义Realm的用户名不存在异常 54 request.setAttribute("msg","用户名不存在!"); 55 } catch (IncorrectCredentialsException e){ 56 request.setAttribute("userName",userName); 57 request.setAttribute("msg","密码错误!"); 58 } catch (AuthenticationException e) { 59 // 这里是捕获自定义Realm的认证失败异常 60 request.setAttribute("msg","认证失败!"); 61 } 62 63 return "login"; 64 } 65 66 @RequestMapping("/logout") 67 public String logout(){ 68 Subject subject = SecurityUtils.getSubject(); 69 if (subject != null) { 70 subject.logout(); 71 } 72 // return "redirect:/main"; 73 return "login"; 74 } 75 76 @RequestMapping("/error/unAuth") 77 public String unAuth(){ 78 return "/error/unAuth"; 79 } 80 81 @RequestMapping("/err") 82 public String err(){ 83 return "/error/unAuth"; 84 } 85 }
用户权限controller,UserController.java
1 package com.xiaostudy.shiro_test1.web.controller; 2 3 import com.xiaostudy.shiro_test1.entity.UserEntity; 4 import org.apache.shiro.SecurityUtils; 5 import org.apache.shiro.authz.annotation.RequiresPermissions; 6 import org.springframework.stereotype.Controller; 7 import org.springframework.web.bind.annotation.RequestMapping; 8 9 import javax.servlet.http.HttpServletRequest; 10 11 /** 12 * 用户页面跳转 13 * Created with IntelliJ IDEA. 14 * User: Administrator 15 * Date: 2019/6/8 16 * Time: 15:21 17 * Description: No Description 18 */ 19 @Controller 20 public class UserController { 21 22 /** 23 * 个人中心,需认证可访问 24 */ 25 @RequestMapping("/user/index") 26 @RequiresPermissions(value = "user")// 这里的user,就是对应权限实体类PermissionEntity的字段url,自定义Realm类UserRealm里是用这个字段 27 public String add(HttpServletRequest request){ 28 UserEntity bean = (UserEntity) SecurityUtils.getSubject().getPrincipal(); 29 request.setAttribute("userName", bean.getName()); 30 return "/user/index"; 31 } 32 33 /** 34 * 会员中心,需认证且角色为vip可访问 35 */ 36 @RequestMapping("/vip/index") 37 @RequiresPermissions(value = "vip") 38 public String update(){ 39 return "/vip/index"; 40 } 41 }
测试redis的controller,TestRedisController.java
1 package com.xiaostudy.shiro_test1.web.controller; 2 3 import com.xiaostudy.shiro_test1.entity.TestRedisEntity; 4 import com.xiaostudy.shiro_test1.entity.UserEntity; 5 import com.xiaostudy.shiro_test1.service.TestRedisService; 6 import org.apache.shiro.SecurityUtils; 7 import org.apache.shiro.authz.annotation.RequiresPermissions; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.stereotype.Controller; 10 import org.springframework.ui.Model; 11 import org.springframework.web.bind.annotation.RequestMapping; 12 import org.springframework.web.bind.annotation.ResponseBody; 13 14 import javax.servlet.http.HttpServletRequest; 15 import java.util.HashMap; 16 import java.util.List; 17 import java.util.Map; 18 19 /** 20 * 用户页面跳转 21 * Created with IntelliJ IDEA. 22 * User: Administrator 23 * Date: 2019/6/8 24 * Time: 15:21 25 * Description: No Description 26 */ 27 @Controller 28 @RequestMapping("/testRedis") 29 public class TestRedisController { 30 31 @Autowired 32 private TestRedisService testRedisService; 33 34 @RequestMapping("/index") 35 public String index() { 36 return "testRedis/index"; 37 } 38 39 @RequestMapping("/all") 40 @ResponseBody 41 public Map getTestRedisAll() { 42 List<TestRedisEntity> redisEntityList = testRedisService.selectAll(); 43 Map map = new HashMap(); 44 map.put("redisEntityList", redisEntityList); 45 return map; 46 } 47 48 @RequestMapping("/pages") 49 @ResponseBody 50 public Map getTestRedisPages(String page, String rows) { 51 List<TestRedisEntity> redisEntityList = testRedisService.selectPages(Integer.parseInt(page), Integer.parseInt(rows)); 52 int total = testRedisService.selectTotal(); 53 Map map = new HashMap(); 54 map.put("redisEntityList", redisEntityList); 55 map.put("pages", total/Integer.parseInt(rows)+((total%Integer.parseInt(rows) == 0) ? 0 : 1)); 56 map.put("total", total); 57 map.put("current", Integer.parseInt(page)); 58 return map; 59 } 60 61 @RequestMapping("/getByName") 62 @ResponseBody 63 public Map getByName(String name) { 64 TestRedisEntity testRedisEntity = testRedisService.selectByName(name); 65 Map map = new HashMap(); 66 map.put("redisEntity", testRedisEntity); 67 return map; 68 } 69 70 @RequestMapping("/get") 71 @ResponseBody 72 public Map getTestRedisByName(String name) { 73 TestRedisEntity testRedisEntity = testRedisService.selectByName(name); 74 Map map = new HashMap(); 75 map.put("testRedisEntity", testRedisEntity); 76 return map; 77 } 78 79 @RequestMapping("/insert") 80 @ResponseBody 81 @RequiresPermissions(value = "vip") 82 public Map insertTestRedis(TestRedisEntity testRedisEntity) { 83 int insert = testRedisService.insert(testRedisEntity); 84 Map map = new HashMap(); 85 map.put("result", insert); 86 return map; 87 } 88 89 @RequestMapping("/update") 90 @ResponseBody 91 @RequiresPermissions(value = "vip") 92 public Map updateTestRedis(TestRedisEntity testRedisEntity) { 93 int update = testRedisService.update(testRedisEntity); 94 Map map = new HashMap(); 95 map.put("result", update); 96 return map; 97 } 98 99 @RequestMapping("/deleteById") 100 @ResponseBody 101 @RequiresPermissions(value = "vip") 102 public Map deleteById(String id) { 103 int deleteById = testRedisService.deleteById(Integer.parseInt(id)); 104 Map map = new HashMap(); 105 map.put("result", deleteById); 106 return map; 107 } 108 109 @RequestMapping("/deleteByName") 110 @ResponseBody 111 @RequiresPermissions(value = "vip") 112 public Map deleteByName(String name) { 113 int deleteByName = testRedisService.deleteByName(name); 114 Map map = new HashMap(); 115 map.put("result", deleteByName); 116 return map; 117 } 118 119 @RequestMapping("/form") 120 public String form() { 121 return "testRedis/form"; 122 } 123 }
springboot启动类,ShiroTest1Application.java添加自定义序列化类bean,不要这个也可以,但是在redis上看就是\x\x\x之类
1 package com.xiaostudy.shiro_test1; 2 3 import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 import com.fasterxml.jackson.annotation.PropertyAccessor; 5 import com.fasterxml.jackson.databind.ObjectMapper; 6 import org.springframework.boot.SpringApplication; 7 import org.springframework.boot.autoconfigure.SpringBootApplication; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.data.redis.connection.RedisConnectionFactory; 10 import org.springframework.data.redis.core.RedisTemplate; 11 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 12 import org.springframework.data.redis.serializer.StringRedisSerializer; 13 14 @SpringBootApplication 15 //@MapperScan(basePackages = "com.xiaostudy.shiro_test1.mapper") 16 public class ShiroTest1Application { 17 18 public static void main(String[] args) { 19 SpringApplication.run(ShiroTest1Application.class, args); 20 } 21 22 /** 23 * redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类 24 * @param redisConnectionFactory 25 * @return 26 */ 27 @Bean 28 public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { 29 RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); 30 redisTemplate.setConnectionFactory(redisConnectionFactory); 31 32 // 使用Jackson2JsonRedisSerialize 替换默认序列化 33 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 34 35 ObjectMapper objectMapper = new ObjectMapper(); 36 objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 37 objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 38 39 jackson2JsonRedisSerializer.setObjectMapper(objectMapper); 40 41 // 设置value的序列化规则和 key的序列化规则 42 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); 43 redisTemplate.setKeySerializer(new StringRedisSerializer()); 44 redisTemplate.afterPropertiesSet(); 45 return redisTemplate; 46 } 47 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 5 version="4.0"> 6 <display-name>Archetype Created Web Application</display-name> 7 8 <!--请求编码设置--> 9 <filter> 10 <filter-name>encodingFilter</filter-name> 11 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 12 <init-param> 13 <param-name>encoding</param-name> 14 <param-value>UTF-8</param-value> 15 </init-param> 16 <init-param> 17 <param-name>forceEncoding</param-name> 18 <param-value>true</param-value> 19 </init-param> 20 </filter> 21 <filter-mapping> 22 <filter-name>encodingFilter</filter-name> 23 <url-pattern>/*</url-pattern> 24 </filter-mapping> 25 26 <listener> 27 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 28 </listener> 29 <listener> 30 <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> 31 </listener> 32 <servlet> 33 <servlet-name>SpringMVC</servlet-name> 34 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 35 <init-param> 36 <param-name>contextConfigLocation</param-name> 37 <param-value>classpath:spring-mvc.xml</param-value> 38 </init-param> 39 <load-on-startup>1</load-on-startup> 40 <async-supported>true</async-supported> 41 </servlet> 42 <servlet-mapping> 43 <servlet-name>SpringMVC</servlet-name> 44 <url-pattern>/</url-pattern> 45 </servlet-mapping> 46 <welcome-file-list> 47 <welcome-file>/index</welcome-file> 48 </welcome-file-list> 49 50 <servlet-mapping> 51 <servlet-name>default</servlet-name> 52 <url-pattern>*.css</url-pattern> 53 </servlet-mapping> 54 <servlet-mapping> 55 <servlet-name>default</servlet-name> 56 <url-pattern>*.gif</url-pattern> 57 </servlet-mapping> 58 <servlet-mapping> 59 <servlet-name>default</servlet-name> 60 <url-pattern>*.jpg</url-pattern> 61 </servlet-mapping> 62 <servlet-mapping> 63 <servlet-name>default</servlet-name> 64 <url-pattern>*.js</url-pattern> 65 </servlet-mapping> 66 </web-app>
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!-- 把Controller交给spring管理 --> <context:component-scan base-package="com.xiaostudy"/> <!-- 配置注解处理器映射器 功能:寻找执行类Controller --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 配置注解处理器适配器 功能:调用controller方法,执行controller --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> <!-- 配置sprigmvc视图解析器:解析逻辑试图 后台返回逻辑试图:index 视图解析器解析出真正物理视图:前缀+逻辑试图+后缀====/WEB-INF/index.jsp --> <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean>--> </beans>
application.yml
1 spring: 2 datasource: 3 url: jdbc:mysql://localhost:3306/my_test?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 4 username: root 5 password: root 6 driver-class-name: com.mysql.cj.jdbc.Driver 7 type: com.alibaba.druid.pool.DruidDataSource 8 # 初始化时建立物理连接连接的个数 9 initialSize: 5 10 # 最小连接池数量 11 minIdle: 5 12 # 最大连接池数量 13 maxActive: 20 14 # 获取连接时最大等待时间(ms),即60s 15 maxWait: 60000 16 # 1.Destroy线程会检测连接的间隔时间;2.testWhileIdle的判断依据 17 timeBetweenEvictionRunsMillis: 60000 18 # 最小生存时间ms 19 minEvictableIdleTimeMillis: 600000 20 maxEvictableIdleTimeMillis: 900000 21 # 用来检测连接是否有效的sql 22 validationQuery: SELECT 1 FROM DUAL 23 # 申请连接时执行validationQuery检测连接是否有效,启用会降低性能 24 testOnBorrow: false 25 # 归还连接时执行validationQuery检测连接是否有效,启用会降低性能 26 testOnReturn: false 27 # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis, 28 # 执行validationQuery检测连接是否有效,不会降低性能 29 testWhileIdle: true 30 # 是否缓存preparedStatement,mysql建议关闭 31 poolPreparedStatements: false 32 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 33 filters: stat,wall,log4j 34 thymeleaf: 35 suffix: .html 36 charset: utf-8 37 #清除缓存,实现热部署 38 cache: false 39 mvc: 40 # 配置静态资源映射路径,/public、/resources路径失效 41 static-path-pattern: templates/** 42 43 #redis配置 44 redis: 45 host: 127.0.0.1 46 port: 6379 47 password: 48 database: 2 49 timeout: 3000ms 50 jedis: 51 pool: 52 max-active: 200 53 max-idle: 100 54 min-idle: 1 55 max-wait: 3000ms 56 57 mybatis: 58 mapper-locations: classpath:mapper/*.xml 59 # mapperLocations: classpath:mapper/*.xml 60 # 虽然可以配置这项来进行pojo包扫描,但其实我更倾向于在mapper.xml写全类名 61 # type-aliases-package: com.xiaostudy.shiro_test1.entity 62 63 # 后台打印sql 64 logging: 65 level: 66 com.xiaostudy.shiro_test1.mapper : debug
登录页面,login.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>登录</title> 6 </head> 7 <body> 8 <h1>用户登录</h1> 9 <hr> 10 <form id="from" action="/login" method="post"> 11 <table> 12 <tr> 13 <td>用户名</td> 14 <td> 15 <input type="text" name="username" placeholder="请输入账户名" value="" th:value="${userName }"/> 16 </td> 17 </tr> 18 <tr> 19 <td>密码</td> 20 <td> 21 <input type="password" name="password" placeholder="请输入密码"/> 22 </td> 23 </tr> 24 <tr> 25 <td colspan="2"> 26 <span style="color: red;">[[${msg }]]</span> 27 </td> 28 </tr> 29 <tr> 30 <td colspan="2"> 31 <input type="submit" value="登录"/> 32 <input type="reset" value="重置"/> 33 </td> 34 </tr> 35 </table> 36 </form> 37 </body> 38 </html>
主页,index.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org" 3 xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> 4 5 <head> 6 <title>首页</title> 7 </head> 8 <body> 9 <h1>首页</h1> 10 <hr> 11 <ul> 12 <li><a href="user/index">个人中心</a></li> 13 <li><a href="vip/index">会员中心</a></li> 14 <p shiro:hasPermission="svip"><li>这是svip能看到的p标签</li></p> 15 <shiro:hasPermission name="vip"><li>这是vip能看到的</li></shiro:hasPermission> 16 <shiro:hasPermission name="svip"><li>这是svip能看到的</li></shiro:hasPermission> 17 <li><a href="testRedis/index">测试redis主页</a></li> 18 <li><a href="logout">退出登录</a></li> 19 </ul> 20 </body> 21 </html>
通过认证后普通用户可以访问,user/index.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <title>用户中心</title> 5 </head> 6 <body> 7 <h1>用户中心</h1> 8 <hr> 9 <h1>欢迎[[${userName }]],这里是用户中心</h1> 10 </body> 11 </html>
通过认证后,vip用户可以访问,vip/index.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <title>会员中心</title> 5 </head> 6 <body> 7 <h1>会员中心</h1> 8 <hr> 9 <h1>欢迎来到<span style="color: red;">会员中心</span></h1> 10 </body> 11 </html>
认证通过后,普通用户访问vip页面时跳转提示没有权限,error/unAuth.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <title>未授权提示</title> 5 </head> 6 <body> 7 <h1>您还不是<span style="color: red;">会员</span> ,没有权限访问这个页面!</h1> 8 </body> 9 </html>
认证通过后,所有用户可以访问,测试redis主页,testRedis/index.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org" 3 xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> 4 5 <head> 6 <title>首页</title> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <meta http-equiv="X-UA-Compatible" content="IE=8"> 9 <meta http-equiv="Expires" content="0"> 10 <meta http-equiv="Pragma" content="no-cache"> 11 <meta http-equiv="Cache-control" content="no-cache"> 12 <meta http-equiv="Cache" content="no-cache"> 13 14 <script src="" th:src="@{/statics/js/jquery-3.0.0.js}"></script> 15 <!--jqueryui--> 16 <link href="//cdn.bootcss.com/jqueryui/1.12.0-rc.2/jquery-ui.min.css" th:href="@{/statics/jquery-ui-1.12.0-rc.2/jquery-ui.min.css}" rel="stylesheet"> 17 <!--jqgrid的css--> 18 <link href="//cdn.bootcss.com/jqgrid/4.6.0/css/ui.jqgrid.css" th:href="@{/statics/jquery.jqGrid-4.6.0/css/ui.jqgrid.css}" rel="stylesheet"> 19 20 <!--locale--> 21 <script src="//cdn.bootcss.com/jqgrid/4.6.0/js/i18n/grid.locale-en.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/i18n/grid.locale-en.js}"></script> 22 <!--jqgrid的js--> 23 <script src="//cdn.bootcss.com/jqgrid/4.6.0/js/jquery.jqGrid.min.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/jquery.jqGrid.min.js}"></script> 24 <link href="" th:href="@{/statics/layui/css/layui.css}" rel="stylesheet"> 25 <script src="" th:src="@{/statics/layui/layui.all.js}"></script> 26 </head> 27 <body> 28 <h1>测试redis</h1> 29 <hr> 30 <shiro:hasPermission name="vip"> 31 <button type="button" class="layui-btn" title="添加" onclick="create()">添加</button> 32 </shiro:hasPermission> 33 <shiro:hasPermission name="vip"> 34 <input type="hidden" id="vip"> 35 </shiro:hasPermission> 36 <shiro:hasPermission name="svip"> 37 <input type="hidden" id="svip"> 38 </shiro:hasPermission> 39 <table id="jqGrid" class="layui-table layui-table-grid"></table> 40 <div id="jqGridPager"></div> 41 </body> 42 </html> 43 44 45 <script> 46 $(function () { 47 $("#jqGrid").jqGrid({ 48 url : '[[${#httpServletRequest.getContextPath()}]]/testRedis/pages', 49 datatype : "json", 50 colModel : [ 51 { label: 'ID', name: 'id', width: 80, hidden:true }, 52 { label: "名称", name: "name", "align": "center", width: 100}, 53 { label: "密码 ", name: "password", "align": "center", width: 100}, 54 { label: "操作 ", name: "id", "align": "center", width: 100, formatter: operation} 55 ], 56 viewrecords : true, 57 height : 300, 58 rowNum : 5, 59 rowList : [5,10,15,20,30,50], 60 rownumbers : true, 61 rownumWidth : 35, 62 autowidth : true, 63 multiselect : true, 64 pager : "#jqGridPager", 65 jsonReader : { 66 root : "redisEntityList", 67 page : "current", 68 total : "pages", 69 records : "total" 70 }, 71 prmNames : { 72 page : "page", 73 rows : "rows", 74 order : "order" 75 }, 76 postData:{ 77 78 }, 79 gridComplete : function() { 80 // 隐藏grid底部滚动条 81 $("#jqGrid").closest(".ui-jqgrid-bdiv").css({ 82 "overflow-x" : "hidden" 83 }); 84 //设置行高 85 var grid = $("#jqGrid"); 86 var ids = grid.getDataIDs(); 87 for (var i = 0; i < ids.length; i++) { 88 grid.setRowData ( ids[i], false, {height: 10} ); 89 } 90 }, 91 beforeRequest : function (){ 92 var current=$(this).getGridParam("page");//当前页 93 var total= $(this).getGridParam('lastpage'); //获取总页数 94 if(current > total && total!=0){ 95 //设置页码为最后一页 并重新加载 96 var postDatas = $(this).jqGrid("getGridParam", "postData"); 97 postDatas['page']=total; 98 $(this).setGridParam({postData:postDatas}); 99 } 100 }, 101 ondblClickRow : function(rowid) { 102 view(rowid); 103 /*if(!ondblClickRowSubTable){ 104 archivesFolderJs.view(rowid); 105 }else{ 106 ondblClickRowSubTable = false; 107 }*/ 108 } 109 }); 110 111 function operation(id) { 112 /*var hrml2 = 113 ' <div class="layui-btn-group">' + 114 ' <button type="button" class="layui-btn" title="查看" onclick="view(\''+id+'\')">查看</button>' + 115 ' <button type="button" class="layui-btn" title="编辑" onclick="update(\''+id+'\')">编辑</button>' + 116 ' <button type="button" class="layui-btn" title="删除" onclick="deleteById(\''+id+'\')">删除</button>';*/ 117 var hrml2 = 118 ' <div class="layui-btn-group">' + 119 ' <button type="button" class="layui-btn" title="查看" onclick="view(\''+id+'\')">查看</button>'; 120 if($("#vip").length>0) { 121 hrml2 = hrml2 + '<button type="button" class="layui-btn" title="编辑" onclick="update(\''+id+'\')">编辑</button>' 122 + '<button type="button" class="layui-btn" title="删除" onclick="deleteById(\''+id+'\')">删除</button>'; 123 } 124 return hrml2; 125 } 126 }); 127 128 function create() { 129 var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; 130 131 var title ="添加"; 132 var btns = [ '确认', '关闭' ]; 133 var width ='700px'; 134 var height = '200px'; 135 var operation = "add"; 136 open(2, title, width, height, 0.5, false, content, btns, operation, ""); 137 } 138 139 function view(id) { 140 var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; 141 142 var title ="查看"; 143 var btns = [ '关闭' ]; 144 var width ='700px'; 145 var height = '200px'; 146 var operation = "view"; 147 open(2, title, width, height, 0.5, false, content, btns, operation, id); 148 } 149 150 function update(id) { 151 var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; 152 153 var title ="修改"; 154 var btns = [ '确认', '关闭' ]; 155 var width ='700px'; 156 var height = '200px'; 157 var operation = "update"; 158 open(2, title, width, height, 0.5, false, content, btns, operation, id); 159 } 160 161 function deleteById(id) { 162 var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; 163 164 layer.confirm('确认删除?', { 165 btn: ['确定','取消'] //按钮 166 }, function(){ 167 $.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/deleteById?id=" + id 168 + "&_=" + new Date().getTime(), function (r) { 169 layer.closeAll(); 170 if(r.result == 1) { 171 layui.layer.msg("删除成功"); 172 $("#jqGrid").jqGrid().trigger("reloadGrid"); 173 } else { 174 layui.layer.msg("删除失败"); 175 } 176 }); 177 }, function(){ 178 // 点击取消事件 179 }); 180 } 181 182 function open(type, title, width, height, shade, maxmin, content, btns, operation, id) { 183 layui.use('layer', function() { 184 var layer = layui.layer; 185 parent.layer.open({ 186 type: type, 187 title: title, 188 area: [width, height], 189 shade: shade, 190 maxmin: maxmin, 191 content: content, 192 btn: btns, 193 yes: function (index, layero) { 194 var selector = layero["selector"]; 195 selector = "#layui-layer-iframe" + selector.substring("#layui-layer".length, selector.length); 196 var name = parent.$(selector).contents().find("#name").val(); 197 var password = parent.$(selector).contents().find("#password").val(); 198 if(undefined == name || null == name || "" == name) { 199 layui.layer.msg("请输入名称"); 200 return; 201 } 202 if(undefined == password || null == password || "" == password) { 203 layui.layer.msg("请输入密码"); 204 return; 205 } 206 if("add" == operation) { 207 $.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/getByName?name=" + name 208 + "&_=" + new Date().getTime(), function (r) { 209 if(null != r.redisEntity && r.redisEntity.name == name) { 210 layui.layer.msg("名称已存在"); 211 return; 212 } else { 213 $.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/insert?name=" + name 214 + "&password=" + password + "&_=" + new Date().getTime(), function (r) { 215 if(r.result == 1) { 216 layer.closeAll(); 217 layui.layer.msg("添加成功"); 218 $("#jqGrid").jqGrid().trigger("reloadGrid"); 219 } else { 220 layui.layer.msg("添加失败"); 221 } 222 }); 223 } 224 }); 225 } else if("update" == operation) { 226 $.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/update?id=" + id + "&name=" + name 227 + "&password=" + password + "&_=" + new Date().getTime(), function (r) { 228 if(r.result == 1) { 229 layer.closeAll(); 230 layui.layer.msg("修改成功"); 231 $("#jqGrid").jqGrid().trigger("reloadGrid"); 232 } else { 233 layui.layer.msg("修改失败"); 234 } 235 }); 236 } else { 237 layer.closeAll(); 238 } 239 }, 240 241 btn3: function () { 242 parent.layer.closeAll(); 243 return false; 244 }, 245 zIndex: 999, 246 success: function (layero) { 247 // 弹出窗弹出之前设置数据到弹出窗页面 248 if("update" == operation) { 249 var selector = layero["selector"]; 250 selector = "#layui-layer-iframe" + selector.substring("#layui-layer".length, selector.length); 251 parent.$(selector).contents().find("#id").val(id); 252 var rowData = $("#jqGrid").jqGrid('getRowData',id); 253 parent.$(selector).contents().find("#name").val(rowData.name); 254 parent.$(selector).contents().find("#password").val(rowData.password); 255 } else if("view" == operation) { 256 var selector = layero["selector"]; 257 selector = "#layui-layer-iframe" + selector.substring("#layui-layer".length, selector.length); 258 parent.$(selector).contents().find("#id").val(id); 259 var rowData = $("#jqGrid").jqGrid('getRowData',id); 260 var name = parent.$(selector).contents().find("#name"); 261 name.val(rowData.name); 262 var password = parent.$(selector).contents().find("#password"); 263 password.val(rowData.password); 264 name.attr("onfocus", "this.blur()"); 265 password.attr("onfocus", "this.blur()"); 266 name.css("background", "#CCCCCC"); 267 name.css("cursor", "not-allowed"); 268 password.css("background", "#CCCCCC"); 269 password.css("cursor", "not-allowed"); 270 /*name.attr("disabled", "disabled"); 271 password.attr("disabled", "disabled");*/ 272 } 273 } 274 }); 275 }); 276 } 277 </script>
测试redis主页,添加、修改、查看的form页面,testRedis/form.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org" 3 xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> 4 <head> 5 <meta charset="UTF-8"> 6 <title>Title</title> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <meta http-equiv="X-UA-Compatible" content="IE=8"> 9 <meta http-equiv="Expires" content="0"> 10 <meta http-equiv="Pragma" content="no-cache"> 11 <meta http-equiv="Cache-control" content="no-cache"> 12 <meta http-equiv="Cache" content="no-cache"> 13 14 <script src="" th:src="@{/statics/js/jquery-3.0.0.js}"></script> 15 <!--jqueryui--> 16 <link href="//cdn.bootcss.com/jqueryui/1.12.0-rc.2/jquery-ui.min.css" th:href="@{/statics/jquery-ui-1.12.0-rc.2/jquery-ui.min.css}" rel="stylesheet"> 17 <!--jqgrid的css--> 18 <link href="//cdn.bootcss.com/jqgrid/4.6.0/css/ui.jqgrid.css" th:href="@{/statics/jquery.jqGrid-4.6.0/css/ui.jqgrid.css}" rel="stylesheet"> 19 20 <!--locale--> 21 <script src="//cdn.bootcss.com/jqgrid/4.6.0/js/i18n/grid.locale-en.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/i18n/grid.locale-en.js}"></script> 22 <!--jqgrid的js--> 23 <script src="//cdn.bootcss.com/jqgrid/4.6.0/js/jquery.jqGrid.min.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/jquery.jqGrid.min.js}"></script> 24 <link href="" th:href="@{/statics/layui/css/layui.css}" rel="stylesheet"> 25 <script src="" th:src="@{/statics/layui/layui.all.js}"></script> 26 </head> 27 <body> 28 <div class="layui-form" style="margin-top: 30px;margin-right: 20px;"> 29 <div class="layui-form-item"> 30 <input type="hidden" id="id" name="id" value=""> 31 <label class="layui-form-label">名称</label> 32 <div class="layui-input-inline"> 33 <input type="text" id="name" name="name" required lay-verify="required" placeholder="名称" autocomplete="off" class="layui-input"> 34 </div> 35 <label class="layui-form-label">密码</label> 36 <div class="layui-input-inline"> 37 <input type="text" id="password" name="password" required lay-verify="required" placeholder="密码" autocomplete="off" class="layui-input"> 38 </div> 39 </div> 40 </div> 41 42 <script> 43 //Demo 44 layui.use('form', function(){ 45 var form = layui.form; 46 47 //监听提交 48 form.on('submit(formDemo)', function(data){ 49 layer.msg(JSON.stringify(data.field)); 50 return false; 51 }); 52 }); 53 </script> 54 </body> 55 </html>
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-parent</artifactId> 8 <version>2.1.5.RELEASE</version> 9 <relativePath/> <!-- lookup parent from repository --> 10 </parent> 11 <groupId>com.xiaostudy</groupId> 12 <artifactId>shiro_test1</artifactId> 13 <version>0.0.1-SNAPSHOT</version> 14 <name>shiro_test1</name> 15 <description>Demo project for Spring Boot</description> 16 17 <properties> 18 <java.version>1.8</java.version> 19 </properties> 20 21 <dependencies> 22 <dependency> 23 <groupId>org.springframework.boot</groupId> 24 <artifactId>spring-boot-starter-jdbc</artifactId> 25 </dependency> 26 <dependency> 27 <groupId>org.springframework.boot</groupId> 28 <artifactId>spring-boot-starter-thymeleaf</artifactId> 29 </dependency> 30 <dependency> 31 <groupId>org.springframework.boot</groupId> 32 <artifactId>spring-boot-starter-web</artifactId> 33 </dependency> 34 <dependency> 35 <groupId>org.mybatis.spring.boot</groupId> 36 <artifactId>mybatis-spring-boot-starter</artifactId> 37 <version>2.0.1</version> 38 </dependency> 39 40 <dependency> 41 <groupId>mysql</groupId> 42 <artifactId>mysql-connector-java</artifactId> 43 <scope>runtime</scope> 44 </dependency> 45 <dependency> 46 <groupId>org.springframework.boot</groupId> 47 <artifactId>spring-boot-starter-test</artifactId> 48 <scope>test</scope> 49 </dependency> 50 51 <!-- 数据库连接池 --> 52 <dependency> 53 <groupId>com.alibaba</groupId> 54 <artifactId>druid</artifactId> 55 <version>1.1.10</version> 56 </dependency> 57 <!-- Shiro --> 58 <dependency> 59 <groupId>org.apache.shiro</groupId> 60 <artifactId>shiro-spring</artifactId> 61 <version>1.3.2</version> 62 </dependency> 63 <!-- log4j --> 64 <dependency> 65 <groupId>log4j</groupId> 66 <artifactId>log4j</artifactId> 67 <version>1.2.17</version> 68 </dependency> 69 70 <dependency> 71 <groupId>com.github.theborakompanioni</groupId> 72 <artifactId>thymeleaf-extras-shiro</artifactId> 73 <version>2.0.0</version> 74 </dependency> 75 76 <!--热部署--> 77 <dependency> 78 <groupId>org.springframework.boot</groupId> 79 <artifactId>spring-boot-devtools</artifactId> 80 <scope>runtime</scope> 81 </dependency> 82 83 <!-- redis 包 --> 84 <dependency> 85 <groupId>org.springframework.boot</groupId> 86 <artifactId>spring-boot-starter-data-redis</artifactId> 87 <version>1.4.7.RELEASE</version> 88 </dependency> 89 </dependencies> 90 91 <build> 92 <plugins> 93 <plugin> 94 <groupId>org.springframework.boot</groupId> 95 <artifactId>spring-boot-maven-plugin</artifactId> 96 </plugin> 97 </plugins> 98 </build> 99 100 </project>
数据库表创建
用户表、角色表、权限表、用户与角色多对多表、角色与权限多对多表
1 DROP TABLE IF EXISTS `role_permission`; 2 DROP TABLE IF EXISTS `permission`; 3 DROP TABLE IF EXISTS `user_role`; 4 DROP TABLE IF EXISTS `role`; 5 DROP TABLE IF EXISTS `user`; 6 7 CREATE TABLE `user` ( 8 `id` VARCHAR(255) PRIMARY KEY, 9 `name` VARCHAR(255), 10 `password` VARCHAR(255) 11 ) engine = InnoDB default charset = utf8 comment = '用户表'; 12 13 CREATE TABLE `role` ( 14 `id` VARCHAR(255) PRIMARY KEY, 15 `name` VARCHAR(255) 16 ) engine = InnoDB default charset = utf8 comment = '角色表'; 17 18 CREATE TABLE `user_role` ( 19 `id` VARCHAR(255) PRIMARY KEY, 20 `user_id` VARCHAR(255), 21 `role_id` VARCHAR(255), 22 FOREIGN KEY (`user_id`) REFERENCES `user`(id), 23 FOREIGN KEY (`role_id`) REFERENCES `role`(id) 24 ) engine = InnoDB default charset = utf8 comment = '用户与角色多对多表'; 25 26 CREATE TABLE `permission` ( 27 `id` VARCHAR(255) PRIMARY KEY, 28 `name` VARCHAR(255), 29 `url` VARCHAR(255) 30 ) engine = InnoDB default charset = utf8 comment = '权限表'; 31 32 CREATE TABLE `role_permission` ( 33 `id` VARCHAR(255) PRIMARY KEY, 34 `role_id` VARCHAR(255), 35 `permission_id` VARCHAR(255), 36 FOREIGN KEY (`role_id`) REFERENCES `role`(id), 37 FOREIGN KEY (`permission_id`) REFERENCES `permission`(id) 38 ) engine = InnoDB default charset = utf8 comment = '角色与权限多对多表'; 39 40 insert into `user` (`id`, `name`, `password`) values('1','admin','123456'); 41 insert into `user` (`id`, `name`, `password`) values('2','vip','123456'); 42 insert into `user` (`id`, `name`, `password`) values('3','svip','1234'); 43 44 insert into `role` (`id`, `name`) values('1','user'); 45 insert into `role` (`id`, `name`) values('2','vip'); 46 insert into `role` (`id`, `name`) values('3','svip'); 47 48 insert into `permission` (`id`, `name`, `url`) values('1','user','user'); 49 insert into `permission` (`id`, `name`, `url`) values('2','vip','vip'); 50 insert into `permission` (`id`, `name`, `url`) values('3','svip','svip'); 51 52 insert into `user_role` (`id`, `user_id`, `role_id`) values('1','1','1'); 53 insert into `user_role` (`id`, `user_id`, `role_id`) values('2','2','1'); 54 insert into `user_role` (`id`, `user_id`, `role_id`) values('3','2','2'); 55 insert into `user_role` (`id`, `user_id`, `role_id`) values('4','3','1'); 56 insert into `user_role` (`id`, `user_id`, `role_id`) values('5','3','2'); 57 insert into `user_role` (`id`, `user_id`, `role_id`) values('6','3','3'); 58 59 insert into `role_permission` (`id`, `role_id`, `permission_id`) values('1','1','1'); 60 insert into `role_permission` (`id`, `role_id`, `permission_id`) values('2','2','1'); 61 insert into `role_permission` (`id`, `role_id`, `permission_id`) values('3','2','2'); 62 insert into `role_permission` (`id`, `role_id`, `permission_id`) values('4','3','1'); 63 insert into `role_permission` (`id`, `role_id`, `permission_id`) values('5','3','2'); 64 insert into `role_permission` (`id`, `role_id`, `permission_id`) values('6','3','3');
测试redis表
1 DROP TABLE IF EXISTS `test_redis`; 2 3 CREATE TABLE `test_redis` ( 4 `id` int(11) PRIMARY KEY auto_increment, 5 `name` VARCHAR(255), 6 `password` VARCHAR(255) 7 ) engine = InnoDB default charset = utf8 comment = '测试redis表';
3、layui与jqGrid相关下载
layui官网下载:https://www.layui.com/
jqGrid官网下载:http://www.trirand.com/blog/?page_id=6
jqueryUI官网下载:http://jqueryui.com/download/all/
jquery下载:http://www.jq22.com/jquery-info122
4、测试
测试权限的就不在这里重复测试了,可以看一下之前写的文章【直接看最后的测试】:https://www.cnblogs.com/xiaostudy/p/10990999.html