前言
在使用spring的過程中,我們有沒有發(fā)現(xiàn)它的擴(kuò)展能力很強(qiáng)呢?由于這個(gè)優(yōu)勢(shì)的存在,使得spring具有很強(qiáng)的包容性,所以很多第三方應(yīng)用或者框架可以很容易的投入到spring的懷抱中。今天我們主要來學(xué)習(xí)Spring中很常用的11個(gè)擴(kuò)展點(diǎn),你用過幾個(gè)呢?
1. 類型轉(zhuǎn)換器
如果接口中接收參數(shù)的實(shí)體對(duì)象中,有一個(gè)字段類型為Date,但實(shí)際傳遞的參數(shù)是字符串類型:2022-12-15 10:20:15,該如何處理?
Spring提供了一個(gè)擴(kuò)展點(diǎn),類型轉(zhuǎn)換器Type Converter
,具體分為3類:
Converter
: 將類型 S 的對(duì)象轉(zhuǎn)換為類型 T 的對(duì)象ConverterFactory
: 將 S 類型對(duì)象轉(zhuǎn)換為 R 類型或其子類對(duì)象GenericConverter
:它支持多種源和目標(biāo)類型的轉(zhuǎn)換,還提供了源和目標(biāo)類型的上下文。此上下文允許您根據(jù)注釋或?qū)傩?a target="_blank">信息執(zhí)行類型轉(zhuǎn)換。
還是不明白的話,我們舉個(gè)例子吧。
- 定義一個(gè)用戶對(duì)象
@Data
public class User {
private Long id;
private String name;
private Date registerDate;
}
- 實(shí)現(xiàn)
Converter
接口
public class DateConverter implements Converter
- 將新定義的類型轉(zhuǎn)換器注入到Spring容器中
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DateConverter());
}
}
- 調(diào)用接口測(cè)試
@RequestMapping("/user")
@RestController
public class UserController {
@RequestMapping("/save")
public String save(@RequestBody User user) {
return "success";
}
}
請(qǐng)求接口時(shí),前端傳入的日期字符串,會(huì)自動(dòng)轉(zhuǎn)換成Date類型。
2. 獲取容器Bean
在我們?nèi)粘i_發(fā)中,經(jīng)常需要從Spring容器中獲取bean,但是你知道如何獲取Spring容器對(duì)象嗎?
2.1 BeanFactoryAware
@Service
public class PersonService implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void add() {
Person person = (Person) beanFactory.getBean("person");
}
}
實(shí)現(xiàn)BeanFactoryAware接口,然后重寫setBeanFactory方法,可以從方法中獲取spring容器對(duì)象。
2.2 ApplicationContextAware
@Service
public class PersonService2 implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void add() {
Person person = (Person) applicationContext.getBean("person");
}
}
實(shí)現(xiàn)ApplicationContextAware
接口,然后重寫setApplicationContext
方法,也可以通過該方法獲取spring容器對(duì)象。
2.3 ApplicationListener
@Service
public class PersonService3 implements ApplicationListener<ContextRefreshedEvent> {
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
applicationContext = event.getApplicationContext();
}
public void add() {
Person person = (Person) applicationContext.getBean("person");
}
}
3. 全局異常處理
以往我們?cè)陂_發(fā)界面的時(shí)候,如果出現(xiàn)異常,要給用戶更友好的提示,例如:
@RequestMapping("/test")
@RestController
public class TestController {
@GetMapping("/add")
public String add() {
int a = 10 / 0;
return "su";
}
}
如果不對(duì)請(qǐng)求添加接口結(jié)果做任何處理,會(huì)直接報(bào)錯(cuò):
用戶可以直接看到錯(cuò)誤信息嗎?
這種交互給用戶帶來的體驗(yàn)非常差。為了解決這個(gè)問題,我們通常在接口中捕獲異常:
@GetMapping("/add")
public String add() {
String result = "success";
try {
int a = 10 / 0;
} catch (Exception e) {
result = "error";
}
return result;
}
界面修改后,出現(xiàn)異常時(shí)會(huì)提示:“數(shù)據(jù)異?!?,更加人性化。
看起來不錯(cuò),但是有一個(gè)問題。
如果只是一個(gè)接口還好,但是如果項(xiàng)目中有成百上千個(gè)接口,還得加異常捕獲代碼嗎?
答案是否定的,這就是全局異常處理派上用場(chǎng)的地方:RestControllerAdvice
。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
if (e instanceof ArithmeticException) {
return "data error";
}
if (e instanceof Exception) {
return "service error";
}
retur null;
}
}
方法中處理異常只需要handleException
,在業(yè)務(wù)接口中就可以安心使用,不再需要捕獲異常(統(tǒng)一有人處理)。
4. 自定義攔截器
Spring MVC攔截器,它可以獲得HttpServletRequest
和HttpServletResponse
等web對(duì)象實(shí)例。
Spring MVC攔截器的頂層接口是HandlerInterceptor
,它包含三個(gè)方法:
preHandle
在目標(biāo)方法執(zhí)行之前執(zhí)行- 執(zhí)行目標(biāo)方法后執(zhí)行的
postHandle
afterCompletion
在請(qǐng)求完成時(shí)執(zhí)行
為了方便,我們一般繼承HandlerInterceptorAdapter
,它實(shí)現(xiàn)了HandlerInterceptor
。
如果有授權(quán)鑒權(quán)、日志、統(tǒng)計(jì)等場(chǎng)景,可以使用該攔截器,我們來演示下吧。
- 寫一個(gè)類繼承
HandlerInterceptorAdapter
:
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestUrl = request.getRequestURI();
if (checkAuth(requestUrl)) {
return true;
}
return false;
}
private boolean checkAuth(String requestUrl) {
return true;
}
}
- 將攔截器注冊(cè)到spring容器中
@Configuration
public class WebAuthConfig extends WebMvcConfigurerAdapter {
@Bean
public AuthInterceptor getAuthInterceptor() {
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor());
}
}
- Spring MVC在請(qǐng)求接口時(shí)可以自動(dòng)攔截接口,并通過攔截器驗(yàn)證權(quán)限。
5. 導(dǎo)入配置
有時(shí)我們需要在某個(gè)配置類中引入其他的類,引入的類也加入到Spring容器中。這時(shí)候可以使用注解@Import
來完成這個(gè)功能。
如果你查看它的源代碼,你會(huì)發(fā)現(xiàn)導(dǎo)入的類支持三種不同的類型。
但是我覺得最好把普通類的配置類和@Configuration
注解分開解釋,所以列出了四種不同的類型:
-
轉(zhuǎn)換器
+關(guān)注
關(guān)注
27文章
8505瀏覽量
145983 -
框架
+關(guān)注
關(guān)注
0文章
396瀏覽量
17269 -
spring
+關(guān)注
關(guān)注
0文章
335瀏覽量
14259
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論