Spring boot 学习笔记
初始化项目
父工程
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.orangbus</groupId>
<artifactId>yeb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--pom管理-->
<packaging>pom</packaging>
<name>yeb</name>
<description>yeb</description>
<properties>
<java.version>11</java.version>
</properties>
</project>
依赖
<!-- web 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok 依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- mysql 依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- mybatis-plus 依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<!-- mybatis-plus 代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!-- freemarker 模板引擎-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!-- swagger2 依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<!--security 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--jwt 依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--redis 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- mongo-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--网页解析-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.3</version>
</dependency>
配置文件
application.yml
server:
port: 8081
spring:
profiles: # 使用那个环境的配置
active: dev
application-dev.yml
server:
port: 8081
# 开启热部署
spring:
thymeleaf:
cache: false
devtools:
livereload:
enabled: true #是否支持livereload
port: 35729
restart:
enabled: true
# 本地数据库连接
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/laravel_web?useSSL=false&useUnicode=true&characterEncode=UTF-8&serverTimezone=GMT
driver-class-name: com.mysql.cj.jdbc.Driver
logging:
level:
root: info
org.orangbus: debug
#com.baomidou: debug
file:
path: /log/logs.txt
#mybatis-plus 配置
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml
# 配置 数据返回类型的别名
type-aliases-package: com.orangbus.server.pojo
configuration:
# 自动驼峰命名
map-underscore-to-camel-case: false
# mybatis sql 打印 (方法接口所在的包,不是mapper.xml所在的包)
logging:
level:
com.orangbus.server.mappder: debug
application-prod.yml
spring:
thymeleaf:
mode: HTML
profiles: //具体使用那个配置文件
active: dev
逆向工程-生成Empty
官网:https://baomidou.com/guide/install.html#release
代码生成插件:mybatisx | MyBatis Generator | Free MyBatis plugin
插件整合
elasticsearch-7.15
官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.15/index.html
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>
配置文件
package com.example.esdemo.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticSearchConfig {
@Bean(destroyMethod = "close")
public RestHighLevelClient client(){
HttpHost httpHost= new HttpHost("192.168.3.5", 9200, "http");
RestClientBuilder restClientBuilder = RestClient.builder(httpHost);
return new RestHighLevelClient(restClientBuilder);
}
}
使用
package com.example.esdemo.controller;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
public class Index {
@Autowired
private RestHighLevelClient client;
private String indexName="video-test";
@GetMapping("/")
public String index() throws IOException {
Object data = new Video("斗罗大陆","http://orangbus.cn");
IndexRequest request = new IndexRequest(indexName).id("1").source(JSON.toJSONString(data), XContentType.JSON);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
return "elasticsearch";
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
class Video{
private String name;
private String url;
}
}
redis
mongo
rabbitmq
aliyun阿里云maven
打开解压的maven文件夹,找到conf文件夹打开,选择settings.xml文件用编辑器打开,搜索mirrors标签,把下面的内容添加在其子标签中
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
Swagger-ui配置
knife4j
<!--knife4j文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
配置
package com.orangbus.web.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.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableSwagger2
@Configuration
public class Knife4jConfig {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(
new ApiInfoBuilder()
.title("orangbus接口文档")
.description("orangbus接口文档")
.termsOfServiceUrl("http://orangbus.cn")
.contact(new Contact("orangbus", "heep://orangbus.cn", "linuc40400@gmail.com"))
.version("1.0")
.build()
)
// .groupName("1.0版本")
.select()
.apis(RequestHandlerSelectors.basePackage("com.orangbus.web.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
源配置
热加载
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
注解
// 拦截标注为 @Controller 的类
@ControllerAdvi
实体类注解
@Entity
@Table(name='table_name')
@id
// 生成策略
@GeneratedValue
// 时间转化
@Temporal(TemporalType,TIMESTAMP
自定义跳转连接
String user = null;
if (user == null){
throw new NotFondException("用户不能为空!");
}
Aop记录日志
th:replace='app::header(~{::title})'
th:href="@{/css/app.css}"
// 重定向跳转
return "redirect:/admin"
统一数据返回
package com.orangbus.common.common;
import lombok.Data;
@Data
public class ApiResponse<T> {
private Integer status;
private String message;
private T data;
// 默认成功返回
private static final int SUCCESS_CODE=200;
private static final String SUCCESS_MESSAGE="success";
// 默认失败返回
private static final int ERROR_CODE=202;
private static final String ERROR_MESSAGE="error";
/**
* 构造函数
* @param status
* @param message
* @param data
*/
public ApiResponse(Integer status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
/**
* 两参函数
* @param status
* @param message
*/
public ApiResponse(Integer status, String message) {
this.status = status;
this.message = message;
}
public ApiResponse(){
this(SUCCESS_CODE,SUCCESS_MESSAGE);
}
/**
* 成功返回
*/
public static <T> ApiResponse<T> success(){
return new ApiResponse<>();
}
public static <T> ApiResponse<T> success(String message){
ApiResponse<T> response = new ApiResponse<>();
response.setMessage(message);
return response;
}
public static <T> ApiResponse<T> success(String message,Integer code){
ApiResponse<T> response = new ApiResponse<>();
response.setMessage(message);
response.setStatus(code);
return response;
}
public static <T> ApiResponse<T> success(T result){
ApiResponse<T> response = new ApiResponse<>();
response.setData(result);
return response;
}
/**
* 失败返回
*/
public static <T> ApiResponse<T> error(){
ApiResponse<T> response = new ApiResponse<>();
response.setStatus(ERROR_CODE);
response.setMessage(ERROR_MESSAGE);
return response;
}
public static <T> ApiResponse<T> error(String message){
ApiResponse<T> response = new ApiResponse<>();
response.setStatus(ERROR_CODE);
response.setMessage(message);
return response;
}
public static <T> ApiResponse<T> error(String message,Integer code){
ApiResponse<T> response = new ApiResponse<>();
response.setMessage(message);
response.setStatus(code);
return response;
}
}
开发开发流程
controller
调用 service
层 ,service
层定义接口,impl
实现serice接口
去处理实际的业务逻辑,最后实现接口层impl
与实体类Mapper
层(数据库对应的字段)进行交互,对异常进行处理。
Aop:
Filter: 过滤器,相当于php中的中间件,对请求进行拦截,已经记录相关日志
1、controller
注解
@PathVariable
/**
* 获取路径变量
* @param id
* @param name
* @return
*/
@GetMapping("/detail/{name}/{id}")
public ApiResponse path(@PathVariable("id") Integer id, @PathVariable("name") String name, @PathVariable Map<String, String> all){
HashMap<String, Object> map = new HashMap<>();
map.put("id",id);
map.put("name",name);
map.put("all",all);
return ApiResponse.success(map);
}
@RequestHeader
/**
* 请求头相关的处理
* @param header
* @return
*/
@GetMapping("/getHeader")
public ApiResponse header(
@RequestHeader Map<String,String> header,
@RequestHeader("host") String host
){
header.put("req-host",host);
return ApiResponse.success(header);
}
@ModelAttribute
页面跳转携带的参数
@RequestParam
@PostMapping("/index")
public ApiResponse login(
@RequestParam String name,
@RequestParam String password
){
HashMap<String, String> map = new HashMap<>();
map.put("name",name);
map.put("password",password);
return ApiResponse.success(map);
}
@MatrixVariable
@CookieValue
@RequestBody
@ResourceMapper
@RequestMapping("/user")
请求参数处理
@PostMapping("/index")
public ApiResponse login(
@RequestParam String name,
@RequestParam String password
){
HashMap<String, String> map = new HashMap<>();
map.put("name",name);
map.put("password",password);
return ApiResponse.success(map);
}
请求头
2、 service
处理业务逻辑:定义接口 -> 实现接口
3、model
定义表的映射关系
dao(mapper): 数据库查询方法
pojo: 实体类-数据库字段
模板Thymeleaf
1、Thymeleaf母版页示例
- 母版页代码(resources/templates/shared/layout1.html)
<!DOCTYPE html>
<html lang="en">
<head>
<title th:text="${title}"></title>
</head>
<body>
<div layout:fragment="content">
默认内容
</div>
</body>
</html>
母版页定义一个id=content
的片段,以便子页面可以替换该内容
2、Thymeleaf子页面继承示例
- 子页面代码(resources/templates/demo/page1.html)
<div layout:decorator="shared/layout1">
<div layout:fragment="content">
page1子页面内容
</div>
</div>
子页面引入模板layout1.html作为模板,并定义content同名片段覆盖母版页内容
3、 控制器代码示例
@RequestMapping("/page1")
ModelAndView page1(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("title","page1页面标题");
modelAndView.setViewName("demo/page1");
return modelAndView;
}
4、最终的渲染结果
<!DOCTYPE html>
<html>
<head>
<title>page1页面标题</title>
</head>
<body>
<div>
page1子页面内容
</div>
</body>
</html>
Thymeleaf语法/标签说明
语法/标签 | 说明 |
---|---|
layout:fragment | 定义模板片段,可以在子页面用同名片段覆盖 |
layout:decorator | 引用Thymeleaf页面作为母版/模板 |
拦截器
用于用户是否登录判断
配置文件
application.properties
server.port=8081
orangbus.name="orangbus"
===== yaml =====
server:
port: 8081
orangbus:
name: "orangbus"
application.yml
server:
port: 8080
# 开启热部署
spring:
profiles: # 使用哪个配置文件 dev|prod
active: prod
server:
port: 8080
# 开启热部署
spring:
thymeleaf:
cache: false
devtools:
livereload:
enabled: true #是否支持livereload
port: 35729
restart:
enabled: true
# 本地数据库连接
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/java_video?useSSL=false&useUnicode=true&characterEncode=UTF-8&serverTimezone=GMT
driver-class-name: com.mysql.cj.jdbc.Driver
logging:
level:
root: info
org.orangbus.video: debug
#com.baomidou: debug
file:
path: /log/logs.txt
获取变量
@Value("${orangbus.name}")
String name;
config对象
package com.orangbus.video.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "orangbus") //前缀
public class Mysql {
String database;
String table;
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
}
使用
@Autowired
Mysql mysql;
mysql.database;
文件上传
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet">
<title>文件上传</title>
</head>
<body>
<div class="container">
<div class="row mt-5">
<div class="col-md-6 offset-md-3">
<div class="alert alert-success" role="alert" th:if="${msg}" th:text="${msg}">
<strong>success</strong>
</div>
<form action="/upload" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="">文件上传</label>
<input type="file" class="form-control-file" name="img" id="">
</div>
<div class="form-group mt-3">
<label for="">多文件上传</label>
<input type="file" class="form-control-file" name="photos" multiple >
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block mt-2">上传</button>
</div>
</form>
</div>
</div>
</div>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap-utilities.rtl.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</body>
</html>
package com.orangbus.web.controller;
import com.orangbus.common.common.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.io.File;
import java.io.IOException;
@Controller
@Slf4j
public class UploadFile {
@GetMapping("/form")
public String form() {
return "upload/index";
}
@PostMapping("/upload")
public String upload(
@RequestPart("img") MultipartFile img,
@RequestPart("photos") MultipartFile[] photos,
RedirectAttributes redirectAttributes
) throws IOException {
log.info("img:{}", img.getOriginalFilename());
log.info("photos:{}", photos.length);
// 单文件上传
if (!img.isEmpty()) {
// 保存到服务器
img.transferTo(new File("D:\\logs\\" + img.getOriginalFilename()));
}
// 多文件上传
if (photos.length > 0) {
for (MultipartFile photo : photos) {
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("D:\\logs\\" + originalFilename));
}
}
redirectAttributes.addFlashAttribute("msg", "文件上传成");
return "redirect:/form";
}
}
异常处理
自定义相应模板错误页面
自定义相应 json 错误信息
数据库访问
druid数据源
// 过时了
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
//最新
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
配置
spring:
druid:
filters: stat,wall
access-to-underlying-connection-allowed: true
aop-patterns: true # 监控配置
stat-view-servlet: # 开启监控页面
enabled: true
login-username: admin
login-password: admin
reset-enable: false
web-stat-filter:
enabled: true
url-pattern: /* # 监控地址
exclusions: '' # 排除地址
redis
线程池
创建
停止线程
shutdown: 不会新增新的任务
isShutdown:是否终止了线程
isTerminated: 所有的线程都直行完毕
工作队列类型
- 直接交接:SynchronousQueue
- 无界队列:LinkedBlockingQueue
- 有界队列:ArrayBlockingQueue
分布式:分散能力
单一功能
集群:分担压力
统一业务,不同机器
cap定理
Consistency : 一致性:读操作是否能读到前一个写的操作结果
Availability : 可用性 ,非故障节点应该在合理的时间范围内作出响应
Partition tolerance: 分区容存,当出现网络分区现象后,系统能都继续运行(网络通信错误)
RabbitMq
协议:AMQP协议
步骤
1、安装rabbitmq,并且成功运行
2、添加依赖,配置连接信息
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3、发送消息,接受消息
安装
配置
spring:
rabbitmq:
host: 162.14.72.65
port: 5672
username: guest
password: guest
virtual-host: /
# 支持发布确认
publisher-confirms: true
# 支持发布返回
publisher-returns: true
listener:
simple:
# 采用手动应答
acknowledge-mode: manual
# 当前监听容器数
concurrency: 1
# 最大数
max-concurrency: 1
# 是否支持重试
retry:
enabled: true
# mvc
交换机
fanout
广播:只需要将队列绑定到交换机上即可,是不需要设置路由键的
direct
根据RoutingKey
匹配消息路由到指定的队列
topic
生产者指定RoutingKey
消息根据消费端指定的队列通过模糊匹配的方式进行相应转发
*
替代一个单词#
替代0或多个单词
headers
根据发送消息内容中的headers属性来匹配
微服务
是一种架构风格
springcloud: 众多子项目
dubbo :https://dubbo.apache.org/zh/docs/quick-start/
差分建议(不适合差分)
小团队,技术薄弱
流量小,压力小,业务变化不大
延迟敏感
Lambda表达式
部署到服务器
nohub java-jar -Dserver.port=80 -Dspring.profiles.active=prod /path/to/project.jar > /tmp/null 2>&
错误汇总
SpringBoot集成swagger后出现: Failed to start bean ‘documentationPluginsBootstrapper‘的解决方法
解决办法:在启动类加一个注解:@EnableWebMvc
版本冲突
当使用httpclient
和 elasticsearch
的时候,他们两个的版本需要保持一致
elasticsearch的版本需要和安装的es的版本保持一致
package com.orangbus.volunteer.config.security;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.orangbus.volunteer.empty.Users;
import com.orangbus.volunteer.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.annotation.Resource;
//@Configuration
//@EnableGlobalMethodSecurity(proxyTargetClass = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AuthenticationFailedHandler authenticationFailedHandler;
@Resource
private UsersService usersService;
/**
* 放行静态资源
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/css/**",
"/image/**",
"/js/**",
"/lib/**"
);
}
/**
* 配置登录地址
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.headers().frameOptions().disable()
.and()
.formLogin()
.usernameParameter("name")
.passwordParameter("password")
.loginPage("/")
.loginProcessingUrl("/login")
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailedHandler)
.and()
.authorizeRequests().antMatchers(
"/","login"
).permitAll()
.anyRequest().authenticated();
}
/**
* 自定义登录方法
* @return
*/
// @Bean
// public UserDetailsService userDetailsService(){
// return new UserDetailsService() {
// @Override
// public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// // 通过用户查询用户
// QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("phone",username);
//// UserDetails userDetails = usersService.getBaseMapper().selectOne(queryWrapper);
//// return userDetails;
// return null;
// }
// };
// }
/**
* 密码加密
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* 告诉框架使用哪个 userDetailsService (上面自定义)
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
}