01 Spring與SpringMVC回顧
文章目錄
前言
SpringBoot本身沒有增加任何新的技術,其是對Spring開發方式的一種簡化。
Spring的出現,本身是為了簡化JavaEE的開發。
可是隨著Spring體系的不斷壯大,Spring本身也被各種配置所拖累,有戲言稱:Spring開發就是一本java一半xml。
SpringBoot則利用Spring4開始提供的條件註解,大大簡化了Spring專案的開發。
現在的開發人員是幸福的,從語言到工具鏈,以及現在的網路環境和學習環境,只要想學,就能有所收穫。
本文梳理一下Spring和SpringMVC的核心功能,並不對基礎概念進行解釋。建議在學習Spring之前,小夥伴需要對Spring有所瞭解。
Spring核心
Spring框架設計原則
Spring的出現了為了簡化JavaEE開發,其在設計過程中遵循了一些基礎原則
- 使用POJO進行輕量級和最小侵入式開發
- 通過依賴注入和基於介面程式設計實現鬆耦合
- 通過AOP和預設習慣進行宣告式程式設計
- 使用AOP和 模板減少模式化程式碼
控制反轉與依賴注入
名詞解釋
- 什麼是控制反轉
在編寫Java程式碼時,最長做的操作可能就是獲取一個物件了,在原始階段,我們可能使用new
關鍵字建立一個物件,當然,也有通過工廠模式獲取物件的。
但不管怎麼說,這個物件是我們自己拿
來的。
而在Spring中,我們是在編寫一個個元件,元件編寫完畢後交給Spring管理,在需要用到的地方只要說
一聲,由Spring負責物件的初始化。
將物件由原先自己建立,改變為使用Spring管理的過程,這就是控制反轉
- 什麼是依賴注入
Spring根據我們的說明,將合適的物件交給我們進行使用,這個就是依賴注入。
核心註解
在控制反轉與依賴注入過程中,我們會用到一些註解
宣告Bean:@Component、@Service、@Repository、@Controller
注入Bean:@Autowired、@Inject、@Resource
@Configuration:聲明當前類是一個配置類
@ComponentScan:掃描Bean,將被掃描到的Bean初始化後納入Spring容器進行管理
面向切面程式設計
面向過程和麵向物件,是我們比較熟悉的兩種程式設計正規化。
面向切面也一樣,也是一種程式設計正規化。
其不是對其它程式設計正規化的顛覆,只是一個有益的補充。有其合適的適用場景。
舉個例子,我們希望在特定方法呼叫前和呼叫後,將呼叫的方法引數和返回值進行答應。這個時候使用AOP做就非常方便。否則我們就需要手動在方法內部進行日誌的列印。
SpEL表示式
- 將固定的字串注入給成員變數
@Value("普通字串注入")
private String str;
- 使用SpEL表示式獲取系統屬性進行注入
@Value("#systemProperties['os.name']")
private String osName;
- 使用SpEL表示式生成一個隨機數
@Value("#{T(java.lang.Math).random()*100.0}")
private double randomNumber;
- 注入其他Bean的屬性
@Value("#{demoService.property}")
- 注入檔案
@Value("classpath:com/ist/a.txt")
private Resource resource;
- 注入網路資源
@Value("http://www.baidu.com")
private Resource resource;
- 注入屬性檔案的鍵值
@Value("${book.name}")
private String st;
- 注入配置檔案
@Autowired
private Environment env;
將當前類使用的配置檔案注入給env,呼叫env.getProperty("book.name)")
,就能夠獲取資料
Bean的生命週期
有時候在Bean初始化和銷燬的時候需要做一些事情
- 在使用@Bean註解的時候,通過initMethod和destoryMethod屬性指定
- 在Bean中,使用@PostConstruct(在建構函式執行完後執行)和@PreDestory
(在Bean銷燬前執行)如果使用第二種方式,那麼需要新增JSR-250支援
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
一般使用initMethod和destoryMethod就行了
非同步方法
使用多執行緒,實現方法的非同步呼叫
1、配置一個執行緒池
package cfg.spring;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* Created by nbcoolkid on 2017-05-20.
*/
@Configuration
@EnableAsync
public class TaskExecConf implements AsyncConfigurer{
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(5);
threadPoolTaskExecutor.setMaxPoolSize(10);
threadPoolTaskExecutor.setQueueCapacity(25);
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
2、在配置類中使用@EnableAsync開啟對非同步任務的支援
在執行Bean中使用@Async註解宣告其是一個非同步任務,如果標註在類上,說明這個類的所有方法都是非同步的
定時任務
對於一些簡單的定時任務,Spring也有自己的實現
使用方法:
1、在配置類上使用@EnableScheduling開啟支援
2、在任務方法上使用@Scheduled,使用core表示式設定時間
package org.zln.spb.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.zln.spb.ann.Task;
/**
* Created by nbcoolkid on 2017-10-17.
*/
@Task
public class Demo01Task {
@Scheduled(cron = "0/5 * * * * ? ")
public void showH() {
System.out.println("定時任務執行---");
}
}
這裡的@Task註解是一個自定義註解
package org.zln.spb.ann;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* Created by nbcoolkid on 2017-10-17.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Task {
String value() default "";
}
package org.zln.spb.task;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* Created by nbcoolkid on 2017-10-17.
*/
@Configuration
@EnableScheduling
@ComponentScan
public class TaskConfig {
}
package org.zln.spb.task;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Created by nbcoolkid on 2017-10-17.
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(TaskConfig.class);
Thread.sleep(1000 * 3600);
}
}
小結
Spring的內容當然不止這麼些,但是有些內容在SpringBoot中會深入講解,有些內容已經過時,這裡就不再深入展開了。
SpringMVC核心
MVC模式思想
如果編寫過非MVC模式的後端程式碼,直接用servlet api進行業務邏輯的實現。
一定能夠深刻的體會到MVC對後端開發帶來的巨大好處。
所謂MVC,就是將後端處理元件劃分為了模型、檢視、控制器,每個元件有自己的功能場景,在程式碼上進行了分層。使得邏輯更加清晰
@ControllerAdvice
控制器增強,一般用於控制器的全域性配置。
我經常用到的一個功能就是使用@ControllerAdvice來捕獲全域性的異常
檔案上傳
所有的MVC框架都會講到檔案上傳。
因為SpringBoot中有更簡潔的方式,這裡就不講了
HttpMessageConverter
服務端推送技術:SSE
小結
寫這篇文章,主要是為了對Sping的常見知識點做一個維護,為後續SpringBoot的展開做一個基礎。
加粗樣式