回顾Java知识点,面试题汇总Day17(持续更新)

Spring Boot整合

Spring和Spring Boot都是用来构建项目的脚手架

Spring和Spring Boot的区别?

Spring 需要手动进行组件的配置

Spring Boot是自动进行组件的配置

一、Spring Boot如何自动进行组件的配置

1.1 自动装配

引入了MyBatis的依赖,项目启动时会自动加载MyBatis相关的组件

DataSource 、sqlSessionFactory...

当启动了Spring Boot时,pom.xml中配置的所有框架的组件都会自动进行加载。

比如:pom.xml中引入了mybatis依赖,不配置datasource,启动就会报错。

1.2 如何进行自动装配?

  • pom.xml文件中添加mybatis的依赖
  • Spring Boot就会自动加载MyBatis需要的bean

只需要在该类配置中将需要创建的对象进行配置即可,Spring 框架就会读取配置类,进而创建对象(反射)

Spring Boot如何自动实现bean的创建,通过配置类的方式

引入MyBatis依赖之后,依赖中会包含一个配置类的信息,配置类中会标注要创建的bean

Spring Boot启动之后会读取配置类信息,从而获得MyBatis需要创建的bean,然后进行创建

Maven:org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:3.0.5

/META-INF/spring.factories

启动Spring Boot时,会读取spring.factories文件,通过key获取到两个配置类。

二、MyBatis Plus

MyBatis Plus基于MyBatis,MyBatis需要开发者手动编写SQL语句,MyBatis Plus不需要开发者手动编写。使用MyBatis Plus会减少代码量。

XML 复制代码
<dependency>
    <groupId>com.baomidou<groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.1</version>
</dependency>

MyBatis Plus除了可以自动生成SQL外,还可以自动生成代码(Controller、Service、Mapper和Enity)

2.1 MyBatis Plus逆向工程的依赖

XML 复制代码
 <!--mybatis plus逆向工程的依赖  要跟starter的版本一致-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.7</version>
        </dependency>
      <!--模板引擎-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

3.5.x 完全重构了生成器,旧的 AutoGenerator 类虽然还在,但构造器已私有化,必须使用新的 流式 API。建议使用3.3.2

XML 复制代码
 <!--mybatis plus的依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <!--mybatis plus逆向工程的依赖   跟starter的版本一致-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
     <!--模板引擎-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>

2.2 通过表逆向生成项目

java 复制代码
package com.dyz;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

public class Main {
    public static void main(String[] args) {
        AutoGenerator autoGenerator = new AutoGenerator();
        //配置数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/car_rental_separate?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setPassword("123456");
        autoGenerator.setDataSource(dataSourceConfig);
        //全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOpen(false);
        globalConfig.setOutputDir(System.getProperty("user.dir") + ("/src/main/java"));
        globalConfig.setServiceName("%sService"); //%s替换符,避免出现IService不规范的情况
        autoGenerator.setGlobalConfig(globalConfig);
        //配置包
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.dyz");
        packageConfig.setEntity("entity");
        packageConfig.setController("controller");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        autoGenerator.setPackageInfo(packageConfig);
        //生成策略
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setEntityLombokModel(true);
        strategyConfig.setInclude("sys_news");
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);//下划线转驼峰 SysNew,不是Sys_news这样不规范
        autoGenerator.setStrategy(strategyConfig);
        //启动
        autoGenerator.execute();

    }
}

生成器帮你写 Java 代码,但 Spring Boot 的启动配置还得你自己配。

就是说想要项目跑起来,还得自己写appliation.yml配置

java 复制代码
package com.dyz.controller;
import com.dyz.entity.SysNews;
import com.dyz.service.SysNewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//@Controller
@RestController  //返回json
@RequestMapping("/news")
public class SysNewsController {
    @Autowired
    private SysNewsService sysNewsService;

    @GetMapping("/list")
    public List<SysNews> list(){
        return this.sysNewsService.list();
    }

    @GetMapping("/get/{id}")
    public SysNews getById(@PathVariable("id") Integer id){
  return this.sysNewsService.getById(id);
    }

}
java 复制代码
package com.dyz;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.dyz.mapper")
public class SpringbootMybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootMybatisPlusApplication.class, args);
    }

}

三、Spring Boot整合jdbcTemplate

jdbcTemplate是一个轻量级的JDBC封装组件。

jdbcTemplate是Spring自带的JDBC模板组件,底层实现了对JDBC的封装,需要开发者自定义SQL语句,jdbcTemplate帮助完成数据库的连接,SQL的执行,结果集的封装。

jdbcTemplate提供了通用的SQL操作方法,execute、update、batchUpdate、query

jdbcTemplate和MyBatis的区别?

MyBatis的SQL定义在XML文件中,jdbcTemplate的SQL定义在Java类中。

3.1 pom.xml中添加依赖

XML 复制代码
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

3.2 表创建&实体类

java 复制代码
package com.dyz.entity;

import lombok.Data;

import java.util.Date;

@Data
public class News {
    private int id;
    private String title;
    private  String content;
    private Date createtime;
    private String opername;

}

3.3 创建Mapper接口,定义JDBC方法

浏览器一般只能测试查询方法

postman一款接口测试工具

java 复制代码
package com.dyz.jdbcTemplate;

import com.dyz.entity.News;

import java.util.List;

public interface NewsMapper {
    public List<News> list();
    public News getById(Integer id);
    public void add(News news);
    public void update(News news);
    public void deleteById(Integer id);
    public void batchUpdate();
    public void batchAdd();
    public void batchDelete();
}
java 复制代码
package com.dyz.jdbcTemplate;

import com.dyz.entity.News;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Repository
public class NewsMapperImpl implements NewsMapper{

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public List<News> list() {
        return this.jdbcTemplate.query("select * from sys_news",new BeanPropertyRowMapper<>(News.class));
    }

    @Override
    public News getById(Integer id) {
        return this.jdbcTemplate.queryForObject("select * from sys_news where id = ?",new Object[]{id},new BeanPropertyRowMapper<>(News.class));
    }

    @Override
    public void add(News news) {
        this.jdbcTemplate.update("insert into sys_news(title,content,createtime,opername) values(?,?,?,?)",news.getTitle(),news.getContent(),news.getCreatetime(),news.getOpername());

    }

    @Override
    public void update(News news) {
     this.jdbcTemplate.update("update sys_news set title = ?,content = ?,createtime = ?,opername = ? where id = ?",news.getTitle(),news.getContent(),news.getCreatetime(),news.getOpername(),news.getId());
    }

    @Override
    public void deleteById(Integer id) {
        this.jdbcTemplate.update("delete from sys_news where id = ?",id);

    }

    @Override
    public void batchAdd() {
        List<Object[]> args = new ArrayList<>();
        args.add(new Object[]{"测试1","这是测试数据1",new Date(),"admin"});
        args.add(new Object[]{"测试2","这是测试数据2",new Date(),"admin"});
        args.add(new Object[]{"测试3","这是测试数据3",new Date(),"admin"});
        args.add(new Object[]{"测试4","这是测试数据4",new Date(),"admin"});
        this.jdbcTemplate.batchUpdate("insert into sys_news(title,content,createtime,opername) values (?,?,?,?)",args);
    }

    @Override
    public void batchUpdate() {
        List<Object[]> args = new ArrayList<>();
        args.add(new Object[]{"测试12","这是测试数据1",new Date(),"admin"});
        this.jdbcTemplate.batchUpdate("update sys_news set title = ?,content = ?,createtime=?,opername=?",args);
    }

    @Override
    public void batchDelete() {
        List<Object[]> args = new ArrayList<>();
        args.add(new Object[]{1});
        args.add(new Object[]{5});
        this.jdbcTemplate.batchUpdate("delete from sys_news where id = ?",args);

    }
}

3.4 controller实现方法

java 复制代码
package com.dyz.controller;


import com.dyz.entity.News;
import com.dyz.jdbcTemplate.NewsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

//@Controller
@RestController
public class NewsController {
    @Autowired
    private NewsMapper newsMapper;

    @GetMapping("/list")
    public List<News> list(){
       return this.newsMapper.list();
    }
    @GetMapping("/getById/{id}")
    public News getById(@PathVariable("id") Integer id){
        News news = null;
        try {
            news = this.newsMapper.getById(id);
        } catch (Exception e) {
            return null;
        }
        return news;

    }

    @PostMapping("/add")
    public void add(@RequestBody  News news){
        this.newsMapper.add(news);
    }

    @PutMapping("/update")
    public void update(@RequestBody News news){
        this.newsMapper.update(news);
    }

    @DeleteMapping("/delete/{id}")
    public void deleteById(@PathVariable("id") Integer id){
        this.newsMapper.deleteById(id);
    }

    @GetMapping("/batchAdd")
    public void batchAdd(){
        this.newsMapper.batchAdd();

    }

    @GetMapping("/batchUpdate")
    public void batchUpdate(){
        this.newsMapper.batchUpdate();
    }

    @GetMapping("/batchDelete")
    public void batchDelete(){
        this.newsMapper.batchDelete();
    }

}

四、Spring Boot整合Spring Data JPA

Spring Data JPA是Spring框架提供的持久层解决方案。

4.1 pom.xml中引入依赖

XML 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

4.2 创建数据表&实体类

java 复制代码
package com.dyz.jpaentity;


import jakarta.persistence.*;
import lombok.Data;

import java.util.Date;

@Data
@Entity(name = "sys_news")  //表示关联到数据库
public class News {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
    private Integer id;
    @Column //普通字段
    private String title;
    @Column
    private String content;
    @Column
    private Date createtime;
    @Column
    private String opername;
}

4.3 创建接口

java 复制代码
package com.dyz.repository;

import com.dyz.jpaentity.News;
import org.springframework.data.jpa.repository.JpaRepository;

public interface NewsRepository extends JpaRepository<News,Integer> {
}

4.4 创建Controller

java 复制代码
package com.dyz.controller;


import com.dyz.jpaentity.News;
import com.dyz.repository.NewsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/jpa")
public class JPANewsController {

    @Autowired
    private NewsRepository newsRepository;

    @GetMapping("/list")
    public List<News> list(){
     return this.newsRepository.findAll();
    }
    @GetMapping("/getById/{id}")
    public News getById(@PathVariable("id") Integer id){
        Optional<News> optional = this.newsRepository.findById(id);
            return optional.get();
    }
    @PostMapping("/add")
    public void add(@RequestBody News news){
        this.newsRepository.save(news);
    }

    @PutMapping("/update")
    public void update(@RequestBody News news){
        this.newsRepository.save(news);
    }
    @DeleteMapping("/deleteById/{id}")
    public void DeleteById(@PathVariable("id") Integer id){
        this.newsRepository.deleteById(id);
    }
}

五、Spring Boot整合Spring Security

5.1 登录认证

5.1.1 pom.xml中添加依赖

相当于添加安全校验的框架,会自动跳转到login页面进行校验

XML 复制代码
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

5.1.2 创建html页面

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Welcome</h1>

</body>
</html>

5.1.3 创建controller

java 复制代码
package com.dyz.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class IndexController {

    @GetMapping("/welcome")
    public String index(){
        return "welcome";
    }

}

5.1.4 控制台输出&测试

username:user

yml文件中可自定义账号密码

java 复制代码
server:
  port: 8081
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/car_rental_separate
    username: root
    password: 123456
  security:
    user:
      name: dyz
      password: 123456

除基本的登录认证,还可以用来完成资源权限管理:当请求某个资源时,对角色进行认证,如果该角色拥有访问权限则正常访问,否则无法访问。

5.2 权限管理

admin:可以访问index和welcome页面

user:只能访问welcome页面

WebSecurityConfigurerAdapterSpring Security 5.7.0+ / Spring Boot 2.7+ 中已被弃用(deprecated) ,并在 Spring Security 6.x / Spring Boot 3.x完全移除

基于内存的用户认证(In-Memory Authentication) + URL 路径拦截(Filter Chain 授权)

5.2.1 新建页面

index.html

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head><title>首页</title></head>
<body>
<h2>🔴 管理员专属页面 - Index</h2>
<p>当前用户: <span sec:authentication="name"></span></p>
<p>角色: <span sec:authentication="principal.authorities"></span></p>

<a th:href="@{/welcome}">去Welcome页面</a> |
<form th:action="@{/logout}" method="post" style="display:inline;">
    <button type="submit">退出</button>
</form>
</body>
</html>

welcome.html

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head><title>欢迎</title></head>
<body>
<h2>欢迎页面 - Welcome</h2>
<p>当前用户: <span sec:authentication="name"></span></p>

<!-- 只有 ADMIN 能看到这个链接 -->
<div sec:authorize="hasRole('ADMIN')">
    <a th:href="@{/index}">去Index页面(仅管理员)</a>
</div>

<!-- 只有 USER 能看到这个提示 -->
<div sec:authorize="hasRole('USER')">
    <p>您是普通用户,无法访问 Index 页面</p>
</div>

<form th:action="@{/logout}" method="post" style="display:inline;">
    <button type="submit">退出</button>
</form>
</body>
</html>

5.2.2 创建controller

java 复制代码
package com.dyz.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class IndexController {

     @GetMapping("/index")
     public String index() {
          return "index";          // admin专属页面
}

    @GetMapping("/welcome")
    public String welcome() {
        return "welcome";        // 所有用户都能访问
    }

}

5.2.3 安全配置类

java 复制代码
package com.dyz.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth
                        // 必须放行 Security 内置端点,不写的话,login会被拦截
                        .requestMatchers("/login", "/logout", "/error").permitAll()
                        .requestMatchers("/index").hasRole("ADMIN")
                        .requestMatchers("/welcome").hasAnyRole("ADMIN", "USER")
                        .anyRequest().authenticated()
                )
                .formLogin(form -> form.defaultSuccessUrl("/welcome"));

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails admin = User.builder()
                .username("admin")
                .password(passwordEncoder().encode("123456"))
                .roles("ADMIN")
                .build();

        UserDetails user = User.builder()
                .username("user")
                .password(passwordEncoder().encode("123456"))
                .roles("USER")
                .build();

        return new InMemoryUserDetailsManager(admin, user);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

六、Spring Boot整合Shiro

通过过滤器和拦截器去拦截用户的各种请求,然后进行各种验证、登录、权限验证。

6.1 Shiro核心组件

  • Token:存储用户登录信息,用户在登录时创建,Shiro通过Token来判断当前用户的身份和权限。
  • Subject:存储当前用户信息,当前用户:用户/第三方进程/后台账户/其他正在交互的用户。
  • SecurityManager:Shiro的核心,用来管理内部的组件实例,实现安全认证和授权。
  • Realm:实现数据交互,对用户执行认证和授权验证时,Shiro从Realm中查找用户信息和权限信息。

6.1.1 pom.xml添加依赖

XML 复制代码
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.8.0</version>
        </dependency>

6.1.2 创建表

sql 复制代码
mysql> use sys;
Database changed
mysql> create table account(id int primary key auto_increment,username varchar(11),password varchar(11),permits varchar(20),role varchar(20));

6.1.3 创建实体类

java 复制代码
package com.dyz.entity;

import lombok.Data;

@Data
public class Account {
    private Integer id;
    private String username;
    private String password;
    private String permits;
    private String role;
}

6.1.4 创建控制器

java 复制代码
package com.dyz.controller;

import com.dyz.entity.Account;
import com.dyz.mapper.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/account")
public class AccountController {
    @Autowired
    private AccountMapper accountMapper;

    @GetMapping("/list")
    public List<Account> list(){
       return this.accountMapper.selectList(null);
    }
}

6.1.5 创建mapper

java 复制代码
package com.dyz.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dyz.entity.Account;

public interface AccountMapper extends BaseMapper<Account> {
}

6.1.6 创建service及其impl

java 复制代码
package com.dyz.service;

import com.dyz.entity.Account;

public interface AccountService {
    public Account findByUsername(String username);
}
java 复制代码
package com.dyz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dyz.entity.Account;
import com.dyz.mapper.AccountMapper;
import com.dyz.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;
    @Override
    public Account findByUsername(String username) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username);
        return this.accountMapper.selectOne(queryWrapper);
    }
}

6.1.7 创建Shiro过滤器

java 复制代码
package com.dyz.realm;

import com.dyz.entity.Account;
import com.dyz.service.AccountService;
import org.apache.shiro.authc.*;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.springframework.beans.factory.annotation.Autowired;

//AuthenticatingRealm只支持认证,不支持授权
// AuthorizingRealm 同时支持认证和授权
public class AccountRealm extends AuthorizingRealm {
    @Autowired
    private AccountService accountService;

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        Account account = this.accountService.findByUsername(token.getUsername());
        //验证密码
        if (account != null){
            return new SimpleAuthenticationInfo(account, account.getPassword(), getName());
    }
        return null;
    }
}

6.1.8 创建配置类

java 复制代码
package com.dyz.config;

import com.dyz.realm.AccountRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfiguration {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(
            @Qualifier("securityManager")DefaultWebSecurityManager securityManager
            ){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        return factoryBean;
    }
    @Bean
    public DefaultWebSecurityManager securityManager(
        @Qualifier("accountRealm")AccountRealm accountRealm
        ){
       DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
       securityManager.setRealm(accountRealm);
       return  securityManager;
    }
    @Bean
    public AccountRealm accountRealm(){
        return  new AccountRealm();
    }

}

6.2 Shiro 认证授权规则

认证过滤器:

  • anon:无需认证就能访问
  • authc:必须登录才能访问
  • authBasic:需要通过httpBasic认证
  • user:不一定通过认证,只要曾经被Shiro记录过登录状态的用户都可以正常发起请求

授权过滤器

  • perms:必须拥有权限才能访问
  • roles:必须拥有角色才能访问
  • port:请求的端口必须为指定值才可访问
  • res:请求必须时基于RESTful的才能访问
  • ssl:必须是安全的URL请求,协议为HTTPS

6.2.1 创建页面/要求/完善配置类

login.html、main.html、manage.html、administratoy.html

  • 登录状态才能访问main.html页面
  • 拥有manager权限的用户才能访问 manage.html
  • 拥有administrator角色才能访问administratoy.html

login.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    <table>
        <tr>
            <td>用户名:</td>
            <td>
                <input type="text" name = "username"/>
            </td>
        </tr>
        <tr>
            <td>密码:</td>
            <td>
                <input type="password" name="password"/>
            </td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="登录"/>
            </td>
        </tr>
    </table>

</form>

</body>
</html>

ShiroConfiguration.java

java 复制代码
 @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(
            @Qualifier("securityManager")DefaultWebSecurityManager securityManager
            ){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        //权限设置
        Map<String,String> map = new HashMap<>();
        map.put("/main","authc");
        map.put("/manage","perms[manager]");
        map.put("/administrator","roles[administrator]");
        factoryBean.setFilterChainDefinitionMap(map);
        //设置登陆页面
        factoryBean.setLoginUrl("/login");
        //设置未授权页面
        factoryBean.setUnauthorizedUrl("/unauth");
        return factoryBean;
    }

6.2.2 controller实现登录

java 复制代码
 @PostMapping("/login")
    public String login(String username, String password, Model model){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        try {
            subject.login(token);
            return "main";
        }catch (UnknownAccountException e){
            model.addAttribute("msg","用户名错误");
            return  "/login";
        } catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return  "/login";
        }
    }

    @RequestMapping("/unauth")
    @ResponseBody
    public String unauth(){
        return "未授权,无法访问";
    }

6.2.3 AccountRealm中实现授权方法

java 复制代码
 //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){
        //获取当前登录对象
        Subject subject = SecurityUtils.getSubject();
        Account account = (Account) subject.getPrincipal();
        //设置角色
        Set<String> roles = new HashSet<>();
        roles.add(account.getRole());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
        //设置权限
        info.addStringPermission(account.getPermits());
        return info;
    }
相关推荐
jjjava2.01 小时前
Java 多线程核心基础与线程安全
java·开发语言
147API1 小时前
Claude Opus 4.8 接口与工程落地分析:长任务调用链应该怎么设计
java·前端·数据库
lulu12165440782 小时前
Claude钩子系统架构设计:从执行时序到扩展机制
java·人工智能·python·ai编程
AI行业学习2 小时前
CC-Switch 下载、安装与使用配置指南【2026.5.29】
java·开发语言·vscode·python·eclipse·laravel
许彰午2 小时前
03_Java流程控制详解
java·开发语言·python
霍格沃兹测试学院-小舟畅学2 小时前
接口自动化测试的下一个十年:从脚本到Skills,让AI学会“如何测”
java·前端·人工智能
我命由我123452 小时前
Retrofit - URL 格式错误问题、支持 HTTP 与 HTTPS
java·http·https·java-ee·android studio·android-studio·retrofit
灰灰老师2 小时前
Docker部署Tomcat9
java·linux·docker·tomcat