springboot整合其它技术栈(全网最详细)

SpringBoot

基于SpringFramework进行二次开发的一个web快速开发框架(创建,编写项目等)

创建项目

  1. 去官网创建Spring Initializr (springboot.io)
  2. 用idea开发工具创建

什么是配置文件?用途是什么?

保存了很多配置参数的

配置文件

  • xxx.properties 配置参数:key=value键值对
  • xxx.yml 配置参数JSON:key:value
  • application.properties,application.yml配置参数文件
  • bootstrap.properties,bootstrap.yml是项目引导文件

多环境的配置

  • 开发环境
  • 测试环境
  • 预生产环境
  • 生成环境

IOC容器

  • 基于注解@Component (@ComponentScan basepackage)
  • @Configurtion
  • @XML Bean
//元注解
@Target({ElementType.TYPE})//生效范围
@Retention(RetentionPolicy.RUNTIME)//声明周期1.源码阶段有效2.编译阶段有效3.运行阶段有效
@Documented
@Inherited

@SpringBootConfiguration

@SpringBootConfiguration->@Configuration配置类==xml

配置文件的注解

@EnableAutoConfiguration

自动配置关键注解->spring.factories

先把类的全路径写在一个配置文件,然后用反射机制创建对象,把对象塞进ioc容器

约定优于配置 配置优于编码

常用注解

@SpringBootApplication //Boot应用启动类
@SpringBootConfiguration//申明boot配置类 =@Configuration配置类==xml
@EnableAutoConfiguration //开启自动配置
@ConfigurationProperties //批量配置参数
@Value   //注入参数
@Configuration      //申明配置类
@ComponentScan  //组件扫描
@RequestMapping     //定义请求路径
@GetMapping  //定义GET请求路径
@PostMapping  //定义POST请求路径
@Controller      //申明控制类 @RestController //申明restful风格控制类
@Service          //申明业务逻辑类
@Component  //定义组件类(Bean)
@RequestParam  //绑定请求参数
@RequestBody   //JSON格式获取HTTP 请求BODY部分数据
@Resource       //自动装配对象 java
@Autowired     //自动装配对象 spring
@PathVariable  //从路径上获取占位符对应参数
@Mapper      //mybatis 数据处理接口
@Bean    //定义 JavaBean
@JsonIgnore//忽略某个字段,不展示给前端
  1. @SpringBootApplication //boot应用启动类
  2. @SpringBootConfiguration //申明boot配置类==@Configuration
  3. @EnableAutoConfiguration //开启自动配置
  4. @ConfigurationProperties //批量配置参数
  5. @Value //配置参数值
  6. @Configuration //申明配置类
  7. @ComponentScan //组件扫描
  8. @RequestMapping //定义请求路径
  9. @GetMapping //定义get请求路径
  10. @PostMapping //定义post请求路径
  11. @Controller //申明控制类
  12. @RestController 申明restful风格控制类
  13. @Service //申明业务逻辑类
  14. @Component //定义组件类
  15. @RequestParam //绑定请求参数
  16. @RequestBody //JSON格式获取HTTP请求BODY部分数据
  17. @Resource //自动装配对象 Java
  18. @Autowired //自动装配对象spring
  19. @PathVariable //从路径上获取占位符对应参数
  20. @Mapper //mybatis数据处理接口
  21. @Bean //定义javabean 注册到ioc

分析软件应用(MVC模式)

在这里插入图片描述

在这里插入图片描述

Springboot日志框架LOGBACK

日志

软件运行过程中用于记录,执行,轨迹的代码块

日志的优点

  • 能够辅助定位软件运行问题
  • 提供统计数据

以前的日志

  • System.out.println()–>往控制台输出一行日志

日志级别

  • trace跟踪
  • debug调试
  • info信息
  • warn警告
  • error错误

日志的格式

时间戳毫秒级 日志级别 线程ID 线程名字 执行类 日志信息

一般info级别就可以;日志也会耗时间的

日志的配置

#推荐的设置方式
#打开日志级别 默认是info
logging.level.root=warn
logging.level.web=debug
logging.level.sql=error
#打印日志信息文件
logging.file.name=s98-1026

测试

package com.spring.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogController {

    //获取日志记录器;注意导入的包名
    final static Logger logger = (Logger) LoggerFactory.getLogger(LogController.class);

    @RequestMapping("/showlog")
    public String show() {
        logger.trace("记录trace级别日志");
        logger.debug("记录debug级别日志");
        logger.info("记录info级别日志");
        logger.warn("记录warn级别日志");
        logger.error("记录error级别日志");
        return null;
    }
}

JWT (Json Web Token)

  • 登录视图->扫描,手机号+验证码
  • 控制层验证手机号码验证码有效
  • 记录登录信息-SESSION-Cookie

jwt的格式

kjsdfgkjsdfb.lshflsdhfds.lsdkhfisdlg

(头部信息.挂载部分.签名信息)

  • kjsdfgkjsdfb 头部信息:加密协议
  • lshflsdhfds 挂载部分:数据体{user:“milo”,pwd:“xxx”}
  • lsdkhfisdlg 签名信息:加密

JWT用法

sadfas = encode(a.s.d,密钥(任意一个字符串))

qwrr = decode(sadfas,密钥(任意一个字符串))

JWT依赖包

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.3.0</version>
</dependency>

生成Token

package com.spring.utiltools;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Verification;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTools {
    //密钥
    public static final String KEY = "qanap&#!";
    //生成token(加密)
    public static String createToken() {
       //token生成器
        JWTCreator.Builder builder = JWT.create();
        //保存头部信息
        Map<String, Object> claims = new HashMap<>();
        claims.put("type", "HS256");
        builder.withHeader(claims)
        .withJWTId("1001")
        .withIssuedAt(new Date());//token生效时间
        Date expDate = new Date(System.currentTimeMillis()+(7*24*60*60*1000));
       return builder.withExpiresAt(expDate)//token失效数据
       .withClaim("attrs",attrMap)
        .sign(Algorithm.HMAC256(KEY));
    }
    public static void main(String[] args) {
        System.out.println(JwtTools.createToken());
    }
}

解析Token

public static void checkToken(String token) {
        //根据加密算法与密钥获取验证器
        JWTVerifier require = JWT.require(Algorithm.HMAC256(KEY)).build();
        DecodedJWT decodedJWT = require.verify(token);
        Map<String, Claim> claims = decodedJWT.getClaims();
        System.out.println(claims.get("username"));
        System.out.println(claims.get("pwd"));
        System.out.println(claims.get("phone"));
        System.out.println(decodedJWT.getHeader());
        System.out.println(decodedJWT.getExpiresAt());
        System.out.println(decodedJWT.getId());
    }

控制层controller

@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;
    @Autowired
    UserMapper userMapper;
    Logger logger = LoggerFactory.getLogger(UserController.class);

    @RequestMapping("/sendSMS")
    public void send(@RequestParam("phone") String phone, HttpSession session) {
        logger.info("phone------------>" + phone);
        String yzm = SendSMSTools.sendSMS(phone);
        System.out.println("---------->"+yzm);
        session.setAttribute("yzm", yzm);
    }

    @RequestMapping("/login")
    public String login(@RequestParam("phone") String phone,
                        @RequestParam("yzm") String yzm,
                        HttpSession session) {
        logger.info(phone);
        logger.info(yzm);
        String code = session.getAttribute("yzm")+"";
        logger.info("code:"+code);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("phone");
        List<User> users = userMapper.selectList(queryWrapper);
        if (users != null) {
            for (User user : users) {
                if (user.getPhone().equals(phone) ) {
                    logger.info("user.getPhone():"+user.getPhone());
                    Map<String,Object>userMap = new HashMap<>();
                    userMap.put("phone", phone);
                    userMap.put("yzm", yzm);
                    return JwtTools.createToken(userMap);
                }
            }
        }
        return null;
    }
}

登录流程

  1. 提供手机号登录,发送验证码,session,redis
  2. 完成手机号与验证
  3. 颁发令牌
  4. 浏览器发送请求&token
  5. 过滤器,拦截器–拦截每一个请求,验证是否有token,如果有token验证token合法性验证通过跳转首页,验证没有token直接返回登录页面

RBAC&ABAC

用户表,权限表,角色表,用户角色表,角色权限表,菜单表,菜单权限表

RBAC:权限管理模块

–角色管理

–权限管理

  • –菜单管理
  • –按钮,DIV,ABAC

–用户管理

ABAC:属性权限管理模块

权限框架Sa-Token&Ruoyi

Ruoyi

官网:RuoYi

Sa-Toekn

这些是部分内容更详细的内容去官网查看

官网:Sa-Token

SaToken的依赖
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.37.0</version>
</dependency>
yml配置
sa-token: 
    # token 名称(同时也是 cookie 名称)
    token-name: satoken
    # token 有效期(单位:秒) 默认30天,-1 代表永久有效
    timeout: 2592000
    # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
    active-timeout: -1
    # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
    is-concurrent: true
    # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
    is-share: true
    # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
    token-style: uuid
    # 是否输出操作日志 
    is-log: true

使用方式

两中方式都在官网官网写的很详细

API
// 会话登录:参数填写要登录的账号id,建议的数据类型:long | int | String, 不可以传入复杂类型,如:User、Admin 等等
StpUtil.login(Object id);     
// 当前会话注销登录
StpUtil.logout();
// 获取当前会话是否已经登录,返回true=已登录,false=未登录
StpUtil.isLogin();
// 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.checkLogin();
// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.getLoginId();

// 类似查询API还有:
StpUtil.getLoginIdAsString();    // 获取当前会话账号id, 并转化为`String`类型
StpUtil.getLoginIdAsInt();       // 获取当前会话账号id, 并转化为`int`类型
StpUtil.getLoginIdAsLong();      // 获取当前会话账号id, 并转化为`long`类型

// ---------- 指定未登录情形下返回的默认值 ----------
// 获取当前会话账号id, 如果未登录,则返回 null 
StpUtil.getLoginIdDefaultNull();
// 获取当前会话账号id, 如果未登录,则返回默认值 (`defaultValue`可以为任意类型)
StpUtil.getLoginId(T defaultValue);

// 获取当前会话的 token 值
StpUtil.getTokenValue();
// 获取当前`StpLogic`的 token 名称
StpUtil.getTokenName();
// 获取指定 token 对应的账号id,如果未登录,则返回 null
StpUtil.getLoginIdByToken(String tokenValue);
// 获取当前会话剩余有效期(单位:s,返回-1代表永久有效)
StpUtil.getTokenTimeout();
// 获取当前会话的 token 信息参数
StpUtil.getTokenInfo();
注解鉴权

官网更详细:注解鉴权 (sa-token.cc)

**注意:**用注解鉴权之前必须要打开注解式功能**注册 Sa-Token拦截器,打开注解式功能**

package com.jwt.config;

import cn.dev33.satoken.interceptor.SaInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//注册 Sa-Token拦截器,打开注解式功能
@Configuration
public class PowerInterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor())
        .addPathPatterns("/**");
    }
}
  • @SaCheckLogin: 登录校验 —— 只有登录之后才能进入该方法。
  • @SaCheckRole("admin"): 角色校验 —— 必须具有指定角色标识才能进入该方法。
  • @SaCheckPermission("user:add"): 权限校验 —— 必须具有指定权限才能进入该方法。
  • @SaCheckSafe: 二级认证校验 —— 必须二级认证之后才能进入该方法。
  • @SaCheckBasic: HttpBasic校验 —— 只有通过 Basic 认证后才能进入该方法。
  • @SaIgnore:忽略校验 —— 表示被修饰的方法或类无需进行注解鉴权和路由拦截器鉴权。
  • @SaCheckDisable("comment"):账号服务封禁校验 —— 校验当前账号指定服务是否被封禁。
@RequestMapping("/anno")
//    @SaCheckLogin
    @SaCheckPermission("打印")
    public Object annoEx() {

        return SaResult.ok("");
    }
@ExceptionHandler
    public Object handException(Exception e, Model model) {
        e.printStackTrace();//异常堆栈
        model.addAttribute("errMsg","非常抱歉:"+e.getMessage());
        return "/power/500";
    }

登录,注销 测试

注意事项

在sa-token 中验证有两种处理方式

  • 中断式处理-以抛出异常方式处理 checkXXX
  • 非中断式处理- 校验式-返回布尔值 isXXX
视图层
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>login</title>
</head>
<body>
<form action="/power/login" method="post">
   用户名:<input type="text" name="username"><br>
   密码:<input type="text" style="margin-left: 15px;margin-top: 10px" name="password"><br>
   <button type="submit" style="margin-top: 10px">登录</button>
   <a href="/power/checkLogin" style="margin-left: 15px;">查看登录状态</a>
   <a href="/power/logout" style="margin-left: 15px;">退出登录</a>
   <a href="/power/checkPower" style="margin-left: 15px;">查看权限</a>
   <a href="/power/checkEx" style="margin-left: 15px;">全局处理异常</a>
</form>
</body>
</html>
控制层
package com.jwt.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jwt.service.UserService;
import com.jwt.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/power")
public class PowerController {

    @Autowired
    UserService userService;

    @RequestMapping("/login")
    public Object login(@RequestParam("username") String username,
                        @RequestParam("password") String password) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uname", username)
        .eq("upwd", password);
        User user = userService.getOne(queryWrapper);
        if (user != null) {
            StpUtil.login(user.getUid());

            return new SaResult(200, "", user);
        }
        return SaResult.error("登录失败,用户未登录");
    }

    @RequestMapping("/checkLogin")
    public Object checkLogin() {
        //在sa-token 中验证有两种处理方式
        //中断式处理-以抛出异常方式处理   checkXXX
        //StpUtil.checkLogin();
        //非中断式处理- 校验式-返回布尔值 isXXX
        if (StpUtil.isLogin()) {
            return SaResult.ok("用户已登录");
        } else {
            return SaResult.ok("用户未登录");
        }
    }

    @RequestMapping("/logout")
    public Object logout() {
      // StpUtil.logout(); //注销所有账号
       // StpUtil.logout(10001);                    // 强制指定账号注销下线 
       // StpUtil.logout(10001, "PC");              // 强制指定账号指定端注销下线 
       // StpUtil.logoutByTokenValue("token");      // 强制指定 Token 注销下线 
       StpUtil.kickout(10001);                    // 将指定账号踢下线 
       StpUtil.kickout(10001, "PC");              // 将指定账号指定端踢下线
       StpUtil.kickoutByTokenValue("token");      // 将指定 Token 踢下线

        return SaResult.ok("");
    }
}

账号封禁

更多内容在官网

// 封禁指定账号 
StpUtil.disable(10001, 86400); 
// 先踢下线
StpUtil.kickout(10001); 
// 再封禁账号
StpUtil.disable(10001, 86400); 
// 校验指定账号是否已被封禁,如果被封禁则抛出异常 `DisableServiceException`
StpUtil.checkDisable(10001); 
// 通过校验后,再进行登录:
StpUtil.login(10001); 
// 封禁指定账号 
StpUtil.disable(10001, 86400); 
// 获取指定账号是否已被封禁 (true=已被封禁, false=未被封禁) 
StpUtil.isDisable(10001); 
// 校验指定账号是否已被封禁,如果被封禁则抛出异常 `DisableServiceException`
StpUtil.checkDisable(10001); 
// 获取指定账号剩余封禁时间,单位:秒,如果该账号未被封禁,则返回-2 
StpUtil.getDisableTime(10001); 
// 解除封禁
StpUtil.untieDisable(10001); 

sa-token权限角色管控

实现 StpInterface接口
package com.jwt.service.impl;

import cn.dev33.satoken.stp.StpInterface;
import org.springframework.stereotype.Component;

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

@Component
public class RoleAndPowerServiceImpl implements StpInterface {
    @Override
    public List<String> getPermissionList(Object o, String s) {
        //1.查询权限表-权限初始化
        //2.最小化范围
        //3.SQL语句带上用户ID查询权限表(重要)
        List<String>list = new ArrayList<>();
        list.add("添加");
        list.add("删除");
        list.add("修改");
        list.add("查询");
        return list;
    }

    @Override
    public List<String> getRoleList(Object o, String s) {
        List<String>roles = new ArrayList<>();
        roles.add("普通用户");
        roles.add("管理员");
        roles.add("经理");
        roles.add("总监");
        return roles;
    }
}
控制层
@RequestMapping("/checkPower")
    public Object checkPower() {
        //在sa-token 中验证有两种处理方式
        boolean check = StpUtil.hasPermission("添加");//非中断式处理
//        StpUtil.checkPermission("打印");//中断式处理
//        StpUtil.checkRole("经理");
        if (check) {
           return SaResult.ok("此用户有这个权限");
        }else {
            return SaResult.ok("此用户没有这个权限");
        }
//        return "";
    }

全局异常处理

这些注解很重要的

@RestControllerAdvice//返回的是json对象
@ControllerAdvice//跳转页面
@ExceptionHandler

定义处理异常类

(这是程序出口)

package com.jwt.handler;

import cn.dev33.satoken.util.SaResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//@Slf4j
@RestControllerAdvice//返回的是json对象
//@ControllerAdvice//跳转页面
public class PowerExceptionHandler {

    @ExceptionHandler
    public Object handException(Exception e) {
        e.printStackTrace();//异常堆栈
        return SaResult.error("非常抱歉" + e.getMessage());
    }
//    @ExceptionHandler
//    public Object handException(Exception e, Model model) {
//        e.printStackTrace();//异常堆栈
// 		  e.getMessage().contains("502")//是否包含502
//        if (e.getMessage().contains("502")||e.getMessage().contains("501")) {
//            model.addAttribute("errMsg","非常抱歉:"+e.getMessage());
//            return "/power/500";
//        }
//        return "/power/404";
//    }

}

控制层

@RequestMapping("/checkEx")
public void checkEx() throws Exception {
    if (!StpUtil.isLogin()) {
        throw new Exception("502,您还没登录");
    }
    boolean role = StpUtil.hasRole("66");
    if (!role) {
        throw new Exception("501,此用户没有这个角色");
    }
}

页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>404</title>
</head>
<body>
<h1 style="color: #8A2BE2">404,请停步,您没有这个角色权限!!!</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>500</title>
</head>
<body>
<h1 style="color: #00ff00">${errMsg}</h1>
</body>
</html>

json格式处理

在这里插入图片描述

跳转页面格式

在这里插入图片描述

接口文档框架Swagger

导入swagger的依赖

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

配置文件

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

配置类

package com.jwt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
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;

@Configuration  //表明是配置类
@EnableSwagger2 //这个声明此类是接口文档配置类
@EnableSwaggerBootstrapUI //开启BootstrapUI
public class SwaggerConfig {

    @Bean
    public Docket initSwagger() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(this.builderApi())
        .select()   //选择器,选哪些类要生成接口文档
        .apis(RequestHandlerSelectors.basePackage("com.jwt"))//用于指定扫描哪些包下的接口,any是扫描任何
        .paths(PathSelectors.any())//选择所有的API,如果你想只为部分API生成文档,可以配置这里
        .build();
        return docket;
    }

    //初始化API设置
    public ApiInfo builderApi() {
        //设置模式是建造者模式,可以链式调用
        ApiInfo api = new ApiInfoBuilder()
        .description("接口文档描述信息")//描述
        .title("Sa-token的接口文档")//标题
        .version("v1.0")//版本
        .contact(new Contact("milo","https://www.baidu.com","cxyali826@qq.com"))//联系人
        .build();
        return api;
    }

}

ApiInfo对象里面的东西

在这里插入图片描述

访问路径

http://localhost:8086/swagger-ui.html

测试

package com.jwt.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jwt.service.UserService;
import com.jwt.vo.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/power")
@Api(value = "SaToken的鉴权接口", tags = "PowerController的鉴权接口")
public class PowerController {

    @Autowired
    UserService userService;

    @ApiOperation("SaToken登录接口")//生成方法描述
    @ApiImplicitParams({
    @ApiImplicitParam(name = "username", value = "用户名"),//描述具体参数作用
    @ApiImplicitParam(name = "password", value = "密码")
    })//生成参数描述
    @RequestMapping("/login")
    public Object login(@RequestParam("username") String username,
                        @RequestParam("password") String password) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uname", username)
        .eq("upwd", password);
        User user = userService.getOne(queryWrapper);
        if (user != null) {
            StpUtil.login(user.getUid());

            return new SaResult(200, "", user);
        }
        return SaResult.error("登录失败,用户未登录");
    }
}

在这里插入图片描述

在这里插入图片描述

导入BootStrapUI依赖

在这里插入图片描述

**访问路径:**http://localhost:8080/doc.html

@EnableSwaggerBootstrapUI //开启BootstrapUI
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.8.7</version>
</dependency>

SpringBoot过滤器,拦截器和监听器

过滤器

拦截器与过滤器的区别
  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
  • 拦截器内容不同:Filter对所有访问进行增强(在Tomcat服务器进行配置),Interceptor仅针对SpringMVC的访问进行增强
定义一个过滤器
package com.jwt.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//@Component
@WebFilter(filterName = "tokenFilter",urlPatterns = "/*")
public class TokenFilter implements Filter {
    Logger logger = LoggerFactory.getLogger(TokenFilter.class);
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("------------>调用init方法");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        logger.info("------------>调用doFilter方法");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
        logger.info("------------>调用destroy方法");
    }
}
注册过滤器

在启动类上加这个注解完成注册;

//加这个注解后,Servlet,Filter,Listener可以直接通过@WebServlet,@WebFilter,@WebListener注解自动注册
@ServletComponentScan

拦截器

作用:

  • 在指定的方法调用前后执行预先设定的代码(比如权限的校验就是在访问controller之前校验)
  • 阻止原始方法的执行(把原始的方法终止掉)

在这里插入图片描述

定义一个拦截器
package com.jwt.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取进过拦截器的路径
        String requestURI = request.getRequestURI();

        //      登录检查逻辑
        HttpSession session = request.getSession();
        Object token = session.getAttribute("token");
        if (token != null) {
//          放行
            return true;//true 本次拦截,false 不拦截
        }
//      拦截   就是未登录,自动跳转到登录页面,然后写拦截住的逻辑
        return false;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
注册拦截器
package com.jwt.config;

import com.jwt.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class LoginWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

//       下面这句代码相当于添加一个拦截器   添加的拦截器就是我们刚刚创建的
        registry.addInterceptor(new LoginInterceptor())
//       addPathPatterns()配置我们要拦截哪些路径 addPathPatterns("/**")表示拦截所有请求,包括我们的静态资源
        .addPathPatterns()
//       excludePathPatterns()表示我们要放行哪些(表示不用经过拦截器)
//       excludePathPatterns("/","/login")表示放行“/”与“/login”请求
//       如果有静态资源的时候可以在这个地方放行
        .excludePathPatterns("/","/login");
//        第二个拦截器
//        registry.addInterceptor(new LoginInterceptor2()).addPathPatterns("/books");

    }
}
解决跨域问题
  • 在后端重定向解决
  • 失败返回一个状态码,然后在前端判断状态码,然后在前端实现跳转

在这里插入图片描述

监听器

SpringBoot邮件服务

引入依赖

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

配置

spring:
  mail:
    host: smtp.qq.com
    username: 1693311433@qq.com
    password: xxxx
    properties:
      mail:
        smtp:
          ssl:
            enable: true
fromMail: 169xxxxxx@qq.com

发送方法

package com.jwt.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.jwt.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

@Service
public class EmailServiceImpl implements EmailService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    JavaMailSender sender;

    @Value("${fromMail}")
    private String fromMail;

    @Override
    public void send(String qq) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject("验证码");
//        System.out.println(fromMail);
        message.setText(String.valueOf(RandomUtil.randomInt(1000, 9999)));
        message.setTo(qq);
        message.setFrom(fromMail);
        sender.send(message);
        logger.info("邮件已发送!");
    }
}

SpringBoot定时器

定义一个定时器类

package com.jwt.quartz;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling//开启定时功能
public class QuartzTest {

    Logger logger = LoggerFactory.getLogger(QuartzTest.class);
	//cron表达式在网上看
    @Scheduled(cron = "*/5 * *  * * *")//每秒执行一次
    public void test() {
        logger.info("-------------->定时任务");
    }
}

SpringBoot+JPA

引入依赖和配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    url: jdbc:mysql://localhost:3306/springboot
    password: 123456
  jpa:
    show-sql: true

实体类

package com.example.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Data
@Entity
@Table(name = "user")
public class AyUser {

    @Id
    private String id;
    private String username;
    private String password;

}

DAO层

要继承JpaRepository类

package com.example.dao;

import com.example.entity.AyUser;
import org.springframework.data.jpa.repository.JpaRepository;

public interface AyUserRepository extends JpaRepository<AyUser,String> {


}

Serivice层

package com.example.service;

import com.example.entity.AyUser;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface AyUserService {

    AyUser findById(String id);
    List<AyUser>findAll();
    AyUser save(AyUser ayUser);
    void delete(String id);
    //分页
    Page<AyUser>findAll(Pageable pageable);
}
package com.example.service.impl;

import com.example.dao.AyUserRepository;
import com.example.entity.AyUser;
import com.example.service.AyUserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

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

@Service
public class AyUserServiceImpl implements AyUserService {

    @Resource(name = "ayUserRepository")
    private AyUserRepository ayUserRepository;

    @Override
    public AyUser findById(String id) {
        return ayUserRepository.findById(id).get();
    }

    @Override
    public List<AyUser> findAll() {
        return ayUserRepository.findAll();
    }

    @Override
    public AyUser save(AyUser ayUser) {
        return ayUserRepository.save(ayUser);
    }

    @Override
    public void delete(String id) {
        ayUserRepository.deleteById(id);
    }

    @Override
    public Page<AyUser> findAll(Pageable pageable) {
        return ayUserRepository.findAll(pageable);
    }
}

自定义查询方法

在这里插入图片描述

测试


@SpringBootTest
class Springboot03ApplicationTests {

    @Resource
    AyUserService ayUserService;

    @Test
    void test01() {
        List<AyUser> users = ayUserService.findAll();
        System.out.println(users);
        PageRequest pageable = PageRequest.of(0, 1);
        Page<AyUser> all = ayUserService.findAll(pageable);
        all.get().forEach(System.out::println);
    }
}

SpringBoot事务的简单实现

    //@Transactional 也可以加在在类上,这意味着该类或者public方法开启事务
    @Transactional
    @Override
    public AyUser save(AyUser ayUser) {
        AyUser user = ayUserRepository.save(ayUser);
       
        String error = null;
        //出现空指针
        error.split("/");
        return user;

    }

测试

@Test
void test02() {
    AyUser ayUser = new AyUser();
    ayUser.setId("4");
    ayUser.setUsername("ayUser");
    ayUser.setPassword("123");
    ayUserService.save(ayUser);

}

	AyUser save(AyUser ayUser) {
        return ayUserRepository.save(ayUser);
    }

    @Override
    public void delete(String id) {
        ayUserRepository.deleteById(id);
    }

    @Override
    public Page<AyUser> findAll(Pageable pageable) {
        return ayUserRepository.findAll(pageable);
    }
}

自定义查询方法

[外链图片转存中…(img-eZMXKE6P-1706420611915)]

测试


@SpringBootTest
class Springboot03ApplicationTests {

    @Resource
    AyUserService ayUserService;

    @Test
    void test01() {
        List<AyUser> users = ayUserService.findAll();
        System.out.println(users);
        PageRequest pageable = PageRequest.of(0, 1);
        Page<AyUser> all = ayUserService.findAll(pageable);
        all.get().forEach(System.out::println);
    }
}

SpringBoot事务的简单实现

    //@Transactional 也可以加在在类上,这意味着该类或者public方法开启事务
    @Transactional
    @Override
    public AyUser save(AyUser ayUser) {
        AyUser user = ayUserRepository.save(ayUser);
       
        String error = null;
        //出现空指针
        error.split("/");
        return user;

    }

测试

@Test
void test02() {
    AyUser ayUser = new AyUser();
    ayUser.setId("4");
    ayUser.setUsername("ayUser");
    ayUser.setPassword("123");
    ayUserService.save(ayUser);

}
  • 16
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cxy_艾力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值