SpringBoot實戰項目精華總結(五)

SpringBoot實戰項目精華總結(五)
  一、異常相關
 
二、Mybatis相關
 
三、AB壓測
 
四、處理併發
 
五、redis緩存的使用
 
六、項目部署
一、異常相關
1.最外層異常(返回給調用方的異常處理)

@ResponseBody
@ExceptionHandler(value = SellException.class)
public ResultVO handdlerSellerException(SellException sellException){
  return ResultVOUtil.error(sellException.getCode(), sellException.getMessage());
}

這樣返回的狀態碼依然是200
如果想讓狀態碼也返回對應的“客戶端”4xx、“服務端”5xx狀態

@ResponseStatus(HttpStatus.FORBIDDEN)
@ExceptionHandler(value = SpecialException.class)
public void handdlerSpException(SpecialException specialException){}

二、Mybatis相關
依賴:

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

在主啓動類上添加註解:@MapperScan(basePackages = "Mapper所在的文件夾")
 1.註解形式

public interface ProductCategoryMapper {
    @Insert("insert into dept (name, age) values(#{name, jdbcType = VARCHAR}, #{age, jdbcType = INTEGER})")
    int insertDeptByObject(Map<String, Object> params);
}

注:不加上@Mapper也沒問題,有Insert()註解就能被識別
  
在傳多個參數時,需要加@Param註解!
 
mybatis打開查看sql語句功能,改變mapper包下的日誌打印等級爲trace
 
 2.xml配置形式
resources下建mybatis/mapper/DeptMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.discovery.dao.DeptDao">
  <select id="findById" resultType="Dept" parameterType="Long">
   select deptno,dname,db_source from dept where deptno=#{deptno}; 
  </select>
  <select id="findAll" resultType="Dept">
   select deptno,dname,db_source from dept; 
  </select>
  <insert id="addDept" parameterType="Dept">
   INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE());
  </insert>
</mapper>

application.yaml文件配置

mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis配置文件所在路徑
  type-aliases-package: com.discovery.entities          # 所有Entity別名類所在包
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml   

mybatis.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
   <setting name="cacheEnabled" value="true"/><!-- 二級緩存開啓 -->
   <setting name="logImpl" value="STDOUT_LOGGING" />
  </settings>
</configuration>

其他代碼示例(先查出map,再將map轉成類做屬性對應):

三、AB壓測
工具:Apache ab
命令示例:
ab -n 100 -c 100 http://www.xxx.com,-n = 模擬請求數,-c = 模擬併發數,即同時請求
ab -t 60 -c 100 http://www.xxx.com,-t = 模擬請求數在60秒內完成,-c = 模擬併發數

四、處理併發
秒殺場景問題代碼
  
1.synchronized處理併發
  在方法上加synchronized關鍵字,原理是每次訪問該方法時只有一個線程進入方法,無法做到細粒度的控制,只適用於單機,並且嚴重影響處理速度
2.redis分佈式鎖(redis.cn中文官網)

單線程工作的,setnx、incr、getset,可以使用 !setnx加鎖
 - 加鎖方法代碼片段:key是商品id,對應的值爲鎖將會過期的時間,只有當一個線程獲取到的和單線程的redis獲取到的剩餘數量一致時,才能拿到鎖。
注:加鎖方法中的入參value是當前時間+超時時間的一個值


分析:倒數第8行,通過getset方法,必然兩個線程,有一個取到的時間是對方帶進來的時間,然後只有一個最終獲得了過期後的鎖。
 - 解鎖代碼片段:

- 使用:

還可以使用redission工具實現秒殺 => 參考:REDIS學習總結(三)REDIS集羣下分佈式鎖學習與SpringBoot秒殺場景簡單實踐

五、redis緩存的使用
緩存使用的會遇到的概念:命中、失效、更新
1.基於註解形式的實現
 - 在啓動類上加@EnableCaching註解
 - 引入spring-boot-cache依賴座標
使用:
 - @Cacheable(cacheNames = "", key = ""),常用的兩個屬性,前者相當於前綴,key是redis存儲的cacheNames:key
 - @CachePut(cacheNames = "", key = ""),更新緩存,但是要求和@Cacheable方法返回值一致
 - @CacheEvict(cacheNames = "", key = ""),清除緩存
key如果不填,那key的值默認爲""!注意要更新相同的key
cacheNames可以通過@CacheConfig(cacheNames = "")提到類上
另外,key可以根據方法入參的值動態變化,使用spel表達式:
 - @Cacheable(cacheNames = "", key = "#方法參數名")
 - condition可以設置緩存條件
 - unless = “result.getCode() != 0”,當返回值不成功時,不緩存!

六、項目部署
 
相關命令:
打包:mvn clean package -Dmaven.test.skip=true
啓動:java -jar -Dserver.port=8080 -Dspring.profiles.active=prod 項目.jar

創建自啓動命令:
cd /etc/systemd/system
vi 項目名.service
  

啓動項目:
systemctl start 項目名
停止項目:
systemctl stop 項目名
開機自啓動:
systemctl enable 項目名

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章