Spring Boot learning
Official website: https://spring.io/projects/spring-boot#overview
file: https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/
Reference video: [crazy God says Java] the latest tutorial of SpringBoot, IDEA version, is easy to understand_ Beep beep beep_ bilibili
Project complete reference code: lexiaoyuan/SpringBootStudy: My Spring Boot study notes (github.com),Springboot study: my Spring Boot study notes (gitee.com)
meet Spring Boot learning notes - Spring Boot integration Shiro (I)
[supplement] install Easy Code plug-in
Introduction: https://gitee.com/makejava/EasyCode
- In the plug-in market in settings, search Easy Code, click Install, and restart IDEA after installation. (I have installed it here)
Integrate MyBatis
-
First, open mysql to ensure that idea can be connected.
-
In POM Import some dependencies into XML
<dependencies> <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.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.22</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
- Use the Easy Code plug-in to generate code. Just follow the following figure
- Directory after code generation, where userserviceimpl The Java directory has been adjusted
- Configure the data source and MyBatis, and create a new application in the resources directory YML file
# Configure data sources spring: datasource: url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource # Custom data source #Spring Boot does not inject these attribute values by default and needs to bind itself #druid data source proprietary configuration initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #Configure filters for monitoring statistics interception, stat: monitoring statistics, log4j: logging, wall: defending sql injection filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 # MyBatis configuration mybatis: type-aliases-package: com.springboot.entity mapper-locations: classpath:mapper/*.xml
- In user Add a toString method in Java
/** * (User)Entity class */ public class User{ private Integer id; private String name; private String pwd; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
- In userdao Add some code to Java
/** * (User)Table database access layer */ @Repository @Mapper public interface UserDao { /** * Query a single piece of data by ID * * @param id Primary key * @return Instance object */ User queryById(Integer id); User queryByName(String name); /** * Query specified row data * * @param offset Query start position * @param limit Number of queries * @return Object list */ List<User> queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit); /** * Query by entity as filter criteria * * @param user Instance object * @return Object list */ List<User> queryAll(User user); /** * New data * * @param user Instance object * @return Number of affected rows */ int insert(User user); /** * Modify data * * @param user Instance object * @return Number of affected rows */ int update(User user); /** * Delete data through primary key * * @param id Primary key * @return Number of affected rows */ int deleteById(Integer id); }
- In userservice A queryByName method is also added to Java
/** * (User)Table service interface */ public interface UserService { /** * Query a single piece of data by ID * * @param id Primary key * @return Instance object */ User queryById(Integer id); User queryByName(String name); /** * Query multiple data * * @param offset Query start position * @param limit Number of queries * @return Object list */ List<User> queryAllByLimit(int offset, int limit); /** * New data * * @param user Instance object * @return Instance object */ User insert(User user); /** * Modify data * * @param user Instance object * @return Instance object */ User update(User user); /** * Delete data through primary key * * @param id Primary key * @return Is it successful */ boolean deleteById(Integer id); }
- In userserviceimpl A queryByName method is also added to Java
/** * (User)Table service implementation class */ @Service("userService") public class UserServiceImpl implements UserService { @Resource private UserDao userDao; /** * Query a single piece of data by ID * * @param id Primary key * @return Instance object */ @Override public User queryById(Integer id) { return this.userDao.queryById(id); } @Override public User queryByName(String name) { return this.userDao.queryByName(name); } /** * Query multiple data * * @param offset Query start position * @param limit Number of queries * @return Object list */ @Override public List<User> queryAllByLimit(int offset, int limit) { return this.userDao.queryAllByLimit(offset, limit); } /** * New data * * @param user Instance object * @return Instance object */ @Override public User insert(User user) { this.userDao.insert(user); return user; } /** * Modify data * * @param user Instance object * @return Instance object */ @Override public User update(User user) { this.userDao.update(user); return this.queryById(user.getId()); } /** * Delete data through primary key * * @param id Primary key * @return Is it successful */ @Override public boolean deleteById(Integer id) { return this.userDao.deleteById(id) > 0; } }
- In userdao An SQL statement of queryByName is also added to 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.springboot.dao.UserDao"> <resultMap type="com.springboot.entity.User" id="UserMap"> <result property="id" column="id" jdbcType="INTEGER"/> <result property="name" column="name" jdbcType="VARCHAR"/> <result property="pwd" column="pwd" jdbcType="VARCHAR"/> </resultMap> <!--Query single--> <select id="queryById" resultMap="UserMap"> select id, name, pwd from mybatis.user where id = #{id} </select> <select id="queryByName" parameterType="String" resultType="user"> select id, name, pwd from mybatis.user where name = #{name} </select> <!--Query specified row data--> <select id="queryAllByLimit" resultMap="UserMap"> select id, name, pwd from mybatis.user limit #{offset}, #{limit} </select> <!--Query by entity as filter criteria--> <select id="queryAll" resultMap="UserMap"> select id, name, pwd from mybatis.user <where> <if test="id != null"> and id = #{id} </if> <if test="name != null and name != ''"> and name = #{name} </if> <if test="pwd != null and pwd != ''"> and pwd = #{pwd} </if> </where> </select> <!--Add all columns--> <insert id="insert" keyProperty="id" useGeneratedKeys="true"> insert into mybatis.user(name, pwd) values (#{name}, #{pwd}) </insert> <!--Modify data through primary key--> <update id="update"> update mybatis.user <set> <if test="name != null and name != ''"> name = #{name}, </if> <if test="pwd != null and pwd != ''"> pwd = #{pwd}, </if> </set> where id = #{id} </update> <!--Delete by primary key--> <delete id="deleteById"> delete from mybatis.user where id = #{id} </delete> </mapper>
- First, test it in the test class
@SpringBootTest class Springboot08ShiroApplicationTests { @Autowired private UserServiceImpl userService; @Test void contextLoads() { System.out.println(userService.queryById(1).toString()); } }
- Run the test class and you can see that there is no problem.
- Modify userrealm The authentication method in Java queries users through the database
// authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("Yes===>authentication doGetAuthorizationInfo"); UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; // User name and password authentication, retrieved from the database User user = userService.queryByName(userToken.getUsername()); if (user == null) // There is no such user (name) return null; // An exception UnknownAccountException will be thrown // Password authentication, shiro do // Can be encrypted: MD5, MD5 salt value encryption return new SimpleAuthenticationInfo("",user.getPwd(),""); }
- Run the web project again and visit: http://localhost:8080/toLogin , you can still prompt relevant information by entering the wrong user name and password. At the same time, you can log in successfully by entering the user name and password in the user table in the database
- OK, integrate MyBatis and Druid!
Request authorization
- In shiroconfig Add authorization rules to methods in Java
// 3. Create ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // Set up security manager shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); // Add shiro's built-in filter /** * anon: Access without authentication * authc: Must be authenticated to access * user: You must have the remember me function to access * perms: You must have permission on a resource to access it * role: You must have a role permission to access */ // Login interception Map<String, String> filterMap = new LinkedHashMap<>(); // Authorization (to be placed first) filterMap.put("/user/add", "perms[user:add]"); // You must have add permission to access the add page filterMap.put("/user/update", "perms[user:update]"); // You must have update permission to access the update page // Intercept request filterMap.put("/user/*", "authc"); // Wildcards are supported shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); // Set login request shiroFilterFactoryBean.setLoginUrl("/toLogin"); return shiroFilterFactoryBean; }
- Test: run the following project to access: http://localhost:8080/toLogin , enter the correct user name and password (e.g. Le xiaoape, admin), log in, and then click the add or update link to find that it is not authorized,
- Configure unauthorized pages:
- In mycontroller Add a method in Java
@GetMapping("/unauthorized") @ResponseBody public String unauthorized() { return "You do not have permission to access this page"; }
- Set the login request above before setting the unauthorized page
// Set unauthorized pages shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
- After repeating the above test, you can see that the user-defined unauthorized page is entered
- Add permissions to users: in userrealm Authorization method in Java
// to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("Yes===>to grant authorization doGetAuthorizationInfo"); // Enter this method to add permissions to the user SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addStringPermission("user:add"); return authorizationInfo; }
- Repeat the above test. You can see that you can access the add page after successful login
- Get the permissions of the current user through the database:
- First, modify the user table and add a column
- Then use Easy Code to regenerate the entity class user Java (added a toString method) and userdao XML (added an SQL statement of queryByName)
/** * (User)Entity class */ public class User implements Serializable { private static final long serialVersionUID = 227972241159940478L; private Integer id; private String name; private String pwd; private String perms; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getPerms() { return perms; } public void setPerms(String perms) { this.perms = perms; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + ", perms='" + perms + '\'' + '}'; } }
<?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.springboot.dao.UserDao"> <resultMap type="com.springboot.entity.User" id="UserMap"> <result property="id" column="id" jdbcType="INTEGER"/> <result property="name" column="name" jdbcType="VARCHAR"/> <result property="pwd" column="pwd" jdbcType="VARCHAR"/> <result property="perms" column="perms" jdbcType="VARCHAR"/> </resultMap> <!--Query single--> <select id="queryById" resultMap="UserMap"> select id, name, pwd, perms from mybatis.user where id = #{id} </select> <select id="queryByName" parameterType="String" resultType="user"> select id, name, pwd, perms from mybatis.user where name = #{name} </select> <!--Query specified row data--> <select id="queryAllByLimit" resultMap="UserMap"> select id, name, pwd, perms from mybatis.user limit #{offset}, #{limit} </select> <!--Query by entity as filter criteria--> <select id="queryAll" resultMap="UserMap"> select id, name, pwd, perms from mybatis.user <where> <if test="id != null"> and id = #{id} </if> <if test="name != null and name != ''"> and name = #{name} </if> <if test="pwd != null and pwd != ''"> and pwd = #{pwd} </if> <if test="perms != null and perms != ''"> and perms = #{perms} </if> </where> </select> <!--Add all columns--> <insert id="insert" keyProperty="id" useGeneratedKeys="true"> insert into mybatis.user(name, pwd, perms) values (#{name}, #{pwd}, #{perms}) </insert> <!--Modify data through primary key--> <update id="update"> update mybatis.user <set> <if test="name != null and name != ''"> name = #{name}, </if> <if test="pwd != null and pwd != ''"> pwd = #{pwd}, </if> <if test="perms != null and perms != ''"> perms = #{perms}, </if> </set> where id = #{id} </update> <!--Delete by primary key--> <delete id="deleteById"> delete from mybatis.user where id = #{id} </delete> </mapper>
- Modify userrealm Methods of authentication and authorization in Java
// to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("Yes===>to grant authorization doGetAuthorizationInfo"); // Enter this method to add permissions to the user SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //authorizationInfo.addStringPermission("user:add"); // Get the current object Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal(); // Get the user object passed from the authentication method below // Add the permissions of the current user and get the permissions of the current user through the database authorizationInfo.addStringPermission(currentUser.getPerms()); return authorizationInfo; } // authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("Yes===>authentication doGetAuthorizationInfo"); UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; // User name and password authentication, retrieved from the database User user = userService.queryByName(userToken.getUsername()); if (user == null) // There is no such user (name) return null; // An exception UnknownAccountException will be thrown // Pass the user found in the database to the authorized method above return new SimpleAuthenticationInfo(user,user.getPwd(),""); }
- Test: access: http://localhost:8080/toLogin , log in with the user name and password in the user table in the database. You can see that only users with certain permissions can access the pages they can access. Test OK!
- Request authorization completed!
shiro integrates thymeleaf
Official website documents: https://github.com/theborakompanioni/thymeleaf-extras-shiro
- In POM Add integration dependency to XML
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
- In shiroconfig Integrating shiro and thymeleaf in Java
// Integrate ShiroDialect: used to integrate shiro and thymeleaf @Bean public ShiroDialect getShiroDialect(){ return new ShiroDialect(); }
- In index Add judgment to 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> </head> <body> <h1>home page</h1> <p th:text="${msg}"></p> <p shiro:notAuthenticated=""> <a th:href="@{/toLogin}">Sign in</a> </p> <div shiro:hasPermission="user:add"> <a th:href="@{/user/add}">add</a> </div> <div shiro:hasPermission="user:update"> <a th:href="@{/user/update}">update</a> </div> </body> </html>
- Rerun the project to access: http://localhost:8080/ , only login is displayed when there is no login
- Click log in and log in with Le xiaoape's account. If you only have add permission, only the add page will be displayed
- Log in with a beta account and only display the update page if you have update permission
- OK, integration is complete!