導(dǎo)航
[React 從零實(shí)踐01-后臺(tái)] 代碼分割
[React 從零實(shí)踐02-后臺(tái)] 權(quán)限控制
[React 從零實(shí)踐03-后臺(tái)] 自定義hooks
[React 從零實(shí)踐04-后臺(tái)] docker-compose 部署react+egg+nginx+mysql
[React 從零實(shí)踐05-后臺(tái)] Gitlab-CI使用Docker自動(dòng)化部署
[源碼-webpack01-前置知識(shí)] AST抽象語(yǔ)法樹(shù)
[源碼-webpack02-前置知識(shí)] Tapable
[源碼-webpack03] 手寫(xiě)webpack - compiler簡(jiǎn)單編譯流程
[源碼] Redux React-Redux01
[源碼] axios
[源碼] vuex
[源碼-vue01] data響應(yīng)式 和 初始化渲染
[源碼-vue02] computed 響應(yīng)式 - 初始化,訪問(wèn),更新過(guò)程
[源碼-vue03] watch 偵聽(tīng)屬性 - 初始化和更新
[源碼-vue04] Vue.set 和 vm.$set
[源碼-vue05] Vue.extend
[源碼-vue06] Vue.nextTick 和 vm.$nextTick
[部署01] Nginx
[部署02] Docker 部署vue項(xiàng)目
[部署03] gitlab-CI
[數(shù)據(jù)結(jié)構(gòu)和算法01] 二分查找和排序
[深入01] 執(zhí)行上下文
[深入02] 原型鏈
[深入03] 繼承
[深入04] 事件循環(huán)
[深入05] 柯里化 偏函數(shù) 函數(shù)記憶
[深入06] 隱式轉(zhuǎn)換 和 運(yùn)算符
[深入07] 瀏覽器緩存機(jī)制(http緩存機(jī)制)
[深入08] 前端安全
[深入09] 深淺拷貝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模塊化
[深入13] 觀察者模式 發(fā)布訂閱模式 雙向數(shù)據(jù)綁定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手寫(xiě)Promise
[深入20] 手寫(xiě)函數(shù)
[深入21] 數(shù)據(jù)結(jié)構(gòu)和算法 - 二分查找和排序
[深入22] js和v8垃圾回收機(jī)制
[深入23] JS設(shè)計(jì)模式 - 代理,策略,單例
[前端學(xué)java01-SpringBoot實(shí)戰(zhàn)] 環(huán)境配置和HelloWorld服務(wù)
[前端學(xué)java02-SpringBoot實(shí)戰(zhàn)] mybatis + mysql 實(shí)現(xiàn)歌曲增刪改查
[前端學(xué)java03-SpringBoot實(shí)戰(zhàn)] lombok,日志,部署
[前端學(xué)java04-SpringBoot實(shí)戰(zhàn)] 靜態(tài)資源 + 攔截器 + 前后端文件上傳
[前端學(xué)java05-SpringBoot實(shí)戰(zhàn)] 常用注解 + redis實(shí)現(xiàn)統(tǒng)計(jì)功能
(一) 前置知識(shí)
(1) 一些單詞
security 安全 保護(hù)
core 核心
archetype 原型 // create from archetype 從原型創(chuàng)建
conditional 條件的
final 最終 決賽 // 在java中是常量的關(guān)鍵字
framework 框架 架構(gòu) // spring framework => spring框架
external 外部的 // external libraries 擴(kuò)展類(lèi)庫(kù)
(2) SpringBoot的默認(rèn)錯(cuò)誤解析
- 在
src/main/resources/templates/error/4xx.html或5xx.html會(huì)被自動(dòng)解析- 1.可以在
resources/templates文件下 - 2.也可以在靜態(tài)資源文件夾下
resources/static|public|resources|META-INF.resources 等
- 1.可以在
-
當(dāng)訪問(wèn)不存在的頁(yè)面時(shí),會(huì)返回templates/error/4xx|5xx頁(yè)面
image
(3) java基本數(shù)據(jù)類(lèi)型
- java提供了8中基本類(lèi)型
四個(gè)整數(shù)型兩個(gè)浮點(diǎn)型字符型布爾型 -
四個(gè)整數(shù)型
-
byte8位 -
short16位 -
int32位 => 4個(gè)Byte -
long64位 => 8個(gè)Byte
-
-
兩個(gè)浮點(diǎn)型
floatdouble
-
字符型
char
-
布爾型
boolean
- 屬性:
SIZETYPEMIN_VALUEMAX_VALUE
(4) java的引用類(lèi)型
- 所有引用類(lèi)型的默認(rèn)值都是 null
- 一個(gè)引用變量可以用來(lái)引用任何與之兼容的類(lèi)型
(5) 常量 final
- 常量通常大寫(xiě)
final double PI = 3.1415927;
(6) 自動(dòng)類(lèi)型轉(zhuǎn)換
int i = 128;
byte b = (byte)i;
(7) List 和 ArrayList 的區(qū)別
List<SomeObject> myList = new ArrayList<SomeObject>();
ArrayList<SomeObject> myList = new ArrayList<SomeObject>();
區(qū)別:
(1) List是一個(gè)接口,它沒(méi)有實(shí)現(xiàn)任何屬性和方法,在List上如果調(diào)用方法,實(shí)際上是調(diào)用的 ArrayList 的方法
(2) List是一個(gè)接口,需要使用實(shí)現(xiàn)類(lèi),比如ArrayList
(3) 使用方式不同:Array數(shù)組使用下標(biāo)獲取元素,List是get
(4) 初始化:Array數(shù)組必須指定大小,不靈活。List 可以自己擴(kuò)充大小,方便
(8) IOC AOP
-
IOC
控制反轉(zhuǎn)/依賴注入=> Bean對(duì)象的實(shí)例化 Bean對(duì)象的創(chuàng)建 -
AOP
面向切面編程=> 動(dòng)態(tài)代理 -
Spring JDBC + 事務(wù)
image
image
(二) SpringBoot常用注解
(1) @RestController
@RestController = @Controller + @ResponseBody- 特點(diǎn)
- 添加該注解后,Controller類(lèi)中的方法
無(wú)法返回頁(yè)面, - 相當(dāng)于在方法上自動(dòng)加了
@ResponseBody注解,所以沒(méi)辦法跳轉(zhuǎn)并傳入數(shù)據(jù)到另一個(gè)頁(yè)面 - 返會(huì)的內(nèi)容就是
return的內(nèi)容
- 添加該注解后,Controller類(lèi)中的方法
(2) @GetMapping @PostMapping @PutMappiing @DeleteMapping
(3) @PathVariable @CookieValue @RequestHeader @ReqeustAttribute @RequestParam @RequestBody @MatrixVariable
- @PathVariable 在 RESTful 風(fēng)格下url中獲取路徑變量
// 測(cè)試 request
// 測(cè)試 @PathVariable
// 測(cè)試 @CookieValue
// 測(cè)試 @RequestHeader => 對(duì)比 @RequestParam @RequestBody @RequestPart
// 測(cè)試 @RequestAttribute
// 測(cè)試 @RequestParam
// 測(cè)試 @RequestBody
// 測(cè)試URL:http://localhost:7777/car/1/owner/woow_wu7?age=20&city=chongqing
@GetMapping("/car/{id}/owner/{username}")
public Void getPath(
HttpServletRequest request,
@PathVariable("id") int id,
@PathVariable("username") String username,
@PathVariable Map<String, String> pathVariable,
// @CookieValue("name") String name,
@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String, String> headers,
@RequestParam("age") int age,
@RequestParam Map<String, String> params
// @RequestBody String body
// @RequestAttribute("message") String message
) {
log.info("@PathVariable('id') => id:{}, username: {}", id, username);
log.info("@PathVariable Map<String, String> => 可以用一個(gè)map對(duì)象,接收所有的path變量 => pv: {}", pathVariable);
String tempId = pathVariable.get("id"); // Map實(shí)例有 ( map.get ) ( map.put ) 等方法
System.out.println(tempId);
log.info("@RequestHeader('User-Agent') => User-Agent: {}", userAgent);
log.info("@RequestHeader Map<String, String> => headers: {}", headers);
log.info("@RequestParam Map<String, String> => params: {}", params);
// log.info("@CookieValue('name') => name: {}", name);
// log.info("@RequestBody String body => 可以獲取post請(qǐng)求的body,也可以是一個(gè)Map實(shí)例,比如 @RequestBody Map<String, Object> body ====> body{}", body);
request.setAttribute("message", "success");
log.info("request: {}", request.getAttribute("message"));
return null;
}
(4) @Configuration配置類(lèi)的注解 + @Bean向容器中注冊(cè)組件
-
@Configuration => 可以理解為xml中的 beans 標(biāo)簽
- 作用:是告訴springboot標(biāo)注的類(lèi)是一個(gè)
配置類(lèi) - 注意點(diǎn):@Configuration 標(biāo)注的
配置類(lèi)本身也是組件 - 參數(shù):
@Configuration(proxyBeanMethods = true)
- 作用:是告訴springboot標(biāo)注的類(lèi)是一個(gè)
-
@Bean => 可以理解為xml中的 bean 標(biāo)簽
- 作用:
向容器中添加組件,并且添加的組件是 ( 單實(shí)例 ) - 組件ID:是
方法名 - 返回類(lèi)型:就是
組件的類(lèi)型 - 返回值:就是
組件在容器中的實(shí)例 @Bean(組件名) => @Bean()的參數(shù)可以重命名組件名,而不是用方法名
- 作用:
(1)
/src/main/java/com.example.demo/config/PetConfig.java
-------
// 1. 對(duì)比參考 UserConfig 類(lèi)
// 2. @Configuration 標(biāo)注的類(lèi)是配置類(lèi),配置類(lèi)本身也是組件
// 3. 外界無(wú)論對(duì)配置類(lèi)中的這個(gè)注冊(cè)方法調(diào)用多少次獲取的都是之前容器中的單實(shí)例,前提是 @Configuration(proxyBeanMethods = true
// 4. 如果 @Configuration(proxyBeanMethods = false) 外界調(diào)用拿到的就不是 ( 代理對(duì)象 ),就 ( 不是單實(shí)例 ) 的了
@Configuration // 配置類(lèi) => 相當(dāng)于以前的xml配置文件,xml中有 beans bean 標(biāo)簽
public class PetConfig {
@Bean // 向容器中注冊(cè)組件 => @Bean(pet02)這樣寫(xiě)可以把注冊(cè)到容器中的組件重新命名為pet02,而不是用方法名pet01
public PetBean pet01() {
return new PetBean("dog", "white");
}
}
(2)
問(wèn)題:如何驗(yàn)證組件已經(jīng)注冊(cè)到容器中呢?
回答:在主類(lèi)中可以查看,因?yàn)橹黝?lèi)中通過(guò) IOC 可以通過(guò) run.getBeanDefinitionNames() 獲取到組件名數(shù)組
問(wèn)題:如果獲取到容器中的組件呢?
回答:run.getBean 來(lái)獲取
具體代碼:
// 主程序類(lèi),主配置類(lèi)
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// 1. 返回 IOC 容器
// 2. IOC的作用是:控制反轉(zhuǎn) 和 依賴注入
ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
// 3. 查看容器里的組件
String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println(name);
}
// 3. 從容器中獲取組件 userX
UserBean userX1 = run.getBean("userX", UserBean.class);
UserBean userX2 = run.getBean("userX", UserBean.class);
System.out.println("組件:" + (userX1 == userX2));
System.out.println("上面是true,因?yàn)樽?cè)的組件默認(rèn)就是單實(shí)例的,因?yàn)锧Bean給容器注冊(cè)的組件是單實(shí)例的");
// 3. 從容器中獲取組件 pet01
PetBean pet01 = run.getBean("pet01", PetBean.class);
System.out.println(pet01.getName()); // 獲取pet01對(duì)象中的name屬性
}
}
(5) @ConditionalOnBean 條件裝配注解
- @ConditionalOnBean(name) 表示IOC容器中存在 ( name組件 ) 時(shí),才向容器中添加 ( @ConditionalOnBean ) 組件,不存在name就不添加
- @ConditionalOnBean(name) 如果標(biāo)注在類(lèi)上,則表示類(lèi)里面所有@Bean生效的前提是:容器中有name組件
- 一般都場(chǎng)景啟動(dòng)器中就有非常多的各種條件注解,條件判斷
- 在IOC中
- 1.優(yōu)先解析
@Component,@Service,@Controller,@Mapper等注解類(lèi) - 2.再解析配置類(lèi),即
@Configuration標(biāo)注的類(lèi) - 3.最后解析配置類(lèi)中定義的
@Bean
- 1.優(yōu)先解析
@Configuration
// @ConditionalOnBean(name = "com.example.demo.bean.ImportBean") 如果標(biāo)注在類(lèi)上,則表示里面所有@Bean生效的前提是容器中有com.example.demo.bean.ImportBean組件
public class TestConditionalOnBeanConfig {
// @ConditionalOnBean(name) 表示IOC容器中存在 ( name組件 ) 時(shí),才向容器中添加 ( @ConditionalOnBean ) 組件,不存在name就不添加
// @ConditionalOnBean(name) 如果標(biāo)注在類(lèi)上,則表示類(lèi)里面所有@Bean生效的前提是:容器中有name組件
// - 在IOC中
// - 1.優(yōu)先解析 `@Component,@Service,@Controller,@Mapper`等注解類(lèi)
// - 2.再解析配置類(lèi),即`@Configuration`標(biāo)注的類(lèi)
// - 3.最后解析配置類(lèi)中定義的 `@Bean`
@ConditionalOnBean(name = "com.example.demo.bean.ImportBean")
@Bean("@ConditionalOnBean")
public TestConditionalOnBeanBean registerConditionalOnBean() {
return new TestConditionalOnBeanBean("@ConditionalOnBean");
}
}
(5) @Import 向容器中添加組件
- @Import 和 @Bean 的作用類(lèi)似,都是向容器中添加組
- 語(yǔ)法:
@Import({ 類(lèi)名.class, 類(lèi)名.class... }) - 組件名:@Import導(dǎo)入容器中的組件名默認(rèn)是 (
全類(lèi)名) - 注意點(diǎn):
- @Import()必須用在組件類(lèi)上,組件肯定是在springboot IOC容器中的
- @Import() 比如用在@Config @Controller @Service 等組件上都可以
- @Import()可以導(dǎo)入第三方包
src/main/java/com.example.demo/config/PetConfig.java
-------
// @Import
// 1. @Import 和 @Bean 的作用類(lèi)似,都是向容器中添加組
// 2. @Import導(dǎo)入容器中的組件名默認(rèn)是 ( `全類(lèi)名` )
@Import({UserBean.class, PetBean.class})
@Configuration(proxyBeanMethods = true) // 配置類(lèi) => 相當(dāng)于以前的xml配置文件,xml中有 beans bean 標(biāo)簽
public class PetConfig {
@Bean // 向容器中注冊(cè)組件 => @Bean(pet02)這樣寫(xiě)可以把注冊(cè)到容器中的組件重新命名為pet02,而不是用方法名pet01
public PetBean pet01() {
return new PetBean("dog", "white");
}
}
// 以上打印的話
// @Import向容器添加的組件名是:com.example.demo.bean.PetBean
// @Bean向容器添加的組件名是:pet01
(6) @ImportResource 把傳統(tǒng)的xml文件配置的組件添加到容器中
-
@ImportResource("classpath:beans/beans.xml")- 參數(shù):
classpath:beans/beans.xml表示的是配置組件beans.xml的文件路徑 - 具體:
beans.xml被放在了src/main/resources/beans/beans.xml中
- 參數(shù):
(1)
src/main/java/com.example.demo/config/PetConig.java
-------
// @ImportResource
// 1. @ImportResource("classpath:beans/beans.xml")
// 2. 參數(shù):`classpath:beans/beans.xml` 表示的是 `配置組件beans.xml的文件路徑`
// 3. 具體:`beans.xml` 被放在了 `src/main/resources/beans/beans.xml` 中
@Import({UserBean.class, PetBean.class})
@Configuration(proxyBeanMethods = true) // 配置類(lèi) => 相當(dāng)于以前的xml配置文件,xml中有 beans bean 標(biāo)簽
@ImportResource("classpath:beans/beans.xml")
public class PetConfig {
@Bean // 向容器中注冊(cè)組件 => @Bean(pet02)這樣寫(xiě)可以把注冊(cè)到容器中的組件重新命名為pet02,而不是用方法名pet01
public PetBean pet01() {
return new PetBean("dog", "white");
}
}
(2)
src/main/resources/beans/beans.xml
-------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--UserBean-->
<bean id="haha" class="com.example.demo.bean.UserBean">
<property name="name" value="zhangsan"></property>
<property name="age" value="20"></property>
</bean>
<!--PetBean-->
<bean id="hehe" class="com.example.demo.bean.PetBean">
<property name="name" value="dog"></property>
<property name="color" value="red"></property>
</bean>
</beans>
(7) @ConfigurationProperties + @Component 實(shí)現(xiàn)配置綁定
@ConfigurationProperties(prefix = "myapp")-
@Compoennt:的作用是將類(lèi)組件添加到容器中
(1)
src/main/java/com.example.demo/bean/AppMessageBean.java
-------
// 1. 只有在容器中的組件才能獲取 SpringBoot 的強(qiáng)大功能,也就是說(shuō)要使用@ConfigurationProperties()必須用@Component將對(duì)象標(biāo)記成容器組件
// 2. 該 bean 對(duì)象主要是測(cè)試 @ConfigurationProperties 和 @Component 兩個(gè)注解
// 3. 如果類(lèi)中的屬性多于application.yml文件中的myapp的話,多的屬性返回的是null
@Data
@Component
@ConfigurationProperties(prefix = "myapp") // prefix="myapp" 這個(gè)前綴的值是在 application.yml 文件中配置的
public class AppMessageBean {
private String name;
private String email;
private String author;
private String other;
}
(2)
src/main/resources/application.yml
-------
myapp:
# 自定義的配置參數(shù),這里主要用來(lái)驗(yàn)證 @ConfigurationProperties 注解的使用
author: woow_wu7
name: react-admin-java
email: woow.wu7@gmail.com
(3)
src/main/java/com.example.demo/controller/TestController.java
-------
@Autowired
AppMessageBean appMessageBean;
// (1)
// 測(cè)試: @ConfigurationProperties 和 @Component 兩個(gè)注解
// 教程: https://www.cnblogs.com/jimoer/p/11374229.html
@GetMapping("/@ConfigurationProperties")
public AppMessageBean getAuthorName() {
System.out.println(appMessageBean);
String author = appMessageBean.getAuthor();
System.out.println(author);
return appMessageBean;
}
(8) @SpringBootTest + @Test 單元測(cè)試
- 1.引入maven場(chǎng)景啟動(dòng)器
spring-boot-starter-test
<!-- spring-boot-starter-test -->
<!-- 單元測(cè)試場(chǎng)景啟動(dòng)器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 2.編譯一個(gè)測(cè)試類(lèi)
src/test/java/com.example.demo/ApplicationTests.java
-------
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() { dosomething...}
}
(三) 修改maven依賴包的版本號(hào)的兩種方法
以mysql為例
(1) 在 pom.xml 中通過(guò) version 標(biāo)簽來(lái)指定 ( 原理是maven的就近依賴原則 )
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
<scope>runtime</scope>
</dependency>
(2) 在 pom.xml 中通過(guò) properties 標(biāo)簽來(lái)修改 ( 原理是maven屬性的就近優(yōu)先原則 )
<properties>
<java.version>1.8</java.version>
<!-- 除了修改version還可以在properties中來(lái)修改依賴的版本號(hào) -->
<!-- <mysql.version>8.0.21</mysql.version> -->
</properties>
(四) 數(shù)據(jù)訪問(wèn)
(1) mysql驅(qū)動(dòng) + JDBC數(shù)據(jù)庫(kù)連接池 = springboot最基礎(chǔ)的操作mysql的方式
在這基礎(chǔ)上還可以添加 mybatis 來(lái)操作數(shù)據(jù)庫(kù)- 1.安裝:mysql驅(qū)動(dòng) => mysql-connector-java
- 2.安裝:jdbc數(shù)據(jù)庫(kù)連接池 => spring-boot-starter-data-jdbc
( 區(qū)分:spring-boot-starter-jdbc ) - 3.配置項(xiàng):spring.datasource...
- 4.數(shù)據(jù)源:
HikariDataSource
spring:
datasource:
# 1. 只要裝了 ( mysql驅(qū)動(dòng) ) 和 ( jdbc數(shù)據(jù)庫(kù)連接池 ),并且在這里配置好 ( 數(shù)據(jù)庫(kù)連接池相關(guān)的配置項(xiàng) ) 就能連接數(shù)據(jù)庫(kù)
# 2. mysql驅(qū)動(dòng) => mysql-connector-java
# 3. jdbc連接池 => spring-boot-starter-jdbc
# 4. 更進(jìn)一步:還可以使用 ( Druid數(shù)據(jù)源 + MyBatis )
url: jdbc:mysql://localhost:3306/7-react-admin-java?serverTimezone=GMT%2B8&useSSL=false
username: root
password: root
dirver-class-name: com.mysql.cj.jdbc.Driver
jdbc:
template:
query-timeout: 10 # 10s沒(méi)查出來(lái)就超時(shí)
- 4.通過(guò)springBoot容器中的 JdbcTemplate 就行操作數(shù)據(jù)庫(kù) ( 單元測(cè)試 )
src/test/com.example.demo/ApplicationTests.java
-------
@SpringBootTest
@Slf4j
class ApplicationTests {
@Autowired
JdbcTemplate jdbcTemplate; // 自動(dòng)注入容器中的 JdbcTemplate
@Test
void contextLoads() {
Long aLong = jdbcTemplate.queryForObject("select count(*) from music", Long.class); // 操作數(shù)據(jù)庫(kù)
log.info("music總數(shù)據(jù)量:{}", aLong);
}
}
(2) HikariDataSource 和 Druid數(shù)據(jù)源 => 濾過(guò)Druid數(shù)據(jù)源
(五) Redis
Redis是一個(gè)開(kāi)源的,( 內(nèi)存中 ) 的 ( 數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng) ),它可以用作 ( 數(shù)據(jù)庫(kù) ) ( 緩存 ) ( 消息中間件 )
(1) 導(dǎo)入maven的依賴包,即redis的場(chǎng)景啟動(dòng)器
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2) 查看springboot的autoconfigure中的redis的 ( 自動(dòng)配置類(lèi) )
- 目錄:
External Libraries/spring-boot-autoconfigure:2.4.2/data/redis/RedisAutoConfiguration.java - external 外部的意思
- external libraries 擴(kuò)展類(lèi)庫(kù)的意思
-
RedisAutoConfiguration.java (1)
- redis自動(dòng)配置:
- @EnableConfigurationProperties(RedisProperties.class) (2)
- spring.redis.xxx (3)
RedisAutoConfiguration.java => @EnableConfigurationProperties(RedisProperties.class) => spring.redis.xxx是對(duì)redis的配置,也就是說(shuō)可以在application.yml中去做redis相關(guān)的配置,比如 spring.redis.xxx
- 連接工廠是準(zhǔn)備好的 ( 兩種 )
- Lettuce => LettuceConnectionConfiguration
- Jedis => JedisConnectionConfiguration
- 操作redis
- 自動(dòng)注入了下面兩個(gè)組件類(lèi)
-
RedisTemplate<Object, Object>
- key: value
- 對(duì)比 JdbcTemplate
-
StringRedisTemplate
- key 和 value 都是 String
- redis自動(dòng)配置:
(3) 申請(qǐng)一個(gè)阿里云的 redis 服務(wù)器,并申請(qǐng)redis公網(wǎng)連接地址,和設(shè)置白名單,用戶權(quán)限(讀寫(xiě))等
(4) 下載安裝 redis 和 redis客戶端
- 下載連接
- redis下載安裝教程
- windows系統(tǒng)redis客戶端下載連接
- redis常用命令
-
redis的使用
- 1.在windows系統(tǒng)上安裝完成后,在解壓的目錄下雙擊
redis-cli.exe運(yùn)行 - 2.除了雙擊運(yùn)行,也可以在該文件夾下打開(kāi)cmd,輸入
./redis-cli.exe命令
- 1.在windows系統(tǒng)上安裝完成后,在解壓的目錄下雙擊
-
redis常用命令
-
獲取讀寫(xiě)權(quán)限
auth username:passwordauth password
-
是否禁用redis
config set disable [yes|no]
-
查詢默認(rèn)密碼 ( 登陸后才可以操作 )
- config get requirepass
-
修改密碼 ( 登陸后才可以操作 )
- config set requirepass 123456
-
登陸redis
- ./redis-cli -p 6379 -a 123456
-
啟動(dòng)服務(wù)
- ./redis-server --service-start
-
停止服務(wù)
- ./redis-server --service-stop
-
string
-
set key value設(shè)置鍵值 -
get key獲取鍵值 -
del key刪除鍵值 -
mget key1key2 同時(shí)獲取 -
exists key檢查key是否存在
-
-
list => 是鏈表
-
lpush key value1 value2在key所關(guān)聯(lián)的list的頭部 ( 插入 ) 所有value值 -
rpush key value1 value2在key所關(guān)聯(lián)的list的頭部 ( 插入 ) 所有value值 -
lrange key start end獲取key鏈表中從start到end的元素的值,start、end可 為負(fù)數(shù),若為-1則表示鏈表尾部的元素 -
lpushx key value當(dāng)key存在時(shí)才leftpush,如果不加x不存在時(shí)會(huì)新建 -
lpop key返回并彈出指定的key關(guān)聯(lián)的鏈表中的第一個(gè)元素,即頭部元素
-
-
set => 是數(shù)組加鏈表
-
sadd key value1 value2向set中添加數(shù)據(jù),如果該key的值已有則不會(huì) 重復(fù)添加 l` -
smembers key獲取set中所有的成員 -
scard key獲取set中成員的數(shù)量 -
srem key member1、member2刪除set中指定的成員
-
-
zset
- zset中的每一個(gè)成員都會(huì)有一個(gè)分 數(shù)(score)與之關(guān)聯(lián),Redis正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序
-
zadd key score member score2 member2將所有成員以及該成員的 分?jǐn)?shù)存放到sorted-set中
-
hash
- Redis中的Hashes類(lèi)型可以看成具有String Key和String Value的map容器,所以適合存儲(chǔ)值是對(duì)象的信息,比如 username
-
hset key fild value為指定的key設(shè)定field/value對(duì)(鍵值對(duì)) -
hgetall key獲取key中的所有filed-vaule
image
-
獲取讀寫(xiě)權(quán)限
(5) 在application.properties 或 applicatioin.yml中配置 redis
spring:
redis:
# 可以通過(guò) (external libraries)/spring-boot-autoconfigure:2.4.2/data/redis/RedisAutoConfiguration/RedisProperties/url 來(lái)查看
# url = redis://user:password@example.com:6379
host: r-bp1z4zrytbuyv7mkuzpd.redis.rds.aliyuncs.com
port: 6379
password: woow_wu7:ALy123456789
(6) 在springboot的測(cè)試類(lèi)中測(cè)試 讀寫(xiě)redis
src/test/java/com.example.demo/ApplicationTests.java
-------
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate redisTemplate;
@Test
void testRedis() {
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
stringStringValueOperations.set("redis", "ok"); // string set
String redis = stringStringValueOperations.get("redis"); // string get
log.info("redis: {}", redis);
}
(7) 從 Lettuce 切換到 Jedis
- springboot中默認(rèn)使用的是 Lettuce,如何切換成 Jedis
(1) 導(dǎo)入依賴
<!-- jedis -->
<!-- SpringBoot默認(rèn)使用的是Lettuce,要切換成jedis就必須安裝該依賴 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
(2) 修改配置
redis:
# 可以通過(guò) (external libraries)/spring-boot-autoconfigure:2.4.2/data/redis/RedisAutoConfiguration/RedisProperties/url 來(lái)查看
# url = redis://user:password@example.com:6379
host: r-bp1z4zrytbuyv7mkuzpd.redis.rds.aliyuncs.com
port: 6379
password: woow_wu7:ALy123456789
client-type: jedis #兩種,默認(rèn)是 Lettuce
(3) 測(cè)試
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Test
void testRedis() {
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
stringStringValueOperations.set("redis", "ok");
String redis = stringStringValueOperations.get("redis");
log.info("redis: {}", redis);
// 打印 redis 的連接工廠是用的 Lettuce 還是 jedis
log.info(String.valueOf(redisConnectionFactory.getClass()));
}
(8) 實(shí)現(xiàn)一個(gè)小功能 => 統(tǒng)計(jì)每個(gè)url訪問(wèn)的次數(shù)
- 在springboot連接好redis后
- 原理
- 1.通過(guò) Interceptor
攔截除去登陸,靜態(tài)資源外的所有請(qǐng)求 - 2.在攔截器中實(shí)現(xiàn) HandlerInterceptor 接口的前置鉤子
preHandle方法 - 3.在 preHandle 方法中通過(guò)獲取自動(dòng)注入的
StringRedisTemplate的opsForValue()的increment()方法實(shí)現(xiàn)統(tǒng)計(jì) - 4.redis => 中的
increment(url)方法,key=url, value=計(jì)數(shù) - 5.攔截器通過(guò)
@Component添加到容器中,在配置類(lèi)中實(shí)現(xiàn)WebMvcConfigurer接口的addInterceptors方法實(shí)現(xiàn)攔截
- 1.通過(guò) Interceptor
- 詳細(xì)步驟
(1)
src/mian/java/com.example.demo/interceptor/RedisUrlCountInteceptor.java
-------
/**
* Interceptor 和 Filter 都具有相同的功能
* 區(qū)別:
* 1. Filter: 是Servlet定義的原生組件,好處是脫離spring也能使用
* 2. Interceptor: 是spring定義的接口,只能在spring中使用,可以使用Spring的 ( 自動(dòng)裝配 ) 等功能
*/
@Component // 將攔截器放到容器中
public class RedisUrlCountInterceptor implements HandlerInterceptor {
@Autowired
StringRedisTemplate stringRedisTemplate; // 自動(dòng)注入操作redis的容器中的組件類(lèi)
// preHandle 前置鉤子
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
// stringRedisTemplate.opsForValue().increment(url) => 該方法每次訪問(wèn)該地址,url計(jì)數(shù)都會(huì)+1
stringRedisTemplate.opsForValue().increment(requestURI);
return true;
}
}
(2)
src/main/java/com.example.demo/config/AdminWebConfig.java
-------
/**
* 攔截器
* 1. 編寫(xiě)一個(gè)攔截器,實(shí)現(xiàn) HandlerInterceptor 接口
* 2. 把攔截器注冊(cè)到容器中 ( 實(shí)現(xiàn) WebMvcConfigurer 接口的 addInterceptors 方法)
* 3. 指定攔截規(guī)則 【如果攔截所有,靜態(tài)資源也會(huì)被攔截,可以用 excludePathPatterns 方法放行】
*/
// @Configuration 用于定義 ( 配置類(lèi) )
@Configuration
@EnableConfigurationProperties
public class AdminWebConfig implements WebMvcConfigurer {
// 這里之所以可以自動(dòng)注入,是因?yàn)镽edisUrlCountInterceptor類(lèi)通過(guò)@Compoent注冊(cè)到容器中了,非配置類(lèi)
@Autowired
RedisUrlCountInterceptor redisUrlCountInterceptor;
// @Override表示被標(biāo)注的方法是一個(gè)重寫(xiě)方法
// override 覆蓋
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(redisUrlCountInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/", "/login", "css/**", "/fonts/**", "/images/**", "/js/**");
}
}