第105天学习打卡(SpringBoot shiro整合thymeleaf Swagger SpringBoot集成Swagger 配置Swagger Swagger配置扫描接口)

shiro 整合thymeleaf

在pom.xml中整合shiro-thymeleaf

<!--shiro-thymeleaf-->
        <!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

添加的代码:

 Subject currentSubject = SecurityUtils.getSubject();
        Session session = currentSubject.getSession();
        session.setAttribute("loginUser",user);

完整代码:UserRealm.java

package com.kuang.config;

import com.kuang.pojo.User;
import com.kuang.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

//自定义的 UserRealm   extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserService userService;


    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=>授权doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("user:add");//无论什么用户等进来都会走这个方法
        //拿到当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();//拿到user对象

        //设置当前用户的权限
        info.addStringPermission(currentUser.getPerms());


        return info;
    }
//认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=>认证doGetAuthenticationInfo");

//        //用户名,密码 数据库中取
//        String name = "root";
//        String password = "123456";

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        //连接真实数据库
        User user = userService.queryUserByName(userToken.getUsername());
        if(user==null){
            //没有这个人
            return null; //爆出异常UnknownAccountException

        }
        Subject currentSubject = SecurityUtils.getSubject();
        Session session = currentSubject.getSession();
        session.setAttribute("loginUser",user);


//        if (!userToken.getUsername().equals(name)){
//            return null;//抛出异常  UnknownAccountException  用户名不存在
//
//        }

        //可以加密:MD5  MD5盐值加密  MD5不可逆

        //密码认证,shiro做   加密

        return new SimpleAuthenticationInfo(user,user.getPwd(),"");



    }
}

ShiroConfig.java

package com.kuang.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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;

import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {

    //ShiroFilterFactory  第三步
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);

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

        //授权,正常情况下,没有授权会跳转到未授权页面
        filterMap.put("/user/add","perms[user:add]"); //是user用户 还必须有add权限才可以访问
        filterMap.put("/user/update","perms[user:update]");
//        filterMap.put("/user/add","authc"); // 方法1
//        filterMap.put("/user/update","authc");
//把上面两行代码合成一个
        filterMap.put("/user/*","authc");
        bean.setFilterChainDefinitionMap(filterMap);
        //设置登录的请求
        bean.setLoginUrl("/toLogin");
        //未授权页面
        bean.setUnauthorizedUrl("/noauth");

        return bean;
    }


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

    //创建 realm对象, 需要自定义 第一步
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //整合ShiroDialect:用来整合shiro thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();

    }


}

index.html

<!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>
<!--从session中判断值-->
<div th:if="${session.loginUser==null}">
    <a th:href="@{/toLogin}">登录</a>
</div>
<p th:text="${msg}"></p>

<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>

下载的开源项目网址:https://github.com/WinterChenS/my-site

连接数据库:

image-20210517103652156

jdbc:mysql://localhost:3306/?serverTimezone=GMT

Swagger

学习目标:

  • 了解Swagger的作用和概念
  • 了解前后端分离
  • 在SpringBoot中集成Swagger

Swagger简介

前后端分离

Vue + SpringBoot

后端时代:前端只用管理静态页面;html==>后端。模板引擎JSP=>后端是主力。

前后端分离时代:

  • 后端:后端控制层, 服务层,数据访问层

  • 前端:前端控制层,视图层

    • 伪造后端数据,json交互。已经存在了,不需要后端,前端工程依旧能跑出来。
  • 前后端如何交互?===> API

  • 前后端相对独立,松耦合

  • 前后端甚至可以部署在不同的服务器上;

产生一个问题:

  • 前后端集成联调,前端人员和后端人员无法做到,及时协商。尽早解决,最终导致问题集中爆发;

解决方案:

  • 首先指定schema[计划的提纲],实时更新最新API,降低集成的风险
  • 早些年:制定word计划文档;
  • 前后端分离:
    • 前端测试后端接口:postman https://www.postman.com/
    • 后端提供接口,需要实时更新最新的消息及改动。

Swagger

  • 号称世界上最流行的APi框架
  • RestFul Api文档在线自动生成工具=>Api文档与API定义同步更新
  • 直接运行,可以在线测试API接口;
  • 支持多种语言(Java php)

官网地址:https://swagger.io/

在项目中使用Swagger需要springbox

  • swagger2
  • ui

SpringBoot集成Swagger

1.新建一个SpringBoot-web项目

2.导入相关依赖

注意点:导入最新的3.0.0版本访问不了页面,需要降级

<dependencies>
        <!-- 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>

3.编写一个Hello工程

package com.kuang.swagger.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController //由于我们没有页面所有要给他返回一个字符串
public class HelloController {

    @RequestMapping(value = "/hello")
    public String hello(){
        return "hello";
    }
}

**出现的错误: Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2021-04-23 19:25:08.794 ERROR 14588 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : **

一般出现这个错误的原因是:另外还存在一个项目在运行 ,把另外一个项目关掉即可。

4.配置Swagger==>Config

package com.kuang.swagger.config;

import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration //相当于@Component
@EnableSwagger2  //开启Swagger2
public class SwaggerConfig {
}

5.测试访问页面:http://localhost:8080/swagger-ui.html

image-20210517103720420

配置Swagger

Swagger的bean实例Docket;

package com.kuang.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;



@Configuration //相当于@Component
@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://blog.kuangstudy.com/", "24736743@qq.com");


        return new ApiInfo("狂神的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "v1.0", "https://blog.kuangstudy.com",
              contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }
}

image-20210517103743552

这个拥有所有的扫描接口:

image-20210517103803731

Swagger配置扫描接口

package com.kuang.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;



@Configuration //相当于@Component
@EnableSwagger2  //开启Swagger2
public class SwaggerConfig {
    //配置了swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                //RequestHandlerSelectors 配置要扫描接口的方式
                //basePackage指定要扫描的包
                .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
                .build();
    }

    //配置Swagger信息 = apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("秦疆", "https://blog.kuangstudy.com/", "24736743@qq.com");


        return new ApiInfo("狂神的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "v1.0", "https://blog.kuangstudy.com",
              contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }
}

image-20210517103820653

package com.kuang.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;



@Configuration //相当于@Component
@EnableSwagger2  //开启Swagger2
public class SwaggerConfig {
    //配置了swagger的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                //RequestHandlerSelectors 配置要扫描接口的方式
                //basePackage指定要扫描的包
                //any 扫描全部  apis(RequestHandlerSelectors.any())
                //none:都不扫描  apis(RequestHandlerSelectors.none())
                //withClassAnnotation():扫描类上的注解  apis(RequestHandlerSelectors.withClassAnnotation())  参数是一个注解的反射对象
                //withMethodAnnotation 扫描方法上的注解  apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
                .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
                //paths()过滤什么路径
                .paths(PathSelectors.ant("/kuang/**"))
                .build();
    }

    //配置Swagger信息 = apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("秦疆", "https://blog.kuangstudy.com/", "24736743@qq.com");


        return new ApiInfo("狂神的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "v1.0", "https://blog.kuangstudy.com",
              contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }
}

image-20210517103843846

配置是否启动Swagger

package com.kuang.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;



@Configuration //相当于@Component
@EnableSwagger2  //开启Swagger2
public class SwaggerConfig {
    //配置了swagger的Docket的bean实例

    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(false) //enable是否启动swagger,如果为false,则swagger不能在浏览器中访问
                //select  apis  build 是一套的
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
                //paths()过滤什么路径
                //.paths(PathSelectors.ant("/kuang/**"))
                .build();
    }

    //配置Swagger信息 = apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("秦疆", "https://blog.kuangstudy.com/", "24736743@qq.com");


        return new ApiInfo("狂神的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "v1.0", "https://blog.kuangstudy.com",
              contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }
}

image-20210517103901520

只希望我的Swagger在生产环境中使用,在发布的时候不使用?

  • 判断是不是生产环境 flag = false
  • 注入enble(flag)

SwaggerConfig.java

package com.kuang.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;



@Configuration //相当于@Component
@EnableSwagger2  //开启Swagger2
public class SwaggerConfig {
    //配置了swagger的Docket的bean实例

    @Bean
    public Docket docket(Environment environment){
        //设置要显示的Swagger环境
        Profiles profiles = Profiles.of("dev","test");
        //获取项目环境
        //通过environment.acceptsProfiles() 判断是否处在自己设定的环境当中
        boolean flag = environment.acceptsProfiles(profiles);
        System.out.println(flag);


        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(flag) //enable是否启动swagger,如果为false,则swagger不能在浏览器中访问
                //select  apis  build 是一套的
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
                //paths()过滤什么路径
                //.paths(PathSelectors.ant("/kuang/**"))
                .build();
    }

    //配置Swagger信息 = apiInfo
    private ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("秦疆", "https://blog.kuangstudy.com/", "24736743@qq.com");


        return new ApiInfo("狂神的SwaggerAPI文档",
                "即使再小的帆也能远航",
                "v1.0", "https://blog.kuangstudy.com",
              contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());

    }
}

application.properties

spring.profiles.active=dev

application-dev.properties

server.port=8081

application-pro.properties

server.port=8082

image-20210423211401503

image-20210517103924197

B站学习网址:【狂神说Java】SpringBoot最新教程IDEA版通俗易懂_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

posted @ 2021-04-23 21:18  豆豆tj  阅读(256)  评论(0)    收藏  举报