Springboot笔记

Spring5常用注解

@Autowired 自动装配 通过类型 ByType
若Autowired不能唯一自动装配上属性,则需要通过@Qualifier(Value=“XXX”)
@Resource 自动装配 通过名字、类型 ByName ByType
@Nullable 字段标记了该注解,说明这个字段可以为null
@Component 组件,放在类上,说明这个类被spring管理了(就是bean)
@Repository 用在dao层(或Mapper层),作用:被spring管理
@Service 用在service层,作用:被spring管理
@controller 用在controller层,作用:被spring管理
coding-Springboot笔记-
coding-Springboot笔记-

@RestController
Spring4之后新加入的注解,原来返回json需要@ResponseBody和@Controller配合。

即@RestController是@ResponseBody和@Controller的组合注解。

@ConfigurationProperties 用在实体类上,结合springboot的yaml配置中使用

coding-Springboot笔记-
coding-Springboot笔记-
@Mapper //注解表示这是一个mybatis的mapper类

@Mapper     //注解表示这是一个mybatis的mapper类
public class UserMapper {
}

@MapperScan(“com.example.demo.mapper”)效果与@Mapper一样

@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {

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

}

Springboot笔记

关于springboot+vue前后端分离的跨域问题

//跨域
package demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CrosConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");

    }
}

松散笔记

根据源码显示静态资源目录可以添加resources、public,且首页index.html页面在public、resources、static中可以直接显示,但在templates中需要添加模板引擎thymeleaf
coding-Springboot笔记-

在springboot中扩展springmvc,添加@Configuration 实现WebMvcConfigurer接口
coding-Springboot笔记-
bootstrap模板:
https://getbootstrap.com/docs/4.0/examples/

thymeleaf引入xmlns:th=“http://www.thymeleaf.org”
coding-Springboot笔记-

springboot使用thymeleaf补充

1.在pom.xml导入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.在templates下创建index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${msg}"></p>
</body>
</html>

3.在contorller跳转至index.html,通过Model传入数据,注意不能使用@RestController

@Controller
public class MyController {

    @RequestMapping({"/","/index"})
    public  String toIndex(Model model){
        model.addAttribute("msg","hello,shiro");
        return "index";
    }
}

在springboot的配置文件中
coding-Springboot笔记-
thymeleaf的国际化
coding-Springboot笔记-
coding-Springboot笔记-
coding-Springboot笔记-
coding-Springboot笔记-
coding-Springboot笔记-

mysql的jdbc配置

jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT

springboot整合Druid

#SpringBoot默认是不注入这些的,需要自己绑定
    #druid数据源专有配置
    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

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Properity
    #则导入log4j 依赖就行
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionoProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

在.yaml文件中通过type修改为Druid
coding-Springboot笔记-

引入pom.xml
coding-Springboot笔记-

在DruidConfig中绑定yaml中的配置
coding-Springboot笔记-

druid后台监控功能
通过/druid进入
coding-Springboot笔记-

springboot整合mybatis

官网:https://mybatis.org/mybatis-3/zh/getting-started.html
coding-Springboot笔记-

1.pom.xml导入mybatis

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

2.在resources下创建mapper.xml文件
coding-Springboot笔记-

<?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.example.demo.mapper.UserMapper">
    <select id="queryUserList" resultType="User">
    select * from User
    </select>

    <select id="queryUserById" resultType="User">
        select * from User where id= #{id}
    </select>
</mapper>

3.在application.properties配置文件

spring.datasource.username=root
spring.datasource.password=zzp
spring.datasource.url=jdbc:mysql://localhost:3306/login?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#整合mybatis
mybatis.type-aliases-package=com.example.demo.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml;

4.mapper层的mapper接口文件添加@Mapper注解或者在启动类添加@MapperScan(“com.example.demo.mapper”)扫描

@Mapper //表示该类是一个mybatis的mapper类
@Repository
public interface UserMapper {

    List<User> queryUserList();

    User queryUserById(int id);

    int addUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
}
@SpringBootApplication
//@MapperScan("com.example.demo.mapper")
public class DemoApplication {

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

}

springboot中SpringSecurity环境搭建

(需注意springboot版本问题)
coding-Springboot笔记-
1.在pom.xml中引入依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
        <!-- security       -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>

2.创建SecurityConfig

//AOP拦截器
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //链式编程
        //首页所有人可以访问,功能页只有对应有权限的人才能访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/levle1").hasRole("vip");

        //无权限默认会到登录页面,需要开启登录页面
        http.formLogin();
        //注销,开启功能
        http.logout().logoutSuccessUrl("/");//登出并跳转
        //开启记住我功能
        http.rememberMe();

    }
    //认证
    //认证,springboot2.1.x 可以直接使用
    //需要密码加密:PasswordEncoder
    //在Spring Security 5.0+新增了很多的加密方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("456").password(new BCryptPasswordEncoder().encode("456")).roles("vip")
                .and()//通过and()拼接下一个用户
                .withUser("root").password(new BCryptPasswordEncoder().encode("admin")).roles("vip");
    }
}

Springboot+vue中EasyExcel(占用内存小)的使用

springboot+vue结合easyexcel的导出

1.在springboot项目pom.xml中导入easyexcel的依赖

 <!--EasyExcel-->
        <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>

2.创建ExcelUtil.java的工具类


/**
 * 导出excel工具类
 * response 返回对象
 * list excel表中记录
 *
 */
public class ExcelUtil {

    public static void writeExcel(HttpServletResponse response, List<PingpangIntegral> list) throws IOException {
        ExcelWriter excelWriter= EasyExcel.write(response.getOutputStream()).build();
        //定义工作表对象
        WriteSheet sheet=EasyExcel.writerSheet(0,"Sheet").head(PingpangIntegral.class).build();
        //往excel文件中写入数据
        excelWriter.write(list,sheet);
        //关闭输出流
        excelWriter.finish();;
    }
}

3.在实体类上添加@ExcelProperty(“列名”)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PingpangIntegral implements Serializable {
    @ExcelProperty("id")
    private Integer id;

    /**
     * 积分差区间下限
     */
    @ExcelProperty("pingpangLow")
    private Integer pingpangLow;
 

4.在controller层调用

@RequestMapping(value = "/export",method = RequestMethod.POST)
    public void export(HttpServletResponse response,@RequestBody PingpangIntegral pingpangIntegral) throws IOException {
        int kinds=pingpangIntegral.getPingpangKinds();
        List list= pingpangService.query(kinds);
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition","attachment;filename="+"_.xlsx");
        ExcelUtil.writeExcel(response,list);
    }

    @RequestMapping(value = "/exportAll",method = RequestMethod.GET)
    public void exportAll(HttpServletResponse response) throws IOException {
        List list= pingpangService.selectAll();
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition","attachment;filename="+"_.xlsx");
        ExcelUtil.writeExcel(response,list);
    }

5.在前端vue获取

methods: {
 handleExportXls() {
      if(this.value==null){
        axios.get('http://localhost:8081/exportAll',{
          responseType: 'blob'
        }).then((res)=>{
          this.downloadFile(res.data);
        }).catch(function (error) {
        })
      }
      else {
        axios.post('http://localhost:8081/export',{
          pingpangKinds:this.value,
        },{
          responseType: 'blob'
        }).then((res)=>{
          this.downloadFile(res.data);
        }).catch(function (error) {
        })
      }

    },
    downloadFile(data) {
      if (!data) {
        return
      }
      const link = document.createElement('a');
      let blob = new Blob([data], {type: 'application/vnd.ms-excel'});
      link.style.display = 'none';
      link.href = URL.createObjectURL(blob);

      link.setAttribute('download', '记录信息' + '.xlsx');
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
    }

注意需要在axios的config中配置 responseType: ‘blob’

springboot+vue结合easyexcel的导入

点击进入:easyexcel官网
1.导入easyexcel的依赖

 <!--EasyExcel-->
        <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>

2.实体类上有@ExcelProperty

	@ExcelProperty("id")
    private Integer id;
    @ExcelProperty("pingpangLow")
    private Integer pingpangLow;

3.DAO

@Mapper
public interface PingpangIntegralDao {
    
    void save(List<PingpangIntegral> list);
    
}

注意导入需要插入数据库操作时,若用的时mybatis可以编写模块插入的sql语句

<insert id="save"  parameterType="List" >
    insert into pingpang_integral (id,pingpangLow, pingpangUp, pingpangHeight,
    pingpangLower, pingpangLoserUp, pingpangLoserLower,
    pingpangKinds)
    VALUES
    <foreach collection="list"  index="index" item="item"  separator=",">
      (#{item.id},#{item.pingpangLow},#{item.pingpangUp},#{item.pingpangHeight},#{item.pingpangLower},#{item.pingpangLoserUp},#{item.pingpangLoserLower},#{item.pingpangKinds})
    </foreach>
  </insert>

4.监听器配置

package demo.util;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import demo.dao.PingpangIntegralDao;
import demo.pojo.PingpangIntegral;
import org.mybatis.logging.Logger;
import org.mybatis.logging.LoggerFactory;


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

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<PingpangIntegral> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<PingpangIntegral> list = new ArrayList<PingpangIntegral>();
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */

    private PingpangIntegralDao pingpangIntegralDao;

    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数

    }
    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param
     */
    public DemoDataListener(PingpangIntegralDao pingpangIntegralDao) {

        this.pingpangIntegralDao = pingpangIntegralDao;
    }



    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(PingpangIntegral data, AnalysisContext context) {

        System.out.println(JSON.toJSONString(data));
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }
    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        System.out.println("所有数据解析完成!");
    }
    /**
     * 加上存储数据库
     */
    private void saveData() {
        System.out.println(list.size()+"条数据,开始存储数据库!");
        pingpangIntegralDao.save(list);
        System.out.println("存储数据库成功!");
    }
}

5.controller层

  @RequestMapping(value = "/input",method = RequestMethod.POST)
    public String upload(@RequestBody MultipartFile file) throws IOException {
        System.out.println(file);
        EasyExcel.read(file.getInputStream(), PingpangIntegral.class, new DemoDataListener( pingpangIntegralDao)).sheet().doRead();
        return "success";
//        String PATH="C:\Users\指尖王者\Desktop\";
//        String fileName = PATH + "记录信息.xlsx";
//        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
//        EasyExcel.read(fileName, PingpangIntegral.class, new DemoDataListener(pingpangIntegralDao)).sheet().doRead();
//        return "success";
    }

6.vue端传入file
1.使用el-upload上传文件

 <el-upload
        class="upload-demo inline-block"
        action="uploadExcel"
        :http-request="httpRequest"
        :before-upload="beforAvatarUpload"
        :show-file-list="false">
        <el-button type="primary" icon="el-icon-download" size="small" >导入</el-button>
      </el-upload>
<!--inline-block使el-upload与普通按钮在同一行-->
.inline-block {
  display: inline-block;
}

2.导入前判断文件格式

 //判断文件类型是否正确
    beforAvatarUpload(file){
      const isxls=file.type==="application/vnd.ms-excel"?true:file.type==="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"?true:false;
      if(!isxls){
        this.$message.error("只能上传.xls或.xlsx格式文件")
      }
      return isxls
    },

3.导入excel

 //导入excel
    httpRequest(params){
      let formdata=new FormData();
      formdata.append("file",params.file);
      let config = {
        // 一定要定义头
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
      axios.post('http://localhost:8081/input',formdata,config).then((res)=>{
        console.log(res.status)
        if(res.status==200){
          this.$message({
            message: '导入成功',
            type: 'success'
          });
        }
      }).catch(res=> {
        if(res.status!=200){
          this.$message.error('导入失败(注:不能导入已有数据)')
        }

      })

需注意formdata与config定义头

let formdata=new FormData();
      formdata.append("file",params.file);
      let config = {
        // 一定要定义头
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
      axios.post('http://localhost:8081/input',formdata,config).then((res)=>{}

Apache POI(占用内存较大)

coding-Springboot笔记-
coding-Springboot笔记-
coding-Springboot笔记-
coding-Springboot笔记-

springboot整合shiro

1.在pom.xml中导入依赖

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

2.自定义一个realm
UserRealm

//自定义的realm
public class UserRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了授权");
        return null;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证");
        return null;
    }
}

3.创建ShiroConfig

@Configuration
public class shiroConfig {
    //ShiroFileterFactoryBean(第三步)
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        return shiroFilterFactoryBean;
    }

    //DefaultWebSecurityManager(第二步)
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建realm对象,需要自定义(第一步)
    @Bean(name = "userRealm")//name属性可省略
    public UserRealm userRealm(){
        return new UserRealm();
    }

shiro实现拦截登录

1.在shiroConfig中配置

//ShiroFileterFactoryBean(第三步)
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean sfb = new ShiroFilterFactoryBean();
        //设置安全管理器
        sfb.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /*
        * anon:无需认证就可以访问
        * authc:必须认证才能访问
        * user:必须拥有 “记住我” 功能才能访问
        *perms:拥有对某个资源的权限才能访问
        *role:拥有某个角色权限才能访问
        * */
        Map<String, String> filterMap=new LinkedHashMap<>();
        filterMap.put("/user/add","anon");
        filterMap.put("/user/update","authc");

        sfb.setFilterChainDefinitionMap(filterMap);
        //设置登录的请求
        sfb.setLoginUrl("/toLogin");

        
        return sfb;
    }

shiro实现用户认证

1.controller层

@RequestMapping("/login")
    public String login(String username, String password, Model model) {


        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);


        try {
            subject.login(token);//执行登录方法,如果没有异常就说明ok
            return "index";
        } catch (UnknownAccountException e) {//用户名不存在
            model.addAttribute("msg", "用户名错误");
            return "user/login";
        } catch (IncorrectCredentialsException e) {//密码不存在
            model.addAttribute("msg", "密码错误");
            return "user/login";
        }

    }

2.UserRealm

//认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证");
        //用户名 密码 一般从数据库中获取 用于校验
        String name="root";
        String password="123";

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        if (!userToken.getUsername().equals(name)) {
            return null;//抛出异常 UnknownAccountException
        }

        //密码认证 shiro自行完成 防止接触密码泄露
        return new SimpleAuthenticationInfo("",password,"");
    }

shiro整合mybatis(Druid数据源)

1.在pom.xml导入依赖

 		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

2.配置application.yaml

 #SpringBoot默认是不注入这些的,需要自己绑定
      #druid数据源专有配置
      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

      #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
      #如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Properity
      #则导入log4j 依赖就行
      filters: stat,wall,log4j
      maxPoolPreparedStatementPerConnectionSize: 20
      useGlobalDataSourceStat: true
      connectionoProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

3.在applica.properties配置mybatis

# thymeleaf
spring.thymeleaf.cache=false    

#配置mybatis
mybatis.type-aliases-package=com.example.pojo
mybatis.mapper-locations=classpath:mapper/*.xml

4.修改UserRealm中的用户名和密码为数据库的信息即可

 //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证");
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        //用户名 密码 一般从数据库中获取 用于校验
        User user=userService.selectname(userToken.getUsername());
        
        if (user==null) {
            return null;//抛出异常 UnknownAccountException
        }
        //密码认证 shiro自行完成 防止接触密码泄露
        return new SimpleAuthenticationInfo("",user.getPassword(),"");
    }

shiro请求授权实现

1.在shiroConfig第三步中设置权限拦截

 //ShiroFileterFactoryBean(第三步)
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean sfb = new ShiroFilterFactoryBean();
        //设置安全管理器
        sfb.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /*
        * anon:无需认证就可以访问
        * authc:必须认证才能访问
        * user:必须拥有 “记住我” 功能才能访问
        *perms:拥有对某个资源的权限才能访问
        *role:拥有某个角色权限才能访问
        * */
        //拦截
        Map<String, String> filterMap=new LinkedHashMap<>();

        //用户拥有“user:add”权限时 客访问
        filterMap.put("/user/add","perms[user:add]");

        //用户通过auchc认证后可访问
        filterMap.put("/user/update","perms[user:update]");

        sfb.setFilterChainDefinitionMap(filterMap);
        //设置登录的请求, 未登录则跳转至该页面
        sfb.setLoginUrl("/toLogin");

        //未授权则跳转至该页面
        sfb.setUnauthorizedUrl("/unauthorized");


        return sfb;
    }

2.在UserRealm中授予权限,通过获取用户表中的权限列,授予相应权限

 //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了授权");
        //SimpleAuthorizationInfo执行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //该位置将会给每个用户授于“user:add”权限
//        info.addStringPermission("user:add");
        //拿到当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();//可以拿到SimpleAuthenticationInfo(user,user.getPassword(),"")中的user
        //设置当前用户的权限
        System.out.println(currentUser);
        System.out.println(currentUser.getPerms());

        info.addStringPermission(currentUser.getPerms());
        if(currentUser.getPerms()!=null){
            return info;
        }
        else {
            return null;
        }
    }

shiro整合Thymeleaf

1.导入依赖

<!--shiro整合thymeleaf-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

2.在UserRealm的认证登录成功时获取session

//认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证");
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        //用户名 密码 一般从数据库中获取 用于校验
        User user=userService.selectname(userToken.getUsername());

        if (user==null) {
            return null;//抛出异常 UnknownAccountException
        }
        
        
        //登时成功时,获取session
        Subject currentsubject = SecurityUtils.getSubject();
        Session session = currentsubject.getSession();
        session.setAttribute("loginUser",user);

        //密码认证 shiro自行完成 防止接触密码泄露
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
    }

3.首页index.html页面
通过该xmlns整合shiro与thymeleaf

xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${msg}"></p>
<div th:if="${session.loginUser==null}">
    <a th:href="@{/toLogin}">登录</a>
</div>
<hr>
<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>
匿名

发表评论

匿名网友