测试项目已上传到GitHub:https://github.com/xiaostudy/springboot_shiro_test1

1、创建springboot项目

 <!-- 数据库连接池 -->
<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>

src\main\webapp\

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;
}
}

 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;
}
}

 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;
}
}

实体类entity,也可以叫bean、domain,具体叫什可以根据自己的喜欢选取

3、数据库创建表和添加数据

  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('','','');

4、接下来写mapper,也叫dao

 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);
}

@Mapper后面再讲,这里也可以不用@Mapper

 <?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>

5、下面写service

 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);
}

 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);
}
}

6、下面写自定义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());
}
}

7、下面写shiro配置类

 package com.xiaostudy.shiro_test1.config;

 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.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:对应角色权限可访问
*/
Map<String, String> map = new HashMap<>();
// 开放登录接口
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;
}
}

8、下面写没有权限异常处理类

 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 "权限认证失败";
}
}

9、下面写controller

 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";
}
}

 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";
}
}

10、下面写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>

11、下面写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>
</web-app>

12、下面写application.yml

 spring:
datasource:
url: jdbc:mysql://localhost:3306/shiro_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
mvc:
# 配置静态资源映射路径,/public、/resources路径失效
static-path-pattern: templates/**
mybatis:
mapper-locations: classpath:mapper/*.xml
# mapperLocations: classpath:mapper/*.xml
# 虽然可以配置这项来进行pojo包扫描,但其实我更倾向于在mapper.xml写全类名
# type-aliases-package: com.xiaostudy.shiro_test1.entity

13、下面写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>

 <!DOCTYPE html>
<html lang="en"> <head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<hr>
<ul>
<li><a href="user/index">个人中心</a></li>
<li><a href="vip/index">会员中心</a></li>
<li><a href="logout">退出登录</a></li>
</ul>
</body>
</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>

 <!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>

 <!DOCTYPE html>
<html lang="en">
<head>
<title>未授权提示</title>
</head>
<body>
<h1>您还不是<span style="color: red;">会员</span> ,没有权限访问这个页面!</h1>
</body>
</html>

下面讲一下@Mapper与@MapperScan这个注解

@Mapper是放在具体的*Mapper.java类上面的,告诉springboot,这是mapper类

而@MapperScan是让springboot去扫描指定包下的mapper类,就不用每个mapper自己添加一个@Mapper注解了,这种方式比较好,因为这里测试只有一个mapper类,就直接用@Mapper了,两个一起用会不会冲突,这里没有测试。

整体目录

先看一下数据库表

下面是启动测试

参考文章:https://blog.csdn.net/qq_34802416/article/details/84959457

thymeleaf

最新文章

  1. volatile关键字 学习记录2
  2. sql通用的存储过程
  3. uva167 The Sultan&#39;s Successors
  4. CREATEINPUTLAYOUT_INCOMPATIBLEFORMAT
  5. iscc2016 mobile1-TurtleShell.apk解题过程
  6. WCF入门教程系列六
  7. Java:import com.sun.awt.AWTUtilities;报错
  8. ●BZOJ 2006 NOI 2010 超级钢琴
  9. 数据拟合:多项式拟合polynomial curve fitting
  10. 如何更有效地说服开发接收你的bug?!
  11. [DP][NOIP2013]花匠
  12. C++ 实现strcpy
  13. BZOJ1180 [CROATIAN2009]OTOCI LCT
  14. TIC Read Status此类网络活动提醒隐藏
  15. 常用类一一字符串相关类一一StringBuilder,StringBuffer。
  16. 有关jQuery valid 验证多个同name属性的input的问题
  17. Scrum立会报告+燃尽图(十月二十三日总第十四次)
  18. 2017-2018-2 20165218 实验四《Android开发基础》实验报告
  19. 求其中同一个主叫号码的两次通话之间间隔大于10秒的通话记录ID
  20. ios上传图片遇见了一个TimeoutError(DOM Exception 23)异常

热门文章

  1. Python: lambda, map, reduce, filter
  2. SQuirreL – Phoenix的GUI
  3. docker: docker安装和镜像下载
  4. 【甘道夫】Eclipse+Maven搭建HBase开发环境及HBaseDAO代码演示样例
  5. [数据挖掘课程笔记]基于规则的分类-顺序覆盖算法(sequential covering algorithm)
  6. IC卡、ID卡、M1卡、射频卡的区别是什么
  7. 往android的内核添加驱动及 ueventd.rc 修改【转】
  8. HDFS namenode 高可用(HA)搭建指南 QJM方式 ——本质是多个namenode选举master,用paxos实现一致性
  9. ios系统的特点
  10. Constructing Roads In JGShining's Kingdom