Spring框架学些SpringBoot

Posted mosakashaka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring框架学些SpringBoot相关的知识,希望对你有一定的参考价值。

关于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,就能去查找中文

以上是关于Spring框架学些SpringBoot的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot:thymeleaf 没有正确渲染片段

Maven多模块项目,框架SSM怎么改成springboot的?

spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器

Spring Boot

spring 和springboot的区别

如何整合SpringBoot和Mybatis框架?