Spring Boot学习日记
2022/8/18 天气:晴天
今天开启了学习SpringBoot的第一天!!!
好家伙,一上来就是直接Hello,World 因为之前学习过了SSM,所以感觉Boot真的超级方便!
直接添加依赖,然后创建主程序,再创建控制器方法,最后启动主程序,输入跳转的页面即可看到效果,比SpringMVC方便太多了,终于可以不用配置一大堆的xml文件了!
1、Spring Boot官方文档
链接: 官方地址
点进去,一般看的都是CURRENT GA标识的,当前长期流行的版本
在遇到一些不太会的,可以进行查阅
2、Spring Boot入门
2.1、maven设置
有一些jdk版本不太一样的,可以百度进行修改
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
2.2、创建maven工程,引入依赖
在工程的pom.xml文件下引入以下依赖, 版本号可以自行修改
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2.3、创建主程序
@SpringBootApplication:该注解声明–>这是一个SpringBoot应用
/**
* 主程序类
* @SpringBootApplication:这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
2.4、创建控制器方法
@RestController:包含了@Controller注解和@ResponseBody注解
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "Hello, Spring Boot!";
}
}
然后直接运行main方法即可,然后输入localhost:8080/hello即可看到
Hello, Spring Boot! 样字
2.5、修改配置
我们可以在resources目录下面添加application.properties文件,对Boot中的一些配置进行修改,比如修改服务器端口号
server.port=8888
2.6、了解配置原理
2.6.1、依赖管理
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<!--他的父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
当我们在引入了版本号之后,springboot会自动给我们引入该版本装配好的jar包,我们也可以自己对一些不满意的版本的jar进行修改,比如修改mysql-connection
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
2.6.2、自动配置
-
自动配好Tomcat
-
- 引入Tomcat依赖。
- 配置Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
-
自动配好SpringMVC
-
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(功能)
-
自动配好Web常见功能,如:字符编码问题
-
- SpringBoot帮我们配置好了所有web开发的常见场景
-
默认的包结构
-
- 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
- 无需以前的包扫描配置
- 想要改变扫描路径,@SpringBootApplication(scanBasePackages=“com.atguigu”)
-
-
- 或者@ComponentScan 指定扫描路径
-
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
-
各种配置拥有默认值
-
- 默认配置最终都是映射到某个类上,如:MultipartProperties
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
-
按需加载所有自动配置项
-
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
2022/8/19 天气:晴天
没想到暑假已经过去这么久了,感觉自己啥都没学,总是空落落的,而且还非常的焦虑,怕秋招校招找不到好工作。恐惧的原因来源于实力不足,还是好好努力吧!
2.7、容器功能
2.7.1、@Configuration
@Configuration注解:告诉SpringBoot这是一个配置类 == 配置文件.xml
1、配置类中使用@Bean注解标识在方法上,给容器注册组件,默认是单实例的
外部无论对配置类中的这个组件注册方法调用多少次,获取的都是容器中的单实例对象
2、配置类本身也是组件,可以进行获取
3、@Configuration注解中的proxyBeanMethods属性:代理bean的方法
–>默认为true,则是单实例 即底层的Full(proxyBeanMethods = true)模式
–>为false时,则是多例 产生多个对象 即底层的Lite(proxyBeanMethods = false)模式 轻量级模式,可以直接跳过检查,不需要查看IOC容器中是否有这个对象 目的是解决组件依赖
2.7.2、@Bean、@Component、@Controller、@Service、@Repository
@Bean 给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
其余注解和Spring5中的注解一致
2.7.3、@ComponentScan、@Import
@ComponentScan即扫描组件
@Import(): 导入组件 默认是一个Class的数组
调用括号中的组件中的无参构造函数,放入IOC容器中
即 给容器中自动创建出这几个类型的组件
直接用getBean就行 默认组件的名字是全类名
@Import 高级用法:https://www.bilibili.com/video/BV1gW411W7wy?p=8
2.7.4、@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
@Conditional:条件装配
满足Conditional指定的条件,则进行组件注入
有许多子组件,比如@ConditionalOnBean @ConditionalOnMissingBean
2.8、原生配置文件引入
2.8.1、@ImportResource
@ImportResource
导入资源 比如说你在xml配置文件中写好了一些东西,可以通过这个注解进行引入
一般写在类上面
2.8.2、配置绑定
如何使用java读取properties文件中的内容,并且把它封装到JavaBean中
@ConfigurationProperties
写在Bean类上
@EnableConfigurationProperties(类.class)+@ConfigurationProperties
@EnableConfigurationProperties(类.class)
在配置类中写 开启属性配置功能 把这个类组件自动注册到容器中
@Component+@ConfigurationProperties(prefix=“”) 前缀
只用在容器中的组件,才会拥有SpringBoot提供的强大功能
/**
* 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
*/
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
2.9、自动配置原理
自动配置原理
2.9.1、引导加载自动配置类
@SpringBootApplication 主要是解释这个注解 以下三个注解是包含在SpringBootApplication注解中的
@SpringBootConfiguration注解的功能 是一个配置类
@EnableAutoConfiguration注解
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
–>@AutoConfigurationPackage
指定了默认的包规则
自动配置包 底层 @Import(AutoConfigurationPackage.Register.class) 批量注册 导入一系列组件
源码是获取包名,转换为list然后进行注册 所以组件才要放到MainApplication同级目录或以下
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
–>@Import(AutoConfigurationImportSelector.class)
文件中写死了springboot中一开始就要给容器中加载的所有配置类 127个
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
–>@ComponentScan(“com.atguigu.boot”) 指定我们要扫描哪些组件
2.9.2、按需开启自动配置项
虽然我们127个配置,默认全部加载,但是最终会按需配置 源码中使用到了@Conditional条件装配
2.9.3、定制化修改自动配置
spring boot默认会在底层配好所有的组件,但是如果用户自己配置了以用户的优先
总结:
SpringBoot先加载所有的自动配置类 xxxAutoConfiguration
每个自动配置类按照条件进行生效,默认会绑定配置文件指定的值 xxxProperties里面拿 xxxProperties和配置文件进行了绑定
生效的配置类就会给容器中装配很多组件
只要用户有自己配置的,就以用户的优先
定制化配置:用户自己@Bean替换底层的组件
用户去看这个组件是获取的配置文件中的什么值 进行修改
查文档,查底层源码
2.10、开发小技巧
2.10.1、Lombok
在新版的IDEA中,是集成了该插件(小辣椒),我们只需要在pom.xml文件中引入依赖,然后使用@Date注解即可配置一个JavaBean对象,直接简化了我们的代码
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
===============================简化JavaBean开发===================================
@NoArgsConstructor
//@AllArgsConstructor
@Data
@ToString
@EqualsAndHashCode
public class User {
private String name;
private Integer age;
private Pet pet;
public User(String name,Integer age){
this.name = name;
this.age = age;
}
}
================================简化日志开发===================================
@Slf4j
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(@RequestParam("name") String name){
log.info("请求进来了....");
return "Hello, Spring Boot 2!"+"你好:"+name;
}
}
2.10.2、dev-tools
项目或者页面修改以后:Ctrl+F9; 相当于reload
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
2.10.3、Spring Initailizer
我们在创建项目的时候可以直接选择创建Spring Initailizer项目,勾选我们所需要的依赖即可
2022/8/20 天气:晴天
3、Web开发
3.1、配置文件
在SpringBoot中,主要有两种配置文件。一种是properties文件,一种是yaml文件
propertries文件即key=value
而yaml文件的基本语法是
-
key: value 注意key与value之间有空格 即冒号后面跟一个空格
-
大小写敏感
-
使用缩进表示层级关系,不允许使用tab,只允许使用空格,空格数量不重要 左对齐就行
-
#表示注释
-
字符串无需加引号,一定要加的话’‘和""之间注意字符转义的问题,一般’'会被转义双引号不会
示例:
先声明两个类 Person类和Pet类 下面会在yaml文件中进行初始化定义
@Data
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salarys;
private Map<String, List<Pet>> allPets;
}
@Data
public class Pet {
private String name;
private Double weight;
}
yaml文件中, 注意Date类型 Pet类型 数组类型 List、Map、Set类型的写法
# yaml表示以上对象
person:
userName: zhangsan
boss: false
birth: 2019/12/12 20:12:33
age: 18
pet:
name: tomcat
weight: 23.4
interests: [篮球,游泳]
animal:
- jerry
- mario
score:
english:
first: 30
second: 40
third: 50
math: [131,140,148]
chinese: {first: 128,second: 136}
salarys: [3999,4999.98,5999.99]
allPets:
sick:
- {name: tom}
- {name: jerry,weight: 47}
health: [{name: mario,weight: 47}]
我们可以在pom.xml文件中添加配置,这样在编写yaml文件的时候,就会有提示了。
配置完成后需要我们重新启动一遍项目才会有提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
3.2、静态资源访问
不用@EnableWebMvc注解。使用
**@Configuration**
+**WebMvcConfigurer**
自定义规则声明
**WebMvcRegistrations**
改变默认底层组件使用
**@EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC**
我们可以将静态资源放在类路径下进行访问
/static
、/public
、/resources
、/META-INF/resources
四个路径进行访问 格式是 当前项目根路径/+静态资源名
原理是 静态映射/**
有请求进来,先去找Controller看能不能处理,不能处理的话,将请求交给静态资源处理器,还是没有找到的话则返回404页面
我们可以使用yaml文件改变默认的静态资源路径
注意:properties文件的优先级大于yaml文件
spring:
mvc:
static-path-pattern: /res/** # 这个会导致welcome page功能失效
resources:
static-locations: [classpath:/haha/]
当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找
3.3、欢迎页支持
-
静态资源路径下 index.html
-
- 可以配置静态资源路径
- 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
3.4、自定义Favicon
favicon.ico 放在静态资源目录下即可。
spring:
mvc:
static-path-pattern: /res/** # 这个会导致Favicon功能失效
2022/8/22 天气:晴天
3.5、静态资源配置原理
- SpringBoot启动默认加载 xxxAutoConfiguration 类(自动配置类)
- SpringMVC功能的自动配置类 WebMvcAutoConfiguration,生效
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {}
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
- 配置文件的相关属性和xxx进行了绑定。
WebMvcProperties==spring.mvc、
ResourceProperties==spring.resources
查看WebMvcAutoConfigurationAdapter该类源码
发现只有一个有参构造器
//有参构造器所有参数的值都会从容器中确定
//ResourceProperties resourceProperties;获取和spring.resources绑定的所有的值的对象
//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象
//ListableBeanFactory beanFactory Spring的beanFactory
//HttpMessageConverters 找到所有的HttpMessageConverters
//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。=========
//DispatcherServletPath
//ServletRegistrationBean 给应用注册Servlet、Filter....
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
ObjectProvider<DispatcherServletPath> dispatcherServletPath,
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
this.resourceProperties = resourceProperties;
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath;
this.servletRegistrations = servletRegistrations;
}
3.5.1、资源处理的默认规则
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
//webjars的规则
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
//
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
主要看if语句中的isAddMappings()方法
我们可以在yaml文件中,进行配置 默认是true 我们改为false则是禁用所有静态资源规则
spring:
# mvc:
# static-path-pattern: /res/**
resources:
add-mappings: false 禁用所有静态资源规则
再看if语句下面的这一句Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
我们进入到ResourceProperties.java文件中查看源码,找到了CLASSPATH_RESOURCE_LOCATIONS资源位置
看到注释也就是我们一开始说的四个位置
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/].
*/
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
3.5.2、欢迎页的处理规则
我们在springmvc中的xml配置文件中,是配置了一个handlerMapping,而在springboot中直接就有
HandlerMapping:处理器映射。保存了每一个Handler能处理哪些请求。
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
return welcomePageHandlerMapping;
}
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {
if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
//要用欢迎页功能,必须是/**
logger.info("Adding welcome page: " + welcomePage.get());
setRootViewName("forward:index.html");
}
else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
// 调用Controller /index
logger.info("Adding welcome page template: index");
setRootViewName("index");
}
}
4、请求参数处理
4.1、请求映射原理
也就是分析@RequestMapping注解的原理
我们现在都是使用了RestFul风格的url,同一个url会有4种不同的方法,我们是用method属性进行区分的。
而且html中的表单功能,只有get和post功能,我们需要使用要隐藏域,然后name属性必须要是_method
,后面的value是Put|Delete
才行
-
核心Filter;HiddenHttpMethodFilter
- 用法: 表单method=post,隐藏域 method=put
- SpringBoot中手动开启
-
_扩展:如何把_method 这个名字换成我们自己喜欢的
示例:
@RequestMapping(value = "/user",method = RequestMethod.GET)
public String getUser(){
return "GET-张三";
}
@RequestMapping(value = "/user",method = RequestMethod.POST)
public String saveUser(){
return "POST-张三";
}
@RequestMapping(value = "/user",method = RequestMethod.PUT)
public String putUser(){
return "PUT-张三";
}
@RequestMapping(value = "/user",method = RequestMethod.DELETE)
public String deleteUser(){
return "DELETE-张三";
}
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
//自定义filter
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
methodFilter.setMethodParam("_m");
return methodFilter;
}
Rest原理(表单提交要使用REST的时候)
-
表单提交会带上_method=PUT_
-
请求过来被HiddenHttpMethodFilter拦截
- 请求是否正常,并且是POST
- 获取到method的值。
兼容以下请求;PUT.DELETE.PATCH - 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
- 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
Rest使用客户端工具,如PostMan直接发送Put、delete等方式请求,无需Filter。
spring:
mvc:
hiddenmethod:
filter:
enabled: true #开启页面表单的Rest功能
源码分析:
SpringMVC功能都从 org.springframework.web.servlet.DispatcherServlet–>doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 找到当前请求使用哪个Handler(Controller的方法)处理
mappedHandler = getHandler(processedRequest);
//HandlerMapping:处理器映射。/xxx->>xxxx
RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
所有的请求映射都在HandlerMapping中。
-
SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
-
SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
-
请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
-
- 如果有就找到这个请求对应的handler
- 如果没有就是下一个 HandlerMapping
-
我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
2022/8/23 天气:晴天
学的有点慢哈,主要是在消化雷神将的源码分析(哭),应该是要慢慢的更新了
4.2、请求处理常用参数
1、@PathVariable() 可以根据url路径中的占位符进行改变 也可以直接在参数中使用map<String, String>
接收所有的占位符的值
2、@RequestHeader 获取部分请求头信息 也可以使用map<String, String>
来接收所有的请求头信息
3、@RequestParam 获取请求参数 也可以使用map<String, String>
来接收所有的请求参数信息 但是如果是list信息不能用map来接收
4、@CookieValue 获取cookie的值 可以直接在参数中声明 Cookie类型的参数用来接收所有的cookie值 _ga
5、@RequestBody 获取请求体[POST]
6、@RequestAttribute 获取request域属性 一般设置页面转发获取 参数中获取转发来的数据
7、@MatrixVariable 矩阵变量 矩阵变量应该绑定在路径变量中
/url/{path}?xxx=xxx&aaa=ccc 这种方式我们成为queryString 查询字符串 使用@RequestParam
/url/{path;low=34;brand=byd,audi,yd} 使用分号写法的 称之为矩阵变量
类似与当禁用cookie时获取session 使用url重写 /abc;jsessionid=xxx 把cookie的值使用矩阵变量的方式进行传递
/boss/1;age=20/
/boss/1;age=20/2;age=20
但是在SpringBoot种禁用了@MatrixVariable功能 应该手动开启
原因:
对于路径的处理,都是在UrlPathHelper进行解析的,其中有一个属性removeSemicolonContent(移除分号内容)默认是true
WebMVCAutoConfiguration–>configPathMatch–>urlPathHelper–>removeSemicolonContent = true
修改为false才能使用
PS:使用pathVar来区分相同名字的参数
以上7种方法都能够使用map进行接收