測試項目已上傳到GitHub:https://github.com/xiaostudy/springboot_shiro_test1
1、創建springboot項目






1 <!-- 數據庫連接池 --> 2 <dependency> 3 <groupId>com.alibaba</groupId> 4 <artifactId>druid</artifactId> 5 <version>1.1.10</version> 6 </dependency> 7 <!-- Shiro --> 8 <dependency> 9 <groupId>org.apache.shiro</groupId> 10 <artifactId>shiro-spring</artifactId> 11 <version>1.3.2</version> 12 </dependency> 13 <!-- log4j --> 14 <dependency> 15 <groupId>log4j</groupId> 16 <artifactId>log4j</artifactId> 17 <version>1.2.17</version> 18 </dependency>





src\main\webapp\


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 }

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 }

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 }
實體類entity,也可以叫bean、domain,具體叫什可以根據自己的喜歡選取
3、數據庫創建表和添加數據


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');
4、接下來寫mapper,也叫dao

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 }
@Mapper后面再講,這里也可以不用@Mapper


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>
5、下面寫service

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 }

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 }
6、下面寫自定義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 }
7、下面寫shiro配置類

1 package com.xiaostudy.shiro_test1.config; 2 3 import com.xiaostudy.shiro_test1.realm.UserRealm; 4 import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 5 import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 6 import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 7 import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; 8 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 9 import org.springframework.context.annotation.Bean; 10 import org.springframework.context.annotation.Configuration; 11 12 import java.util.HashMap; 13 import java.util.Map; 14 15 /** 16 * Shiro配置類 17 * Created with IntelliJ IDEA. 18 * User: Administrator 19 * Date: 2019/6/8 20 * Time: 15:06 21 * Description: No Description 22 */ 23 @Configuration 24 public class ShiroConfig { 25 26 // 創建自定義 realm 27 @Bean 28 public UserRealm userRealm() { 29 UserRealm userRealm = new UserRealm(); 30 return userRealm; 31 } 32 33 // 創建 SecurityManager 對象 34 @Bean 35 public DefaultWebSecurityManager securityManager() { 36 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 37 securityManager.setRealm(userRealm()); 38 return securityManager; 39 } 40 41 // Filter工廠,設置對應的過濾條件和跳轉條件 42 @Bean 43 public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { 44 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 45 shiroFilterFactoryBean.setSecurityManager(securityManager); 46 /** 47 * anon:匿名用戶可訪問 48 * authc:認證用戶可訪問 49 * user:使用rememberMe可訪問 50 * perms:對應權限可訪問 51 * role:對應角色權限可訪問 52 */ 53 Map<String, String> map = new HashMap<>(); 54 // 開放登錄接口 55 map.put("/login", "anon"); 56 // map.put("/login", "authc"); 57 // 對登錄跳轉接口進行釋放 58 map.put("/error", "anon"); 59 // 對所有用戶認證 60 map.put("/**", "authc"); 61 // 登出 62 map.put("/logout", "logout"); 63 // 登錄 64 // 注意:這里配置的 /login 是指到 @RequestMapping(value="/login")中的 /login 65 shiroFilterFactoryBean.setLoginUrl("/login"); 66 // 首頁 67 shiroFilterFactoryBean.setSuccessUrl("/index"); 68 // 錯誤頁面,認證不通過跳轉 69 shiroFilterFactoryBean.setUnauthorizedUrl("/error/unAuth"); 70 shiroFilterFactoryBean.setFilterChainDefinitionMap(map); 71 return shiroFilterFactoryBean; 72 } 73 74 // 加入注解的使用,不加這個,注解不生效 75 @Bean 76 public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { 77 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 78 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 79 return authorizationAttributeSourceAdvisor; 80 } 81 82 // 跟上面的注解配置搭配使用,有時候加了上面的配置后注解不生效,需要加入下面的配置 83 @Bean 84 @ConditionalOnMissingBean 85 public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { 86 DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator(); 87 app.setProxyTargetClass(true); 88 return app; 89 } 90 }
8、下面寫沒有權限異常處理類

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 }
9、下面寫controller

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 }

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 }
10、下面寫spring-mvc.xml

1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:mvc="http://www.springframework.org/schema/mvc" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xmlns:context="http://www.springframework.org/schema/context" 7 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 8 xsi:schemaLocation="http://www.springframework.org/schema/beans 9 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 10 http://www.springframework.org/schema/mvc 11 http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 12 http://www.springframework.org/schema/context 13 http://www.springframework.org/schema/context/spring-context-3.2.xsd 14 http://www.springframework.org/schema/aop 15 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 16 http://www.springframework.org/schema/tx 17 http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> 18 19 <!-- 把Controller交給spring管理 --> 20 <context:component-scan base-package="com.xiaostudy"/> 21 22 <!-- 配置注解處理器映射器 功能:尋找執行類Controller --> 23 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> 24 25 <!-- 配置注解處理器適配器 功能:調用controller方法,執行controller --> 26 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> 27 28 <!-- 配置sprigmvc視圖解析器:解析邏輯試圖 29 后台返回邏輯試圖:index 30 視圖解析器解析出真正物理視圖:前綴+邏輯試圖+后綴====/WEB-INF/index.jsp --> 31 <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 32 <property name="prefix" value="/WEB-INF/"/> 33 <property name="suffix" value=".jsp"/> 34 </bean>--> 35 </beans>
11、下面寫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 </web-app>
12、下面寫application.yml

1 spring: 2 datasource: 3 url: jdbc:mysql://localhost:3306/shiro_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 mvc: 38 # 配置靜態資源映射路徑,/public、/resources路徑失效 39 static-path-pattern: templates/** 40 mybatis: 41 mapper-locations: classpath:mapper/*.xml 42 # mapperLocations: classpath:mapper/*.xml 43 # 雖然可以配置這項來進行pojo包掃描,但其實我更傾向於在mapper.xml寫全類名 44 # type-aliases-package: com.xiaostudy.shiro_test1.entity


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

1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <title>首頁</title> 6 </head> 7 <body> 8 <h1>首頁</h1> 9 <hr> 10 <ul> 11 <li><a href="user/index">個人中心</a></li> 12 <li><a href="vip/index">會員中心</a></li> 13 <li><a href="logout">退出登錄</a></li> 14 </ul> 15 </body> 16 </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>

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>

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>
下面講一下@Mapper與@MapperScan這個注解
@Mapper是放在具體的*Mapper.java類上面的,告訴springboot,這是mapper類

而@MapperScan是讓springboot去掃描指定包下的mapper類,就不用每個mapper自己添加一個@Mapper注解了,這種方式比較好,因為這里測試只有一個mapper類,就直接用@Mapper了,兩個一起用會不會沖突,這里沒有測試。

整體目錄



先看一下數據庫表






下面是啟動測試
















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