公司做網站app入什么科目國家高新技術企業(yè)查詢
百日筑基第十一天-看看SpringBoot
創(chuàng)建項目
Spring 官方提供了 Spring Initializr 的方式來創(chuàng)建 Spring Boot 項目。網址如下:
https://start.spring.io/
打開后的界面如下:
可以將 Spring Initializr 看作是 Spring Boot 項目的初始化向導,它可以幫助開發(fā)人員在一分鐘之內創(chuàng)建一個 Spring Boot 骨架,非常的傻瓜式。
來解釋一下 Spring Initializr 初始化界面中的關鍵選項。
1)Project:項目的構建方式,可以選擇 Mavenopen in new window(安裝方式可以戳鏈接) 和 Gradle(構建腳本基于 Groovy 或者 Kotlin 等語言來編寫,而不是傳統(tǒng)的 XML)。編程喵默認采用的 Maven。
2)Language:項目的開發(fā)語言,可以選擇 Java、Kotlin(JetBrains開發(fā)的可以在 JVM 上運行的編程語言)、Groovy(可以作為 Java 平臺的腳本語言來使用)。默認 Java 即可。
3)Spring Boot:項目使用的 Spring Boot 版本。默認版本即可,比較穩(wěn)定。
4)Project Metada:項目的基礎設置,包括包名、打包方式、JDK 版本等。
- Group:項目所屬組織的標識符,比如說 top.codingmore;
- Artifact:項目的標識符,比如說 coding-more;
- Name:默認保持和 Artifact 一致即可;
- Description: 項目的描述信息,比如說《編程喵實戰(zhàn)項目(Spring Boot+Vue 前后端分離項目)》;
- Package name:項目包名,根據Group和Artifact自動生成即可。
- Packaging: 項目打包方式,可以選擇 Jar 和 War(SSM 時代,JavaWeb 項目通常會打成 War 包,放在 Tomcat 下),Spring Boot 時代默認 Jar 包即可,因為 Spring Boot 可以內置 Tomcat、Jetty、Undertow 等服務容器了。
- Java:項目選用的 JDK 版本。
5)Dependencies:項目所需要的依賴和 starter。如果不選擇的話,默認只有核心模塊 spring-boot-starter 和測試模塊 spring-boot-starter-test。
生成zip文件解壓:
重要的包
spring-boot-devtools 熱部署
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId>
</dependency>
整合Lombok簡化代碼
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.6</version><scope>provided</scope>
</dependency>
然后就可以這樣用了:
@Getter
@Setter
class CmowerLombok {private int age;private String name;private BigDecimal money;
}
其中 scope=provided
,就說明 Lombok
只在編譯階段生效。也就是說,Lombok
會在編譯期靜悄悄地將帶 Lombok
注解的源碼文件正確編譯為完整的 class
文件。
SpringBoot 2.1.x 版本后不需要再顯式地添加 Lombok 依賴了。之后,還需要為 Intellij IDEA 安裝 Lombok
插件,否則 Javabean
的 getter / setter
就無法自動編譯,也就不能被調用。不過,新版的 Intellij IDEA 也已經內置好了,不需要再安裝。
@Getter / @Setter
用起來很靈活,比如說像下面這樣:
class CmowerLombok {@Getter @Setter private int age;@Getter private String name;@Setter private BigDecimal money;
}
@ToString
注解可以生成 toString
方法:
@ToString
class CmowerLombok {private int age;private String name;private BigDecimal money;
}
@Data
注解可以生成 getter / setter
、equals
、hashCode
,以及 toString
,是個總和的選項。
@Data
class CmowerLombok {private int age;private String name;private BigDecimal money;
}
@Slf4j
可以用來生成注解對象,你可以根據自己的日志實現方式來選用不同的注解,比如說:@Log
、@Log4j
、@Log4j2
、@Slf4j
等。
@Slf4j
public class Log4jDemo {public static void main(String[] args) {log.info("level:{}","info");log.warn("level:{}","warn");log.error("level:{}", "error");}
}
@Builder
注解可以用來通過建造者模式來創(chuàng)建對象,這樣就可以通過鏈式調用的方式進行對象賦值,非常的方便。
@Builder
@ToString
public class BuilderDemo {private Long id;private String name;private Integer age;public static void main(String[] args) {BuilderDemo demo = BuilderDemo.builder().age(18).name("沉默王二").build();System.out.println(demo);}
}
Lombok 還提供了同步注解 @Synchronized、自動拋出異常注解 @SneakyThrows、不可變對象 @Value、自動生成 hashCode 和 equals 方法的注解 @EqualsAndHashCode等等,
Lombok 用起來雖然爽,但需要團隊內部達成一致,就是要用大家都用,否則有些用了有些沒用就會亂成一鍋粥,很影響代碼的整體風格。
整合 MySQL 和 Druid
Mysql
對應pom.xml文件中的代碼:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>
</dependency>
在 application.yml 文件中添加數據庫鏈接驅動信息:
spring:datasource:username: codingmore-mysqlpassword: YyfR4TDxCwrjZ2Fsurl:jdbc: mysql://118.190.99.232:3306/codingmore-mysql?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
@SpringBootTest
@Slf4j
class CodingmoreMysqlApplicationTests {@Resourceprivate JdbcTemplate jdbcTemplate;@Testvoid contextLoads() {String sql ="select * from user";List<User> users = jdbcTemplate.query(sql, new RowMapper<User>() {@Overridepublic User mapRow(ResultSet rs, int rowNum) throws SQLException {User user = new User();user.setId(rs.getInt(1));user.setAge(rs.getInt("age"));user.setName(rs.getString("name"));user.setPassword(rs.getString("password"));return user;}});log.info("查詢成功");log.info("用戶{}",users);}
}
Spring Boot 的測試類主要放置在 src/test/java
目錄下面,項目創(chuàng)建成功后,Spring Boot 會根據項目名稱自動為我們生成測試類。
比如說本次項目名為 codingmore-mysql,那么測試類名為 CodingmoreMysqlApplicationTests。
@SpringBootTest
注解能夠測試我們的項目主類,該項目為 CodingmoreMysqlApplication。
@Test
注解是 junit 單元測試的注解,表示該方法為測試方法。
JdbcTemplate
一個通過 JDBC 連接數據庫的工具類,spring-boot-starter-jdbc 依賴中包含了該類。
@Resource
注解會幫我們在 Spring Boot 啟動的時候注入一個 JdbcTemplate 的對象。
jdbcTemplate.query()
方法通過 SQL 語句和匿名內部類參數的形式,執(zhí)行 SQL 并查詢結果集。
RowMapper
就是查詢到的每一行數據對象,我們可以通過重寫 mapRow 方法將數據結果集封裝到 User 對象上。
Druid
Druid 是阿里巴巴開源的一款數據庫連接池,結合了C3P0、DBCP 等 DB 池的優(yōu)點,同時還加入了日志監(jiān)控。
Druid 包含了三個重要的組成部分:
- DruidDriver,能夠提供基于 Filter-Chain 模式的插件體系;
- DruidDataSource,高效可管理的數據庫連接池;
- SQLParser,支持所有 JDBC 兼容的數據庫,包括 Oracle、MySQL 等。
第一步,在 pom.xml 文件中添加 Druid 的依賴,官方已經提供了 starter,我們直接使用。
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.23</version>
</dependency>
第二步,在 application.yml 文件中添加 Druid 配置。
spring:datasource: type: com.alibaba.druid.pool.DruidDataSourcedruid:#初始化連接池大小initial-size: 5#配置最小連接數min-idle: 5#配置最大連接數max-active: 200#配置連接等待超時時間max-wait: 60000#配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒time-between-eviction-runs-millis: 60000#配置一個連接在池中最小生存的時間,單位是毫秒min-evictable-idle-time-millis: 300000#測試連接validation-query: SELECT 1 FROM DUAL#申請連接的時候檢測,建議配置為true,不影響性能,并且保證安全test-while-idle: true#獲取連接時執(zhí)行檢測,建議關閉,影響性能test-on-borrow: false#歸還連接時執(zhí)行檢測,建議關閉,影響性能test-on-return: false#是否開啟PSCache,PSCache對支持游標的數據庫性能提升巨大,oracle建議開啟,mysql下建議關閉pool-prepared-statements: false#開啟poolPreparedStatements后生效max-pool-prepared-statement-per-connection-size: 20#配置擴展插件,常用的插件有=>stat:監(jiān)控統(tǒng)計 log4j:日志 wall:防御sql注入filters: stat,wall,slf4j#打開mergeSql功能;慢SQL記錄connection-properties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000#配置DruidStatFilterweb-stat-filter:enabled: trueurl-pattern: "/*"exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"#配置DruidStatViewServletstat-view-servlet:url-pattern: "/druid/*"#登錄名login-username: root#登錄密碼login-password: root
第三步,啟動項目。在日志信息里可以看到 Druid 的初始化信息。
第四步,通過 http://localhost:9002/druid/
地址就可以在瀏覽器訪問 Druid 的監(jiān)控頁面了,用戶名和密碼是我們在配置文件里指定的 root 和 root,登錄后是這樣的。
Spring 對事務的支持
Spring 支持兩種事務方式,分別是編程式事務和聲明式事務,后者最常見,通常情況下只需要一個 @Transactional
就搞定了(代碼侵入性降到了最低),就像這樣:
@Transactional
public void savePosts(PostsParam postsParam) {// 保存文章save(posts);// 處理標簽insertOrUpdateTag(postsParam, posts);
}
1)編程式事務
編程式事務是指將事務管理代碼嵌入嵌入到業(yè)務代碼中,來控制事務的提交和回滾。
你比如說,使用 TransactionTemplate 來管理事務:
@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {try {// .... 業(yè)務代碼} catch (Exception e){//回滾transactionStatus.setRollbackOnly();}}});
}
再比如說,使用 TransactionManager 來管理事務:
@Autowired
private PlatformTransactionManager transactionManager;public void testTransaction() {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// .... 業(yè)務代碼transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}
}
就編程式事務管理而言,Spring 更推薦使用 TransactionTemplate。
在編程式事務中,必須在每個業(yè)務操作中包含額外的事務管理代碼,就導致代碼看起來非常的臃腫,但對理解 Spring 的事務管理模型非常有幫助。
2)聲明式事務
聲明式事務將事務管理代碼從業(yè)務方法中抽離了出來,以聲明式的方式來實現事務管理,對于開發(fā)者來說,聲明式事務顯然比編程式事務更易用、更好用。
當然了,要想實現事務管理和業(yè)務代碼的抽離,就必須得用到 Spring 當中最關鍵最核心的技術之一,AOP,其本質是對方法前后進行攔截,然后在目標方法開始之前創(chuàng)建或者加入一個事務,執(zhí)行完目標方法之后根據執(zhí)行的情況提交或者回滾。
聲明式事務雖然優(yōu)于編程式事務,但也有不足,聲明式事務管理的粒度是方法級別,而編程式事務是可以精確到代碼塊級別的。
Spring Boot 對事務的支持
只需要在業(yè)務層添加事務注解(@Transactional
)就可以快速開啟事務。
也就是說,我們只需要把焦點放在 @Transactional
注解上就可以了。
@Transactional 的作用范圍
- 類上,表明類中所有 public 方法都啟用事務
- 方法上,最常用的一種
- 接口上,不推薦使用
@Transactional 的常用配置參數
雖然 @Transactional 注解源碼中定義了很多屬性,但大多數時候,我都是采用默認配置,當然了,如果需要自定義的話,前面也都說明過了。
@Transactional 的使用注意事項總結
1)要在 public 方法上使用,在AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法中有個判斷,如果目標方法不是public,則TransactionAttribute返回null,即不支持事務。
2)避免同一個類中調用 @Transactional 注解的方法,這樣會導致事務失效。
過濾器、攔截器、監(jiān)聽器
- 過濾器(Filter):當有一堆請求,只希望符合預期的請求進來。
- 攔截器(Interceptor):想要干涉預期的請求。
- 監(jiān)聽器(Listener):想要監(jiān)聽這些請求具體做了什么。
過濾器
- 過濾敏感詞匯(防止sql注入)
- 設置字符編碼
- URL級別的權限訪問控制
- 壓縮響應信息
添加一個過濾器 MyFilter :
@WebFilter(urlPatterns = "/*", filterName = "myFilter")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {long start = System.currentTimeMillis();chain.doFilter(request,response);System.out.println("Execute cost="+(System.currentTimeMillis()-start));}@Overridepublic void destroy() {Filter.super.destroy();}
}
@WebFilter 注解用于將一個類聲明為過濾器,urlPatterns 屬性用來指定過濾器的 URL 匹配模式,filterName 用來定義過濾器的名字。
MyFilter 過濾器的邏輯非常簡單,重寫了 Filter 的三個方法,在 doFilter 方法中加入了時間戳的記錄。然后我們在項目入口類上加上 @ServletComponentScan 注解,這樣過濾器就會自動注冊。
攔截器
- 登錄驗證,判斷用戶是否登錄
- 權限驗證,判斷用戶是否有權限訪問資源,如校驗token
- 日志記錄,記錄請求操作日志(用戶ip,訪問時間等),以便統(tǒng)計請求訪問量
- 處理cookie、本地化、國際化、主題等
- 性能監(jiān)控,監(jiān)控請求處理時長等
@Slf4j
public class LoggerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("preHandle{}...",request.getRequestURI());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}
一個攔截器必須實現 HandlerInterceptor 接口,preHandle 方法是 Controller 方法調用前執(zhí)行,postHandle 是 Controller 方法正常返回后執(zhí)行,afterCompletion 方法無論 Controller 方法是否拋異常都會執(zhí)行。
只有 preHandle 返回 true 的話,其他兩個方法才會執(zhí)行。
如果 preHandle 返回 false 的話,表示不需要調用Controller方法繼續(xù)處理了,通常在認證或者安全檢查失敗時直接返回錯誤響應。
再來一個 InterceptorConfig 對攔截器進行配置:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggerInterceptor()).addPathPatterns("/**");}
}
@Configuration 注解用于定義配置類,干掉了以往 Spring 繁瑣的 xml 配置文件。
編寫一個用于被攔截的控制器 MyInterceptorController:
@RestController
@RequestMapping("/myinterceptor")
public class MyInterceptorController {@RequestMapping("/hello")public String hello() {return "沉默王二是傻X";}
}
@RestController 注解相當于 @Controller + @ResponseBody 注解,@ResponseBody 注解用于將 Controller 方法返回的對象,通過適當的 HttpMessageConverter 轉換為指定格式后,寫入到 Response 對象的 body 數據區(qū),通常用來返回 JSON 或者 XML 數據,返回 JSON 數據的情況比較多。