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进行接收

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值