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