springboot与redis
该项目已上传至GitHub:https://github.com/xiaostudy/springboot_redis
用到的框架技术有:springboot、mybatis、shiro、redis
前端有:layui、jqGrid
这里先不讲redis在Windows安装,比较简单,百度看一下其他文章就可以了,有空这里也可以补一个教程。
1、先看项目目录
2、下面放源码
实体类,权限PermissionEntity.java
package com.xiaostudy.shiro_test1.entity; import java.io.Serializable; /**
* 权限实体类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:21
* Description: No Description
*/
public class PermissionEntity implements Serializable {
private String id;
private String name;
private String url; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
}
}
实体类,角色RoleEntity.java
package com.xiaostudy.shiro_test1.entity; import java.io.Serializable;
import java.util.HashSet;
import java.util.Set; /**
* 角色实体类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:24
* Description: No Description
*/
public class RoleEntity implements Serializable {
private String id;
private String name;
private Set<PermissionEntity> permissions = new HashSet<>(); public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Set<PermissionEntity> getPermissions() {
return permissions;
} public void setPermissions(Set<PermissionEntity> permissions) {
this.permissions = permissions;
}
}
实体类,用户UserEntity.java
package com.xiaostudy.shiro_test1.entity; import java.io.Serializable;
import java.util.HashSet;
import java.util.Set; /**
* 用户实体类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:26
* Description: No Description
*/
public class UserEntity implements Serializable {
private String id;
private String name;
private String password;
private Set<RoleEntity> roles = new HashSet<>(); public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public Set<RoleEntity> getRoles() {
return roles;
} public void setRoles(Set<RoleEntity> roles) {
this.roles = roles;
}
}
实体类,测试redis实体类TestRedisEntity.java
package com.xiaostudy.shiro_test1.entity; import java.io.Serializable; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 22:04
* Description: No Description
*/
public class TestRedisEntity implements Serializable {
private int id;
private String name;
private String password; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}
自定义Realm类,UserRealm.java
package com.xiaostudy.shiro_test1.realm; import com.xiaostudy.shiro_test1.entity.PermissionEntity;
import com.xiaostudy.shiro_test1.entity.RoleEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired; import java.util.Collection;
import java.util.HashSet;
import java.util.Set; /**
* 自定义Realm,实现授权与认证
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:01
* Description: No Description
*/
public class UserRealm extends AuthorizingRealm { @Autowired
private UserService userService; /**
* 用户授权
**/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principalCollection) { System.out.println("===执行授权==="); Subject subject = SecurityUtils.getSubject();
UserEntity user = (UserEntity)subject.getPrincipal();
if(user != null){
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 角色字符串集合
Collection<String> rolesCollection = new HashSet<>();
// 权限字符串集合
Collection<String> premissionCollection = new HashSet<>();
// 读取并赋值用户角色与权限
Set<RoleEntity> roles = user.getRoles();
for(RoleEntity role : roles){
rolesCollection.add(role.getName());
Set<PermissionEntity> permissions = role.getPermissions();
for (PermissionEntity permission : permissions){
// 权限名称为PermissionEntity为字段url
premissionCollection.add(permission.getUrl());
}
info.addStringPermissions(premissionCollection);
}
info.addRoles(rolesCollection);
return info;
}
return null;
} /**
* 用户认证
**/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("===执行认证==="); UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
UserEntity bean = userService.findByName(token.getUsername()); if(bean == null){
// 用户不存在
throw new UnknownAccountException();
} else {
bean = userService.findById(bean.getId());
if(null == bean) {
// 认证失败
throw new AuthenticationException();
}
} ByteSource credentialsSalt = ByteSource.Util.bytes(bean.getName()); return new SimpleAuthenticationInfo(bean, bean.getPassword(),
credentialsSalt, getName());
}
}
处理没权限异常,NoPermissionException.java
package com.xiaostudy.shiro_test1.exception; import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:13
* Description: No Description
*/
@ControllerAdvice
public class NoPermissionException {
// 授权失败,就是说没有该权限
@ExceptionHandler(UnauthorizedException.class)
public String handleShiroException(Exception ex) {
return "/error/unAuth";
} @ResponseBody
@ExceptionHandler(AuthorizationException.class)
public String AuthorizationException(Exception ex) {
return "权限认证失败";
}
}
shiro配置类,ShiroConfig.java
package com.xiaostudy.shiro_test1.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.xiaostudy.shiro_test1.realm.UserRealm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; /**
* Shiro配置类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:06
* Description: No Description
*/
@Configuration
public class ShiroConfig { // 创建自定义 realm
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
} // 创建 SecurityManager 对象
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm());
return securityManager;
} // Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
/**
* anon:匿名用户可访问
* authc:认证用户可访问
* user:使用rememberMe可访问
* perms:对应权限可访问
* role:对应角色权限可访问
*/
LinkedHashMap<String, String> map = new LinkedHashMap<>();
// map.put("/resources/**", "anon");//匿名访问静态资源
map.put("/static/**", "anon");//匿名访问静态资源
map.put("/statics/**", "anon");//匿名访问静态资源
map.put("/jquery.jqGrid-4.6.0/**", "anon");//匿名访问静态资源
map.put("/jquery-ui-1.12.0-rc.2/**", "anon");//匿名访问静态资源
map.put("/layui/**", "anon");//匿名访问静态资源
map.put("/external/**", "anon");//匿名访问静态资源
map.put("/jquery/**", "anon");//匿名访问静态资源
map.put("/js/**", "anon");//匿名访问静态资源
map.put("/css/**", "anon");//匿名访问静态资源
map.put("/images/**", "anon");//匿名访问静态资源
// 开放登录接口
map.put("/login", "anon");
// map.put("/login", "authc");
// 对登录跳转接口进行释放
map.put("/error", "anon");
// 对所有用户认证
map.put("/**", "authc");
// 登出
map.put("/logout", "logout");
// 登录
// 注意:这里配置的 /login 是指到 @RequestMapping(value="/login")中的 /login
shiroFilterFactoryBean.setLoginUrl("/login");
// 首页
shiroFilterFactoryBean.setSuccessUrl("/index");
// 错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error/unAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
} // 加入注解的使用,不加这个,注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
} // 跟上面的注解配置搭配使用,有时候加了上面的配置后注解不生效,需要加入下面的配置
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator();
app.setProxyTargetClass(true);
return app;
} @Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
静态资源过滤配置类【告诉shiro不要拦截】,WebMvcConfig.java
package com.xiaostudy.shiro_test1.config; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/9
* Time: 0:51
* Description: No Description
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer { /**
* @author xiaobu
* @date 2019/1/18 13:51
* @param registry registry
* @descprition 等价于 http://localhost:9001/1.txt 依次在static upload目录下找1.txt文件
* @version 1.0
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
} }
用户mapper,UserMapper.xml
<?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.xiaostudy.shiro_test1.mapper.UserMapper"> <resultMap id="userMap" type="com.xiaostudy.shiro_test1.entity.UserEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="password" column="password"/>
<collection property="roles" ofType="com.xiaostudy.shiro_test1.entity.RoleEntity">
<id property="id" column="roleId"/>
<result property="name" column="roleName"/>
<collection property="permissions" ofType="com.xiaostudy.shiro_test1.entity.PermissionEntity">
<id property="id" column="permissionId"/>
<result property="name" column="permissionName"/>
<result property="url" column="permissionUrl"/>
</collection>
</collection>
</resultMap> <select id="findByName" parameterType="java.lang.String" resultType="com.xiaostudy.shiro_test1.entity.UserEntity">
SELECT id, name, password
FROM user
WHERE name = #{name}
</select> <select id="findById" parameterType="java.lang.String" resultMap="userMap">
SELECT user.id, user.name, user.password,
role.id as roleId, role.name as roleName,
permission.id as permissionId,
permission.name as permissionName,
permission.url as permissionUrl
FROM user, user_role, role, role_permission, permission
WHERE user.id = #{id}
AND user.id = user_role.user_id
AND user_role.role_id = role.id
AND role.id = role_permission.role_id
AND role_permission.permission_id = permission.id
</select> </mapper>
测试redis的mapper,TestRedisMapper.xml
<?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.xiaostudy.shiro_test1.mapper.TestRedisMapper"> <select id="selectAll" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" >
SELECT id, name, password
FROM test_redis;
</select> <select id="selectPages" parameterType="java.lang.Integer" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" >
SELECT id, name, password
FROM test_redis limit #{page}, #{rows};
</select> <select id="selectTotal" resultType="java.lang.Integer" >
SELECT COUNT(*) as total FROM test_redis;
</select> <select id="selectById" parameterType="java.lang.Integer" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity">
SELECT id, name, password
FROM test_redis
WHERE id = #{id};
</select> <select id="selectByName" parameterType="java.lang.String" resultType="com.xiaostudy.shiro_test1.entity.TestRedisEntity">
SELECT id, name, password
FROM test_redis
WHERE name = #{name};
</select> <insert id="insert" parameterType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" >
insert into test_redis (name, password) value (#{name}, #{password});
</insert> <update id="update" parameterType="com.xiaostudy.shiro_test1.entity.TestRedisEntity" >
update test_redis
set
name = #{name},
password = #{password}
where
id = #{id};
</update> <delete id="deleteById" parameterType="java.lang.Integer" >
delete from test_redis
where
id = #{id};
</delete> <delete id="deleteByName" parameterType="java.lang.String" >
delete from test_redis
where
name = #{name};
</delete> </mapper>
用户mapper,UserMapper.java
package com.xiaostudy.shiro_test1.mapper; import com.xiaostudy.shiro_test1.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:45
* Description: No Description
*/
@Mapper
public interface UserMapper { // 根据用户名称,查询用户信息
public UserEntity findByName(String name); // 根据用户id,查询用户信息、角色、权限
public UserEntity findById(String id);
}
测试redis的mapper,TestRedisMapper.java
package com.xiaostudy.shiro_test1.mapper; import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import java.util.List; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 22:07
* Description: No Description
*/
@Mapper
public interface TestRedisMapper { public List<TestRedisEntity> selectAll(); /**
* 简单分页
* <p>@Param的作用是告诉mapper他的参数名,因为存在多个参数</p>
* @param page
* @param rows
* @return
*/
public List<TestRedisEntity> selectPages(@Param("page") int page, @Param("rows") int rows); public int selectTotal(); public TestRedisEntity selectById(int id); public TestRedisEntity selectByName(String name); public int insert(TestRedisEntity testRedisEntity); public int update(TestRedisEntity testRedisEntity); public int deleteById(int id); public int deleteByName(String name);
}
用户service,UserService.java
package com.xiaostudy.shiro_test1.service; import com.xiaostudy.shiro_test1.entity.UserEntity; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:55
* Description: No Description
*/
public interface UserService { UserEntity findByName(String name); UserEntity findById(String id);
}
测试redis的service,TestRedisService.java
package com.xiaostudy.shiro_test1.service; import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity; import java.util.List; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:55
* Description: No Description
*/
public interface TestRedisService { public List<TestRedisEntity> selectAll(); public List<TestRedisEntity> selectPages(int page, int rows); public int selectTotal(); public TestRedisEntity selectById(int id); public TestRedisEntity selectByName(String name); public int insert(TestRedisEntity testRedisEntity); public int update(TestRedisEntity testRedisEntity); public int deleteById(int id); public int deleteByName(String name);
}
用户service实现类,UserServiceImpl.java
package com.xiaostudy.shiro_test1.service.impl; import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.mapper.UserMapper;
import com.xiaostudy.shiro_test1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; /**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:56
* Description: No Description
*/
@Service
public class UserServiceImpl implements UserService { @Autowired
private UserMapper userMapper; @Override
public UserEntity findByName(String name) {
return userMapper.findByName(name);
} @Override
public UserEntity findById(String id) {
return userMapper.findById(id);
}
}
测试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
package com.xiaostudy.shiro_test1.web.controller; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* 用户登录、登出、错误页面跳转控制器
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:15
* Description: No Description
*/
@Controller
public class MainController { @RequestMapping("/index")
public String index(HttpServletRequest request, HttpServletResponse response){
response.setHeader("root", request.getContextPath());
return "index";
} @RequestMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response){
response.setHeader("root", request.getContextPath());
String userName = request.getParameter("username");
String password = request.getParameter("password"); // 等于null说明用户没有登录,只是拦截所有请求到这里,那就直接让用户去登录页面,就不认证了。
// 如果这里不处理,那个会返回用户名不存在,逻辑上不合理,用户还没登录怎么就用户名不存在?
if(null == userName) {
return "login";
} // 1.获取Subject
Subject subject = SecurityUtils.getSubject();
// 2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
// 3.执行登录方法
try{
subject.login(token);
return "redirect:/index";
} catch (UnknownAccountException e){
// 这里是捕获自定义Realm的用户名不存在异常
request.setAttribute("msg","用户名不存在!");
} catch (IncorrectCredentialsException e){
request.setAttribute("userName",userName);
request.setAttribute("msg","密码错误!");
} catch (AuthenticationException e) {
// 这里是捕获自定义Realm的认证失败异常
request.setAttribute("msg","认证失败!");
} return "login";
} @RequestMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
subject.logout();
}
// return "redirect:/main";
return "login";
} @RequestMapping("/error/unAuth")
public String unAuth(){
return "/error/unAuth";
} @RequestMapping("/err")
public String err(){
return "/error/unAuth";
}
}
用户权限controller,UserController.java
package com.xiaostudy.shiro_test1.web.controller; import com.xiaostudy.shiro_test1.entity.UserEntity;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; /**
* 用户页面跳转
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:21
* Description: No Description
*/
@Controller
public class UserController { /**
* 个人中心,需认证可访问
*/
@RequestMapping("/user/index")
@RequiresPermissions(value = "user")// 这里的user,就是对应权限实体类PermissionEntity的字段url,自定义Realm类UserRealm里是用这个字段
public String add(HttpServletRequest request){
UserEntity bean = (UserEntity) SecurityUtils.getSubject().getPrincipal();
request.setAttribute("userName", bean.getName());
return "/user/index";
} /**
* 会员中心,需认证且角色为vip可访问
*/
@RequestMapping("/vip/index")
@RequiresPermissions(value = "vip")
public String update(){
return "/vip/index";
}
}
测试redis的controller,TestRedisController.java
package com.xiaostudy.shiro_test1.web.controller; import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.service.TestRedisService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 用户页面跳转
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:21
* Description: No Description
*/
@Controller
@RequestMapping("/testRedis")
public class TestRedisController { @Autowired
private TestRedisService testRedisService; @RequestMapping("/index")
public String index() {
return "testRedis/index";
} @RequestMapping("/all")
@ResponseBody
public Map getTestRedisAll() {
List<TestRedisEntity> redisEntityList = testRedisService.selectAll();
Map map = new HashMap();
map.put("redisEntityList", redisEntityList);
return map;
} @RequestMapping("/pages")
@ResponseBody
public Map getTestRedisPages(String page, String rows) {
List<TestRedisEntity> redisEntityList = testRedisService.selectPages(Integer.parseInt(page), Integer.parseInt(rows));
int total = testRedisService.selectTotal();
Map map = new HashMap();
map.put("redisEntityList", redisEntityList);
map.put("pages", total/Integer.parseInt(rows)+((total%Integer.parseInt(rows) == 0) ? 0 : 1));
map.put("total", total);
map.put("current", Integer.parseInt(page));
return map;
} @RequestMapping("/getByName")
@ResponseBody
public Map getByName(String name) {
TestRedisEntity testRedisEntity = testRedisService.selectByName(name);
Map map = new HashMap();
map.put("redisEntity", testRedisEntity);
return map;
} @RequestMapping("/get")
@ResponseBody
public Map getTestRedisByName(String name) {
TestRedisEntity testRedisEntity = testRedisService.selectByName(name);
Map map = new HashMap();
map.put("testRedisEntity", testRedisEntity);
return map;
} @RequestMapping("/insert")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map insertTestRedis(TestRedisEntity testRedisEntity) {
int insert = testRedisService.insert(testRedisEntity);
Map map = new HashMap();
map.put("result", insert);
return map;
} @RequestMapping("/update")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map updateTestRedis(TestRedisEntity testRedisEntity) {
int update = testRedisService.update(testRedisEntity);
Map map = new HashMap();
map.put("result", update);
return map;
} @RequestMapping("/deleteById")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map deleteById(String id) {
int deleteById = testRedisService.deleteById(Integer.parseInt(id));
Map map = new HashMap();
map.put("result", deleteById);
return map;
} @RequestMapping("/deleteByName")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map deleteByName(String name) {
int deleteByName = testRedisService.deleteByName(name);
Map map = new HashMap();
map.put("result", deleteByName);
return map;
} @RequestMapping("/form")
public String form() {
return "testRedis/form";
}
}
springboot启动类,ShiroTest1Application.java添加自定义序列化类bean,不要这个也可以,但是在redis上看就是\x\x\x之类
package com.xiaostudy.shiro_test1; import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; @SpringBootApplication
//@MapperScan(basePackages = "com.xiaostudy.shiro_test1.mapper")
public class ShiroTest1Application { public static void main(String[] args) {
SpringApplication.run(ShiroTest1Application.class, args);
} /**
* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory); // 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); // 设置value的序列化规则和 key的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Archetype Created Web Application</display-name> <!--请求编码设置-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index</welcome-file>
</welcome-file-list> <servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
</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
spring:
datasource:
url: jdbc:mysql://localhost:3306/my_test?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
# 初始化时建立物理连接连接的个数
initialSize: 5
# 最小连接池数量
minIdle: 5
# 最大连接池数量
maxActive: 20
# 获取连接时最大等待时间(ms),即60s
maxWait: 60000
# 1.Destroy线程会检测连接的间隔时间;2.testWhileIdle的判断依据
timeBetweenEvictionRunsMillis: 60000
# 最小生存时间ms
minEvictableIdleTimeMillis: 600000
maxEvictableIdleTimeMillis: 900000
# 用来检测连接是否有效的sql
validationQuery: SELECT 1 FROM DUAL
# 申请连接时执行validationQuery检测连接是否有效,启用会降低性能
testOnBorrow: false
# 归还连接时执行validationQuery检测连接是否有效,启用会降低性能
testOnReturn: false
# 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,
# 执行validationQuery检测连接是否有效,不会降低性能
testWhileIdle: true
# 是否缓存preparedStatement,mysql建议关闭
poolPreparedStatements: false
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
thymeleaf:
suffix: .html
charset: utf-8
#清除缓存,实现热部署
cache: false
mvc:
# 配置静态资源映射路径,/public、/resources路径失效
static-path-pattern: templates/** #redis配置
redis:
host: 127.0.0.1
port: 6379
password:
database: 2
timeout: 3000ms
jedis:
pool:
max-active: 200
max-idle: 100
min-idle: 1
max-wait: 3000ms mybatis:
mapper-locations: classpath:mapper/*.xml
# mapperLocations: classpath:mapper/*.xml
# 虽然可以配置这项来进行pojo包扫描,但其实我更倾向于在mapper.xml写全类名
# type-aliases-package: com.xiaostudy.shiro_test1.entity # 后台打印sql
logging:
level:
com.xiaostudy.shiro_test1.mapper : debug
登录页面,login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h1>用户登录</h1>
<hr>
<form id="from" action="/login" method="post">
<table>
<tr>
<td>用户名</td>
<td>
<input type="text" name="username" placeholder="请输入账户名" value="" th:value="${userName }"/>
</td>
</tr>
<tr>
<td>密码</td>
<td>
<input type="password" name="password" placeholder="请输入密码"/>
</td>
</tr>
<tr>
<td colspan="2">
<span style="color: red;">[[${msg }]]</span>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="登录"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</form>
</body>
</html>
主页,index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> <head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<hr>
<ul>
<li><a href="user/index">个人中心</a></li>
<li><a href="vip/index">会员中心</a></li>
<p shiro:hasPermission="svip"><li>这是svip能看到的p标签</li></p>
<shiro:hasPermission name="vip"><li>这是vip能看到的</li></shiro:hasPermission>
<shiro:hasPermission name="svip"><li>这是svip能看到的</li></shiro:hasPermission>
<li><a href="testRedis/index">测试redis主页</a></li>
<li><a href="logout">退出登录</a></li>
</ul>
</body>
</html>
通过认证后普通用户可以访问,user/index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>用户中心</title>
</head>
<body>
<h1>用户中心</h1>
<hr>
<h1>欢迎[[${userName }]],这里是用户中心</h1>
</body>
</html>
通过认证后,vip用户可以访问,vip/index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>会员中心</title>
</head>
<body>
<h1>会员中心</h1>
<hr>
<h1>欢迎来到<span style="color: red;">会员中心</span></h1>
</body>
</html>
认证通过后,普通用户访问vip页面时跳转提示没有权限,error/unAuth.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>未授权提示</title>
</head>
<body>
<h1>您还不是<span style="color: red;">会员</span> ,没有权限访问这个页面!</h1>
</body>
</html>
认证通过后,所有用户可以访问,测试redis主页,testRedis/index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> <head>
<title>首页</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=8">
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache"> <script src="" th:src="@{/statics/js/jquery-3.0.0.js}"></script>
<!--jqueryui-->
<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">
<!--jqgrid的css-->
<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"> <!--locale-->
<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>
<!--jqgrid的js-->
<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>
<link href="" th:href="@{/statics/layui/css/layui.css}" rel="stylesheet">
<script src="" th:src="@{/statics/layui/layui.all.js}"></script>
</head>
<body>
<h1>测试redis</h1>
<hr>
<shiro:hasPermission name="vip">
<button type="button" class="layui-btn" title="添加" onclick="create()">添加</button>
</shiro:hasPermission>
<shiro:hasPermission name="vip">
<input type="hidden" id="vip">
</shiro:hasPermission>
<shiro:hasPermission name="svip">
<input type="hidden" id="svip">
</shiro:hasPermission>
<table id="jqGrid" class="layui-table layui-table-grid"></table>
<div id="jqGridPager"></div>
</body>
</html> <script>
$(function () {
$("#jqGrid").jqGrid({
url : '[[${#httpServletRequest.getContextPath()}]]/testRedis/pages',
datatype : "json",
colModel : [
{ label: 'ID', name: 'id', width: 80, hidden:true },
{ label: "名称", name: "name", "align": "center", width: 100},
{ label: "密码 ", name: "password", "align": "center", width: 100},
{ label: "操作 ", name: "id", "align": "center", width: 100, formatter: operation}
],
viewrecords : true,
height : 300,
rowNum : 5,
rowList : [5,10,15,20,30,50],
rownumbers : true,
rownumWidth : 35,
autowidth : true,
multiselect : true,
pager : "#jqGridPager",
jsonReader : {
root : "redisEntityList",
page : "current",
total : "pages",
records : "total"
},
prmNames : {
page : "page",
rows : "rows",
order : "order"
},
postData:{ },
gridComplete : function() {
// 隐藏grid底部滚动条
$("#jqGrid").closest(".ui-jqgrid-bdiv").css({
"overflow-x" : "hidden"
});
//设置行高
var grid = $("#jqGrid");
var ids = grid.getDataIDs();
for (var i = 0; i < ids.length; i++) {
grid.setRowData ( ids[i], false, {height: 10} );
}
},
beforeRequest : function (){
var current=$(this).getGridParam("page");//当前页
var total= $(this).getGridParam('lastpage'); //获取总页数
if(current > total && total!=0){
//设置页码为最后一页 并重新加载
var postDatas = $(this).jqGrid("getGridParam", "postData");
postDatas['page']=total;
$(this).setGridParam({postData:postDatas});
}
},
ondblClickRow : function(rowid) {
view(rowid);
/*if(!ondblClickRowSubTable){
archivesFolderJs.view(rowid);
}else{
ondblClickRowSubTable = false;
}*/
}
}); function operation(id) {
/*var hrml2 =
' <div class="layui-btn-group">' +
' <button type="button" class="layui-btn" title="查看" onclick="view(\''+id+'\')">查看</button>' +
' <button type="button" class="layui-btn" title="编辑" onclick="update(\''+id+'\')">编辑</button>' +
' <button type="button" class="layui-btn" title="删除" onclick="deleteById(\''+id+'\')">删除</button>';*/
var hrml2 =
' <div class="layui-btn-group">' +
' <button type="button" class="layui-btn" title="查看" onclick="view(\''+id+'\')">查看</button>';
if($("#vip").length>0) {
hrml2 = hrml2 + '<button type="button" class="layui-btn" title="编辑" onclick="update(\''+id+'\')">编辑</button>'
+ '<button type="button" class="layui-btn" title="删除" onclick="deleteById(\''+id+'\')">删除</button>';
}
return hrml2;
}
}); function create() {
var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; var title ="添加";
var btns = [ '确认', '关闭' ];
var width ='700px';
var height = '200px';
var operation = "add";
open(2, title, width, height, 0.5, false, content, btns, operation, "");
} function view(id) {
var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; var title ="查看";
var btns = [ '关闭' ];
var width ='700px';
var height = '200px';
var operation = "view";
open(2, title, width, height, 0.5, false, content, btns, operation, id);
} function update(id) {
var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; var title ="修改";
var btns = [ '确认', '关闭' ];
var width ='700px';
var height = '200px';
var operation = "update";
open(2, title, width, height, 0.5, false, content, btns, operation, id);
} function deleteById(id) {
var content = "[[${#httpServletRequest.getContextPath()}]]/testRedis/form"; layer.confirm('确认删除?', {
btn: ['确定','取消'] //按钮
}, function(){
$.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/deleteById?id=" + id
+ "&_=" + new Date().getTime(), function (r) {
layer.closeAll();
if(r.result == 1) {
layui.layer.msg("删除成功");
$("#jqGrid").jqGrid().trigger("reloadGrid");
} else {
layui.layer.msg("删除失败");
}
});
}, function(){
// 点击取消事件
});
} function open(type, title, width, height, shade, maxmin, content, btns, operation, id) {
layui.use('layer', function() {
var layer = layui.layer;
parent.layer.open({
type: type,
title: title,
area: [width, height],
shade: shade,
maxmin: maxmin,
content: content,
btn: btns,
yes: function (index, layero) {
var selector = layero["selector"];
selector = "#layui-layer-iframe" + selector.substring("#layui-layer".length, selector.length);
var name = parent.$(selector).contents().find("#name").val();
var password = parent.$(selector).contents().find("#password").val();
if(undefined == name || null == name || "" == name) {
layui.layer.msg("请输入名称");
return;
}
if(undefined == password || null == password || "" == password) {
layui.layer.msg("请输入密码");
return;
}
if("add" == operation) {
$.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/getByName?name=" + name
+ "&_=" + new Date().getTime(), function (r) {
if(null != r.redisEntity && r.redisEntity.name == name) {
layui.layer.msg("名称已存在");
return;
} else {
$.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/insert?name=" + name
+ "&password=" + password + "&_=" + new Date().getTime(), function (r) {
if(r.result == 1) {
layer.closeAll();
layui.layer.msg("添加成功");
$("#jqGrid").jqGrid().trigger("reloadGrid");
} else {
layui.layer.msg("添加失败");
}
});
}
});
} else if("update" == operation) {
$.get("[[${#httpServletRequest.getContextPath()}]]/testRedis/update?id=" + id + "&name=" + name
+ "&password=" + password + "&_=" + new Date().getTime(), function (r) {
if(r.result == 1) {
layer.closeAll();
layui.layer.msg("修改成功");
$("#jqGrid").jqGrid().trigger("reloadGrid");
} else {
layui.layer.msg("修改失败");
}
});
} else {
layer.closeAll();
}
}, btn3: function () {
parent.layer.closeAll();
return false;
},
zIndex: 999,
success: function (layero) {
// 弹出窗弹出之前设置数据到弹出窗页面
if("update" == operation) {
var selector = layero["selector"];
selector = "#layui-layer-iframe" + selector.substring("#layui-layer".length, selector.length);
parent.$(selector).contents().find("#id").val(id);
var rowData = $("#jqGrid").jqGrid('getRowData',id);
parent.$(selector).contents().find("#name").val(rowData.name);
parent.$(selector).contents().find("#password").val(rowData.password);
} else if("view" == operation) {
var selector = layero["selector"];
selector = "#layui-layer-iframe" + selector.substring("#layui-layer".length, selector.length);
parent.$(selector).contents().find("#id").val(id);
var rowData = $("#jqGrid").jqGrid('getRowData',id);
var name = parent.$(selector).contents().find("#name");
name.val(rowData.name);
var password = parent.$(selector).contents().find("#password");
password.val(rowData.password);
name.attr("onfocus", "this.blur()");
password.attr("onfocus", "this.blur()");
name.css("background", "#CCCCCC");
name.css("cursor", "not-allowed");
password.css("background", "#CCCCCC");
password.css("cursor", "not-allowed");
/*name.attr("disabled", "disabled");
password.attr("disabled", "disabled");*/
}
}
});
});
}
</script>
测试redis主页,添加、修改、查看的form页面,testRedis/form.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=8">
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache"> <script src="" th:src="@{/statics/js/jquery-3.0.0.js}"></script>
<!--jqueryui-->
<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">
<!--jqgrid的css-->
<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"> <!--locale-->
<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>
<!--jqgrid的js-->
<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>
<link href="" th:href="@{/statics/layui/css/layui.css}" rel="stylesheet">
<script src="" th:src="@{/statics/layui/layui.all.js}"></script>
</head>
<body>
<div class="layui-form" style="margin-top: 30px;margin-right: 20px;">
<div class="layui-form-item">
<input type="hidden" id="id" name="id" value="">
<label class="layui-form-label">名称</label>
<div class="layui-input-inline">
<input type="text" id="name" name="name" required lay-verify="required" placeholder="名称" autocomplete="off" class="layui-input">
</div>
<label class="layui-form-label">密码</label>
<div class="layui-input-inline">
<input type="text" id="password" name="password" required lay-verify="required" placeholder="密码" autocomplete="off" class="layui-input">
</div>
</div>
</div> <script>
//Demo
layui.use('form', function(){
var form = layui.form; //监听提交
form.on('submit(formDemo)', function(data){
layer.msg(JSON.stringify(data.field));
return false;
});
});
</script>
</body>
</html>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xiaostudy</groupId>
<artifactId>shiro_test1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shiro_test1</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> <dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency> <!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency> <!-- redis 包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
数据库表创建
用户表、角色表、权限表、用户与角色多对多表、角色与权限多对多表
DROP TABLE IF EXISTS `role_permission`;
DROP TABLE IF EXISTS `permission`;
DROP TABLE IF EXISTS `user_role`;
DROP TABLE IF EXISTS `role`;
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (
`id` VARCHAR(255) PRIMARY KEY,
`name` VARCHAR(255),
`password` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '用户表'; CREATE TABLE `role` (
`id` VARCHAR(255) PRIMARY KEY,
`name` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '角色表'; CREATE TABLE `user_role` (
`id` VARCHAR(255) PRIMARY KEY,
`user_id` VARCHAR(255),
`role_id` VARCHAR(255),
FOREIGN KEY (`user_id`) REFERENCES `user`(id),
FOREIGN KEY (`role_id`) REFERENCES `role`(id)
) engine = InnoDB default charset = utf8 comment = '用户与角色多对多表'; CREATE TABLE `permission` (
`id` VARCHAR(255) PRIMARY KEY,
`name` VARCHAR(255),
`url` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '权限表'; CREATE TABLE `role_permission` (
`id` VARCHAR(255) PRIMARY KEY,
`role_id` VARCHAR(255),
`permission_id` VARCHAR(255),
FOREIGN KEY (`role_id`) REFERENCES `role`(id),
FOREIGN KEY (`permission_id`) REFERENCES `permission`(id)
) engine = InnoDB default charset = utf8 comment = '角色与权限多对多表'; insert into `user` (`id`, `name`, `password`) values('','admin','');
insert into `user` (`id`, `name`, `password`) values('','vip','');
insert into `user` (`id`, `name`, `password`) values('','svip',''); insert into `role` (`id`, `name`) values('','user');
insert into `role` (`id`, `name`) values('','vip');
insert into `role` (`id`, `name`) values('','svip'); insert into `permission` (`id`, `name`, `url`) values('','user','user');
insert into `permission` (`id`, `name`, `url`) values('','vip','vip');
insert into `permission` (`id`, `name`, `url`) values('','svip','svip'); insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','',''); insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
测试redis表
DROP TABLE IF EXISTS `test_redis`; CREATE TABLE `test_redis` (
`id` int(11) PRIMARY KEY auto_increment,
`name` VARCHAR(255),
`password` VARCHAR(255)
) 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
springboot与redis的更多相关文章
- 【springBoot】springBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- SpringBoot整合Redis、ApachSolr和SpringSession
SpringBoot整合Redis.ApachSolr和SpringSession 一.简介 SpringBoot自从问世以来,以其方便的配置受到了广大开发者的青睐.它提供了各种starter简化很多 ...
- SpringBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- springboot集成redis(mybatis、分布式session)
安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...
- Windows环境下springboot集成redis的安装与使用
一,redis安装 首先我们需要下载Windows版本的redis压缩包地址如下: https://github.com/MicrosoftArchive/redis/releases 连接打开后如下 ...
- SpringBoot系列——Redis
前言 Redis是一个缓存.消息代理和功能丰富的键值存储.StringBoot提供了基本的自动配置.本文记录一下springboot与redis的简单整合实例 官方文档:https://docs.sp ...
- SpringBoot整合Redis及Redis工具类撰写
SpringBoot整合Redis的博客很多,但是很多都不是我想要的结果.因为我只需要整合完成后,可以操作Redis就可以了,并不需要配合缓存相关的注解使用(如@Cacheable). ...
- SpringBoot 整合 Redis缓存
在我们的日常项目开发过程中缓存是无处不在的,因为它可以极大的提高系统的访问速度,关于缓存的框架也种类繁多,今天主要介绍的是使用现在非常流行的NoSQL数据库(Redis)来实现我们的缓存需求. Spr ...
- 带着新人学springboot的应用04(springboot+mybatis+redis 完)
对于缓存也说了比较多了,大家对下图这一堆配置类现在应该有些很粗略的认识了(因为我也就很粗略的认识了一下,哈哈!),咳,那么我们怎么切换这个缓存呢?(就是不用springboot提供的默认的Simple ...
- SpringBoot系列十:SpringBoot整合Redis
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合 Redis 2.背景 Redis 的数据库的整合在 java 里面提供的官方工具包:jed ...
随机推荐
- AS400 printer setting
(1) CRTOUTQ OUTQ(TESTLIB/PRINTER2) (2) CRTDEVPRT ===> CRTDEVPRT DEVD(PRINTER2) DEVCLS(*LAN) TYPE( ...
- java上传文件夹文件
这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...
- CF1051D Bicolorings 递推
考试T2,随便推一推就好了~ code: #include <bits/stdc++.h> #define N 1015 #define mod 998244353 #define ll ...
- QoS in RoCE
QoS in RoCE 首页分类标签留言关于订阅2018-03-22 | 分类 Network | 标签 RDMA RoCE ECN PFC Overview TCP/IP协议栈满足不了现代I ...
- 对list某个条件排序,并实现分页
package com.jcloud.aioc.api.controller.Test; import com.alibaba.fastjson.JSON; import org.apache.poi ...
- C++标准库分析总结(七)——<Hashtable、Hash_set、Hash_multiset、unordered容器设计原则>
编译器对关联容器的实现有两个版本,上一节总结了以红黑树做为基础的实现版本,这一节总结以哈希表(hash table,散列表)为底部结构的实现版本. 一.Hashtable简单介绍 Hashtable相 ...
- linuxfind命令按照文件大小搜索的注意事项
[root@localhost ~]# man find -size n[cwbkMG] File uses n units of space. The following suffixes can ...
- mac解压7z格式文件
brew直接安装解压工具 $ brew search 7z p7zip $ brew install p7zip ==> Downloading https://downloads.source ...
- 实现一个微信小程序组件:文字跑马灯效果
marquee.json { "component": true, "usingComponents": {} } marquee.wxml <!--co ...
- android: ListView设置emptyView 误区
使用ListVIew 来设置EmptyView的时候须注意: ListView listview = (ListView) findViewById(R.id.list); View emptyVie ...