关于SpringBoot
SpringBoot官方简介:
Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can run. We take an opinionated view of the Spring platform and third-party libraries, so that you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.
个人理解的SpringBoot做了这几件事:
- 针对不同场景提供一些基础包(starter),其中处理了各个场景下不同包的版本依赖,简化了写pom文件
- 提供一系列功能性的辅助包,比如国际化(Localizer/Internationization)、拦截(Interceptor/Filter)、制动(Actuator)等等
- 最重要的:自动配置。这是SpringBoot的思想,简化配置,尽量做到零配置。并非所有组件没有配置功能,而是用约定替代认为配置,格个组件已经默认使用最常用的配置作为默认值,很多时候并不需要认为手工配置。
所以学习SpringBoot稍微会不太明白究竟学的是什么,内容比较散似乎没有核心,可能向我理解的,核心就是自动配置的思想,外加各种配置吧。
无论怎样,我是参照TutorialPoint上的教程大体了解了一边
核心的一些内容
starter
Spring官方有这样一个Starter页面(地址),在这里选择工程类型、springboot版本和初始依赖后,可以生成一个spring项目下载下来,作为项目开发的起点。
这个想法刚看到其实觉得有点不可思议,第一次看到一个框架会提供这样的功能帮助开展一个项目。不过Spring涉及的组件实在是太多,由这样的功能帮助解决依赖的确会方便不少。
基本的一个web项目内容:
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
parent模块包含了spring项目的一系列默认配置(比如再也不用手动指定java1.8版本了),而spring-boot-starter-web
依赖项包含了一系列开发web
项目需要的包,这里不需要指定版本,而是spring包帮忙维护了。
这些spring-boot-starter-***
的依赖,就是springboot的起点,除了web,还有一些其他的依赖封装,代表不同的功能。
自动配置
主入口
不再是SpringCore的ApplicationContext
,而是封装在了SpringApplication
中
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
// or new SpringApplicationBuilder(Example.class).run(args);
}
}
传入的Example.class
是类似SpringCore中的@Configuration
注解类,代表这个类里可以定义Bean
等,不过在SpringBoot中,不再是用Configuration
,而是使用@SpringBootApplication
。
这个注解包含了很多默认的配置,比如一个关键的从这个类开始进行component scan
,扫描application.properties
作为程序的property(bean
中也会用到),配置默认的MessageSource
读取位置等等。
推荐的项目结构
Spring推荐的项目结构:
com
+- example
+- myapplication
+- Application.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
简单来说,Spring的主入口(main函数,以及spring程序的主入口)最好也在main函数的类中,而且最好在整个项目的基础包中。
这是因为spring默认的@ComponetScan等功能,会以次类作为扫描起点扫描子包,如果配置成其他的,就需要一些额外的手动配置了。
其他功能
感觉SpringBoot核心就是这些,但是主要相关功能还是一些组件/注解的使用和配置,当然这些可能实际都不属于SpringBoot的范畴了。。
properties
bean
注解中也会用到,如
@Value("${prop.field.name}")
默认springboot会读取resources
目录下的application.properties
文件作为配置属性,当然,属性可以被命令行传入参数替换。
ApplicationRunner/CommandLineRunner
可以配置相应的Bean,或者实现这两个接口中的一个,使Spring启动后,运行这个Bean的Run方法,如:
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
log.info("Command line runner called");
Quote quote = restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
log.info(quote.toString());
};
}
interceptor/filter
两个功能上有点类似,都是拦截HTTP请求做处理的,类似SpringCore中的PostProcesser等,但是Filter使用更复杂一些,属于Servlet级别的。而Interceptor是Spring框架自己维护的机制。
这里注册了一个Intercepter,分别有三个接口,在请求处理前,处理后,处理完成时调用。
@Component
public class ProductInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("Pre Handle method is Calling");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Post Handle method is Calling");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) throws Exception {
System.out.println("Request and Response is completed");
}
}
Controller Advice
这个注解可以用于处理异常:
@ControllerAdvice
public class ProductExceptionController {
@ExceptionHandler(value = ProductNotfoundException.class)
public ResponseEntity<Object> exception(ProductNotfoundException exception) {
return new ResponseEntity<>("Product not found", HttpStatus.NOT_FOUND);
}
}
定义这个类,当Controller出现异常时,就会被其中的exception
方法捕获,处理响应
@Service和@RestController
其实本来没什么联系,但是放到一起。
@Service
用于标记MVC中的服务层。
@RestController
类似MVC中的@Controller
,不同的是@Controller
的返回值会被进一步交给View处理,而@RestController
会将结果直接返回
i18n
国际化/多语言配置,需要配置多个bean和注册interceptor:
//定义默认的Local
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.US);
return sessionLocaleResolver;
}
//处理每个请求对应的不同的locale
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("language");
return localeChangeInterceptor;
}
//定义国际化的资源文件,默认在resources目录下的messages.properties
//这里改为i18n目录下的messages.properties
//注意默认语言外的文件,通过下标来区分,如messages_cn.properties
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/i18n/messages");
return messageSource;
}
注册:
@Component
public class ProductInterceptorConfig implements WebMvcConfigurer {
@Autowired
LocaleChangeInterceptor localeChangeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor);
}
}
我看的教程,ProductInterceptorConfig
是继承的WebMvcConfigurerAdapter
类,不过在我的版本中,这个类已经被废弃了,可以直接实现WebMvcConfigurer
接口就能起作用。
我定义的一个工具类,用于获取资源:
@Component
public class I18nUtil {
@Autowired
MessageSource messageSource;
public String getMessage(String msg, Object[] args) {
String localeMessage = "";
try {
localeMessage = messageSource.getMessage(msg, args, LocaleContextHolder.getLocale());
} catch (Exception var4) {
System.out.println("Exception[" + messageSource + "]:" + var4.getMessage());
}
return localeMessage;
}
}
在Controller中就能获取对应的文字:
@Autowired
I18nUtil i18n;
@RequestMapping(value = "/hello")
public ResponseEntity<Object> sayHello() {
return new ResponseEntity<>(i18n.getMessage("welcome.text", null), HttpStatus.OK);
}
如果请求中增加?language=zh
,就能去查找中文
原文地址:https://www.cnblogs.com/mosakashaka/p/12609117.html