Springboot、mybatis、excel工具、shiro、swagger、Page分页等详细用法

Spring5常用注解

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

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

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

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

在这里插入图片描述
在这里插入图片描述
@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前后端分离的跨域问题

//跨域
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 CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("*")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");

    }
}

松散笔记

bootstrap模板地址

根据源码显示静态资源目录可以添加resources、public,且首页index.html页面在public、resources、static中可以直接显示,但在templates中需要添加模板引擎thymeleaf
在这里插入图片描述
thymeleaf引入xmlns:th=“http://www.thymeleaf.org”
在这里插入图片描述
在springboot中扩展springmvc,添加@Configuration 实现WebMvcConfigurer接口
在这里插入图片描述

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的配置文件中
在这里插入图片描述
thymeleaf的国际化
在这里插入图片描述
在这里插入图片描述
th:text="#{}"
在这里插入图片描述
在这里插入图片描述

注:mysql的jdbc配置,mysql8.0+需要写上时区,serverTimezone=GMT

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
在这里插入图片描述

引入pom.xml
在这里插入图片描述

在DruidConfig中绑定yaml中的配置
在这里插入图片描述

druid后台监控功能
通过/druid进入
在这里插入图片描述

springboot整合mybatis

官网:https://mybatis.org/mybatis-3/zh/getting-started.html
在这里插入图片描述

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文件
在这里插入图片描述

<?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版本问题)
在这里插入图片描述
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(占用内存较大)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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>

AutoPOI(Excel工具)的使用方法

   /**
     * 导出excel
     *
     * @param request
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(SysAnnouncement sysAnnouncement,HttpServletRequest request) {
        // Step.1 组装查询条件
        QueryWrapper<SysAnnouncement> queryWrapper = QueryGenerator.initQueryWrapper(sysAnnouncement, request.getParameterMap());
        //Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        List<SysAnnouncement> pageList = sysAnnouncementService.list(queryWrapper);
        //导出文件名称
        mv.addObject(NormalExcelConstants.FILE_NAME, "系统通告列表");
        mv.addObject(NormalExcelConstants.CLASS, SysAnnouncement.class);
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("系统通告列表数据", "导出人:"+user.getRealname(), "导出信息"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<SysAnnouncement> listSysAnnouncements = ExcelImportUtil.importExcel(file.getInputStream(), SysAnnouncement.class, params);
                for (SysAnnouncement sysAnnouncementExcel : listSysAnnouncements) {
                	if(sysAnnouncementExcel.getDelFlag()==null){
                		sysAnnouncementExcel.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
					}
                    sysAnnouncementService.save(sysAnnouncementExcel);
                }
                return Result.ok("文件导入成功!数据行数:" + listSysAnnouncements.size());
            } catch (Exception e) {
                log.error(e.getMessage(),e);
                return Result.error("文件导入失败!");
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("文件导入失败!");
    }

springboot结合PageHelper的分页查询

1.导入pagehelper依赖

<!--pagehelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

2.配置PageHelperConfig文件

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class PageHelperConfig {

    public PageHelper getPageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("offsetAsPageNum","true");
        properties.setProperty("rowBoundsWithCount","true");
        properties.setProperty("reasonable","true");
        //配置数据库方言
        properties.setProperty("dialect","mysql");
        pageHelper.setProperties(properties);
        return pageHelper;
    }

}

3.service以及serviceImpl
Service

import com.github.pagehelper.PageInfo;
import demo.pojo.PingpangIntegral;

public interface PageService {
    PageInfo<PingpangIntegral> findByPage(int pageNum, int pageSize);
}

ServiceImpl

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import demo.dao.PingpangIntegralDao;
import demo.pojo.PingpangIntegral;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
public class PageServiceImpl implements PageService {

    @Resource
    private PingpangIntegralDao pingpangIntegralDao;

    @Override
    public PageInfo<PingpangIntegral> findByPage(int pageNum, int pageSize) {
        //分页查询,会对紧跟着的第一个select方法进行分页查询,后面除非再次调用否则不会进行分页
        PageHelper.startPage(pageNum, pageSize);

        List<PingpangIntegral> articleList = pingpangIntegralDao.selectAll();
//        int totalNum = pingpangIntegralDao.count();

        PageInfo<PingpangIntegral> pageInfo = new PageInfo<>();
        //设置当前页
        pageInfo.setPageNum(pageNum);
        //设置每页的数量
        pageInfo.setPageSize(pageSize);
        //设置当前页的数量
        pageInfo.setSize(pageSize);
        //设置结果集
        pageInfo.setList(articleList);
        return pageInfo;
    }

}

4.application.properties(可不配置)

#分页助手pageHelper的配置 application.properties配置(可选,因为mybatis会自动配置):
#pagehelper.helper-dialect=mysql
#
#pagehelper.params=count=countSql
#
#pagehelper.reasonable=true
#
#pagehelper.support-methods-arguments=true

5.contorller层(PingpangIntegral为实体类)

@RestController

public class PageController {

    @Autowired
    private PageService pageService;

    /**
     * 分页查询
     * @param pageNum   //当前是第几页
     * @param pageSize  //每页的数量
     * @return
     */
    @RequestMapping("/findByPage")
    @ResponseBody
    public PageInfo<PingpangIntegral> findByPage(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "5") int pageSize) {
        //分页查询
        PageInfo<PingpangIntegral> pageInfo = pageService.findByPage(pageNum, pageSize);

        //将数据转换为json
//        String jsonString = JSON.toJSONString(pageInfo);
        return pageInfo;
    }
}

springboot结合swagger

1.导入springfox-swagger-ui与springfox-swagger2依赖

<!--swagger-->
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

或者导入

 <!-- https://mvnrepository.com/artifact/com.spring4all/swagger-spring-boot-starter -->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.1.RELEASE</version>
        </dependency>

2.配置SwaggerConfig


@Configuration
@EnableSwagger2         //开启Swagger2
public class SwaggerConfig {
}

3.通过访问http://localhost:8080/swagger-ui.html可打开swagger页面(注:3.0.0版本无法打开swagger页面,可以降级)
在这里插入图片描述
4.配置Swagger
Swagger的bean实例Docket

@Configuration
@EnableSwagger2         //开启Swagger2
public class SwaggerConfig {

    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }
    //配置Swagger新消息 apiInfo
    private ApiInfo apiInfo(){

        //作者信息
        Contact contact = new Contact("森", "https://www.baidu.com", "2460718527@qq.com");

        return  new ApiInfo("我的SwaggerApi文档",
                "酷裤的森",
                "1.0",
                "urn:tos",
                contact,        //放contact,默认值为 DEFAULT_CONTACT
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList<VendorExtension>());
    }

}

在这里插入图片描述
5.Swagger配置扫描接口
Docket.select()


    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(true) //是否启动swagger,若为false,则swagger不能再浏览器中访问
                .select()
                //RequestHandlerSelectors 配置要扫描接口的方式
                //basePackage 扫描指定包 apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
                //any() 扫描全部
                //none() 不扫描
                //withClassAnnotation() 扫描类上的注解,参数为一个注解的反射对象
                //withMethodAnnotation() 扫描方法上的注解,参数为一个注解的反射对象,只扫描有GetMapping的
                .apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
                //paths() 过滤路径 只扫描有example请求的接口
                .paths(PathSelectors.ant("/example/**"))
                .build();
    }

6.实现Swagger在开发环境中使用,在发布时不使用
(1)新建application-dev.properties(开发环境)

server.port=8081

application-pro.properties(发布环境)

server.port=8082

application.properties 选择激活某一环境

#激活dev环境
spring.profiles.active=dev 

(2)配置SwaggerConfig


@Configuration
@EnableSwagger2         //开启Swagger2
public class SwaggerConfig {

    //配置Swagger的Docket的bean实例
    @Bean
    public Docket docket(Environment environment){

        //设置要显示的swagger环境
        Profiles profiles=Profiles.of("dev","test");//可存在多个环境变量实例dev、test

        //获取项目的环境:
        environment.getActiveProfiles();

        //通过environment.acceptsProfiles判断是否处在自己设定的环境中
        boolean flag = environment.acceptsProfiles(profiles);


        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(flag) //是否启动swagger,若为false,则swagger不能再浏览器中访问
                .select()
                //RequestHandlerSelectors 配置要扫描接口的方式
                //basePackage 扫描指定包 apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
                //any() 扫描全部
                //none() 不扫描
                //withClassAnnotation() 扫描类上的注解,参数为一个注解的反射对象
                //withMethodAnnotation() 扫描方法上的注解,参数为一个注解的反射对象,只扫描有GetMapping的
//                .apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
                //paths() 过滤路径 只扫描有hello请求的接口
                .paths(PathSelectors.ant("/hello/**"))
                .build();
    }
    //配置Swagger新消息 apiInfo
    private ApiInfo apiInfo(){

        //作者信息
        Contact contact = new Contact("森", "https://www.baidu.com", "2460718527@qq.com");

        return  new ApiInfo("我的SwaggerApi文档",
                "酷裤的森",
                "1.0",
                "urn:tos",
                contact,        //放contact,默认值为 DEFAULT_CONTACT
                "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList<VendorExtension>());
    }

}

7.配置API文档分组
(1)配置一个组的名称

//return new Docket(DocumentationType.SWAGGER_2)
                //.apiInfo(apiInfo())
                .groupName("组的名称")

(2)配置多个组 (即在SwaggerConfig中创建多个Docket实例)

@Configuration
@EnableSwagger2         //开启Swagger2
public class SwaggerConfig {

    //多个Docket
    @Bean
    public Docket docket1(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("A");
    }
    @Bean
    public Docket docket2(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("B");
    }
    @Bean
    public Docket docket3(){
        return new Docket(DocumentationType.SWAGGER_2).groupName("C");
    }

在这里插入图片描述
8.contorller中配置

//接口中返回值中存在实体类,就会被扫描到swagger中
    @PostMapping("/user")
    public  User user(){
        return new User();
    }

9.在实体类中添加说明

@ApiModel("用户实体类") //在swagger中给实体类添加说明
public class User {

    @ApiModelProperty("用户名") //在swagger中给属性添加说明
    public String username;
    @ApiModelProperty("用户名")
    public String password;
}

在这里插入图片描述
10.@Api注释用法

 //@ApiOperation()放在接口上
    @ApiOperation("hello2接口")
    @GetMapping(value = "/hello2")
    public  String hello2(@ApiParam("用户名") String username){
        return "hello"+username;
    }

jeecg-boot统一文件上传规则.

1.配置application.yaml文件

#jeecg专用配置
jeecg :
  # 本地:local\Minio:minio\阿里云:alioss
  uploadType: local
  path :
    #文件上传根目录 设置
    upload: D://opt//upFiles
    #webapp文件路径
    webapp: D://opt//webapp
  #短信秘钥
  sms:
     accessKeyId: ??
     accessKeySecret: ??
  shiro:
     excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**
  #阿里云oss存储配置
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com
    accessKey: ??
    secretKey: ??
    bucketName: jeecgos
    staticDomain: https://static.jeecg.com
  # ElasticSearch 6设置
  elasticsearch:
    cluster-name: jeecg-ES
    cluster-nodes: 127.0.0.1:9200
    check-enabled: false
  # 表单设计器配置
  desform:
    # 主题颜色(仅支持 16进制颜色代码)
    theme-color: "#1890ff"
  # 在线预览文件服务器地址配置
  file-view-domain: http://fileview.jeecg.com
  # minio文件上传
  minio:
    minio_url: http://minio.jeecg.com
    minio_name: ??
    minio_pass: ??
    bucketName: otatest

2.controller层

/**
	 * 文件上传统一方法
	 * @param request
	 * @param response
	 * @return
	 */
	@PostMapping(value = "/upload")
	public Result<?> upload(HttpServletRequest request, HttpServletResponse response) {
		Result<?> result = new Result<>();
		String savePath = "";
		String bizPath = request.getParameter("biz");
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
		if(oConvertUtils.isEmpty(bizPath)){
			if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
				//未指定目录,则用阿里云默认目录 upload
				bizPath = "upload";
				//result.setMessage("使用阿里云文件上传时,必须添加目录!");
				//result.setSuccess(false);
				//return result;
			}else{
				bizPath = "";
			}
		}
		if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
			//针对jeditor编辑器如何使 lcaol模式,采用 base64格式存储
			String jeditor = request.getParameter("jeditor");
			if(oConvertUtils.isNotEmpty(jeditor)){
				result.setMessage(CommonConstant.UPLOAD_TYPE_LOCAL);
				result.setSuccess(true);
				return result;
			}else{
				savePath = this.uploadLocal(file,bizPath);
			}
		}else{
			savePath = sysBaseAPI.upload(file,bizPath,uploadType);
		}
		if(oConvertUtils.isNotEmpty(savePath)){
			result.setMessage(savePath);
			result.setSuccess(true);
		}else {
			result.setMessage("上传失败!");
			result.setSuccess(false);
		}
		return result;
	}

3.vue端结合ant design vue

<template>
    <div>
      <a-upload
        list-type="picture"
        action="http://127.0.0.1:8081/jeecg-boot/upload"
        :preview-file="previewFile"
      >
        <a-button> <a-icon type="upload" /> Upload </a-button>
      </a-upload>
    </div>
</template>
  <script>
    export default {
      name: "Video",
      methods: {
        previewFile(file) {
          console.log('Your upload file:', file);
          // Your process logic. Here we just mock to the same file
          return fetch('http://127.0.0.1:8081/jeecg-boot/upload', {
            method: 'POST',
            body: file,
          })
            .then(res => res.json())
            .then(({ thumbnail }) => thumbnail);
        },
      },
    };
  </script>

<style scoped>

</style>

springboot结合redis

1.导入pom依赖

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

2.配置连接

#配置redis
spring.redis.host=127.0.0.1
spring.redis.port=6379

3.测试类

package com.example;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class SpringbootRedisApplicationTests {


    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {

        //redisTemplate 操作不同数据类型 常用的方法都可以通过redisTemplate操作
        //opsForCluster() 操作字符串 类似String
        //opsForList() 操作List 类似List

//        获取redis的连接对象
//        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//        connection.flushDb();
//        connection.flushAll();

        redisTemplate.opsForValue().set("mykey","zzp帅哥");
        System.out.println(redisTemplate.opsForValue().get("mykey"));
    }

}

springboot结合mybatis-plus

1.导入pom依赖

<!--引入mabatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

2.配置在application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/login?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
spring.datasource.username=root
spring.datasource.password=zzp
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

3.在UserMapper继承BaseMapper类

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

Springboot自带MD5加密

import org.springframework.util.DigestUtils;

//对密码进行 md5 加密
String md5Password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值