SpringBoot(springboot常用注解)

  本篇文章为你整理了SpringBoot(springboot常用注解)的详细内容,包含有springboot启动流程 springboot常用注解 springboot核心注解 springboot自动装配 SpringBoot,希望能帮助你了解 SpringBoot。

  官方文档架构

  查看版本新特性;

  https://github.com/spring-projects/spring-boot/wiki#release-notes

  快速体验SpringBoot

  Java 8 兼容java14 .

  Maven 3.3+

  idea 2019.1.2

  Maven设置

  

 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

  

 

  Hello Word

  需求:浏览发送/hello请求,响应 Hello,Spring Boot 2

  创建maven工程

  

 parent 

 

   groupId org.springframework.boot /groupId

   artifactId spring-boot-starter-parent /artifactId

   version 2.3.4.RELEASE /version

   /parent

  
groupId org.springframework.boot /groupId

   artifactId spring-boot-starter-web /artifactId

   /dependency

   /dependencies

  

 

  创建主程序

  

package com.lkjedu.boot;

 

  import org.springframework.boot.SpringApplication;

  import org.springframework.boot.autoconfigure.SpringBootApplication;

   * 主程序类

   * @SpringBootApplication:告诉SpringBoot这是一个SpringBoot应用

   * */

  @SpringBootApplication

  public class MainApplication {

   public static void main(String[] args) {

   SpringApplication.run(MainApplication.class,arg s);

  

 

  

package com.lkjedu.boot.controller;

 

  import org.springframework.web.bind.annotation.RequestMapping;

  import org.springframework.web.bind.annotation.RestController;

  @RestController

  public class HelloController {

   @RequestMapping("hello")

   public String handle01(){

   return "Hello SpringBoot2";

  

 

  直接运行main方法

  

 build 

 

   plugins

   plugin

   groupId org.springframework.boot /groupId

   artifactId spring-boot-maven-plugin /artifactId

   /plugin

   /plugins

   /build

  

 

  把项目打成jar包,直接在目标服务器执行即可。

  注意点:

  取消掉cmd的快速编辑模式

  父项目做依赖管理

  

依赖管理 

 

   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

  几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制

  

 

  开发导入starter场景启动器

  

1、见到很多 spring-boot-starter-* : *就某种场景

 

  2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入

  3、SpringBoot所有支持的场景

  https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter

  4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。

  5、所有场景启动器最底层的依赖

   dependency

   groupId org.springframework.boot /groupId

   artifactId spring-boot-starter /artifactId

   version 2.3.4.RELEASE /version

   scope compile /scope

   /dependency

  

 

  无需关注版本号,自动版本仲裁

  1、引入依赖默认都可以不写版本
 

  2、引入非版本仲裁的jar,要写版本号。

  可以修改默认版本号

  

1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。

 

  2、在当前项目里面重写配置

   properties

   mysql.version 5.1.43 /mysql.version

   /properties

  

 

  
groupId org.springframework.boot /groupId

   artifactId spring-boot-starter-tomcat /artifactId

   version 2.3.4.RELEASE /version

   scope compile /scope

   /dependency

  

 

 

  
无需以前的包扫描配置

  想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.atguigu")

  
默认配置最终都是映射到某个类上,如:MultipartProperties

  配置文件的值最终会绑定每个类上,这个类会在容器中创建对象

  
引入了哪些场景这个场景的自动配置才会开启

  SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

  
配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断

  配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式

  


#############################Configuration使用示例######################################################

 

   * 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的

   * 2、配置类本身也是组件

   * 3、proxyBeanMethods:代理bean的方法

   * Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】

   * Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】

   * 组件依赖必须使用Full模式默认。其他默认是否Lite模式

  @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件

  public class MyConfig {

   * Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象

   * @return

   @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例

   public User user01(){

   User zhangsan = new User("zhangsan", 18);

   //user组件依赖了Pet组件

   zhangsan.setPet(tomcatPet());

   return zhangsan;

   @Bean("tom")

   public Pet tomcatPet(){

   return new Pet("tomcat");

  
################################@Configuration测试代码如下########################################

  @SpringBootConfiguration

  @EnableAutoConfiguration

  @ComponentScan("com.atguigu.boot")

  public class MainApplication {

   public static void main(String[] args) {

   //1、返回我们IOC容器

   ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

   //2、查看容器里面的组件

   String[] names = run.getBeanDefinitionNames();

   for (String name : names) {

   System.out.println(name);

   //3、从容器中获取组件

   Pet tom01 = run.getBean("tom", Pet.class);

   Pet tom02 = run.getBean("tom", Pet.class);

   System.out.println("组件:"+(tom01 == tom02));

  
//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892

   MyConfig bean = run.getBean(MyConfig.class);

   System.out.println(bean);

   //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。

   //保持组件单实例

   User user = bean.user01();

   User user1 = bean.user01();

   System.out.println(user == user1);

  
User user01 = run.getBean("user01", User.class);

   Pet tom = run.getBean("tom", Pet.class);

   System.out.println("用户的宠物:"+(user01.getPet() == tom));

  
2@Bean、@Component、@Controller、@Service、@Repository

  

 * 4、@Import({User.class, DBHelper.class})

 

   * 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名

  @Import({User.class, DBHelper.class})

  @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件

  public class MyConfig {

  

 

  @Import 高级用法: https://www.bilibili.com/video/BV1gW411W7wy?p=8

  3、@ComponentScan、@Import

  

 * 4、@Import({User.class, DBHelper.class})

 

   * 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名

  @Import({User.class, DBHelper.class})

  @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件

  public class MyConfig {

  

 

  @Import 高级用法: https://www.bilibili.com/video/BV1gW411W7wy?p=8

  4、@Conditional

  条件装配:满足Conditional指定的条件,则进行组件注入

  

=====================测试条件装配==========================

 

  @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件

  //@ConditionalOnBean(name = "tom")

  @ConditionalOnMissingBean(name = "tom")

  public class MyConfig {

  
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象

   * @return

   @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例

   public User user01(){

   User zhangsan = new User("zhangsan", 18);

   //user组件依赖了Pet组件

   zhangsan.setPet(tomcatPet());

   return zhangsan;

   @Bean("tom22")

   public Pet tomcatPet(){

   return new Pet("tomcat");

  public static void main(String[] args) {

   //1、返回我们IOC容器

   ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

   //2、查看容器里面的组件

   String[] names = run.getBeanDefinitionNames();

   for (String name : names) {

   System.out.println(name);

   boolean tom = run.containsBean("tom");

   System.out.println("容器中Tom组件:"+tom);

   boolean user01 = run.containsBean("user01");

   System.out.println("容器中user01组件:"+user01);

   boolean tom22 = run.containsBean("tom22");

   System.out.println("容器中tom22组件:"+tom22);

  


======================beans.xml=========================

 

   ?xml version="1.0" encoding="UTF-8"?

   beans xmlns="http://www.springframework.org/schema/beans"

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:context="http://www.springframework.org/schema/context"

   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"

   bean id="haha"

   property name="name" value="zhangsan" /property

   property name="age" value="18" /property

   /bean

   bean id="hehe"

   property name="name" value="tomcat" /property

   /bean

   /beans

  

 

  

@ImportResource("classpath:beans.xml")

 

  public class MyConfig {}

  ======================测试=================

   boolean haha = run.containsBean("haha");

   boolean hehe = run.containsBean("hehe");

   System.out.println("haha:"+haha);//true

   System.out.println("hehe:"+hehe);//true

  

 

  
@ConfigurationProperties

  如何使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用;

  

public class getProperties {

 

   public static void main(String[] args) throws FileNotFoundException, IOException {

   Properties pps = new Properties();

   pps.load(new FileInputStream("a.properties"));

   Enumeration enum1 = pps.propertyNames();//得到配置文件的名字

   while(enum1.hasMoreElements()) {

   String strKey = (String) enum1.nextElement();

   String strValue = pps.getProperty(strKey);

   System.out.println(strKey + "=" + strValue);

   //封装到JavaBean。

  

 

  
@EnableConfigurationProperties + @ConfigurationProperties

  

@EnableConfigurationProperties(Car.class)

 

  //1、开启Car配置绑定功能

  //2、把这个Car这个组件自动注册到容器中

  public class MyConfig {

  

 

  
@EnableAutoConfiguration

  @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),

   @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

  public @interface SpringBootApplication{}

  
@Import({AutoConfigurationImportSelector.class})

  public @interface EnableAutoConfiguration {}

  

 

  


@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件

 

  public @interface AutoConfigurationPackage {}

  //利用Registrar给容器中导入一系列组件

  //将指定的一个包下的所有组件导入进来?MainApplication 所在包下。

  

 

  


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

  

 

  
按需开启自动配置项

  

虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration

 

  按照条件装配规则(@Conditional),最终会按需配置。

  

 

  修改默认配置

  

 @Bean

 

   @ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件

   @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件

   public MultipartResolver multipartResolver(MultipartResolver resolver) {

   //给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。

   //SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范

   // Detect if the user has created a MultipartResolver but named it incorrectly

   return resolver;

  给容器中加入了文件上传解析器;

  

 

  SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

  

@Bean

 

   @ConditionalOnMissingBean

   public CharacterEncodingFilter characterEncodingFilter() {

  

 

  总结:

  

● SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration

 

  ● 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定

  ● 生效的配置类就会给容器中装配很多组件

  ● 只要容器中有这些组件,相当于这些功能就有了

  ● 定制化配置

   ○ 用户直接自己@Bean替换底层的组件

   ○ 用户去看这个组件是获取的配置文件什么值就去修改。

  xxxxxAutoConfiguration --- 组件 --- xxxxProperties里面拿值 ---- application.properties

  

 

  
自己分析,引入场景对应的自动配置一般都生效了

  配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)

  
import lombok.Data(@Data):生成已有属性的geter和seter方法

  import lombok.ToString(@ToString):生成已有属性的toString方法

  import lombok.NoArgsConstructor(@NoArgsConstructor):生成已有属性的无参构造器

  import lombok.AllArgsConstructor(@AllArgsConstructor):生成已有属性的全参构造器

  import lombok.EqualsAndHashCode(@EqualsAndHashCode):重写我们的Equals和HashCode方法

  import lombok.slf4j(@slf4j):相当于我们的日志类

  

 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;

  
groupId org.springframework.boot /groupId

   artifactId spring-boot-devtools /artifactId

   optional true /optional

   /dependency

  

 

  项目或者页面修改以后:Ctrl+F9;

  Spring Initailizr(项目初始化向导)

  
YAML 是 "YAML Aint Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。非常适合用来做以数据为中心的配置文件

  
在yaml文件格里面式,单引号会将“\n”简单的字符串输出

  在yaml文件格里面式,双引号会将“\n”则会作为转义符

  
groupId org.springframework.boot /groupId

   artifactId spring-boot-configuration-processor /artifactId

   optional true /optional

   /dependency

  
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

  

 

  web开发

  SpringMVC自动配置概览

  Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)

  The auto-configuration adds the following features on top of Spring’s defaults:

  
自动使用 ConfigurableWebBindingInitializer ,(DataBinder负责将请求数据绑定到JavaBean上)

  
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

  
不用@EnableWebMvc注解。使用 **@Configuration** + **WebMvcConfigurer** 自定义规则

  
If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

  
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.

  
使用 **@EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC**

  
静态资源目录

  只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources

  访问:当前项目根路径/+静态资源名

  原理:静态映射/**

  请求进来先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则直接报404

  改变默认的静态资源路径

  

spring:

 

   mvc:

   static-path-pattern: /res/**

  #改变姿态资源路径

   resources:

   static-locations: [classpath:/haha/]

  

 

  
可以配置静态资源路径

  但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问

  
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进行了绑定。WebMvcPropertiesspring.mvc、ResourcePropertiesspring.resources

  配置类只有一个有参构造器

  

 //有参构造器所有参数的值都会从容器中确定

 

  //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;

  

 

  

spring:

 

  # mvc:

  # static-path-pattern: /res/**

   resources:

   add-mappings: false 禁用所有静态资源规则

  

 

  

@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;

  

 

  欢迎页的处理规则

  

 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");

  

 

  请求参数处理

  rest使用与原理

  
以前:**/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户

  现在: /user GET-**获取用户 DELETE-**删除用户 PUT-**修改用户 POST-**保存用户

  核心Filter;HiddenHttpMethodFilter

  


 @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.DELETE)

   public String deleteUser(){

   return "DELETE-张三";

  
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)

   @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)

   public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {

   return new OrderedHiddenHttpMethodFilter();

  
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){

   HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();

   methodFilter.setMethodParam("_m");

   return methodFilter;

  

 

  
兼容以下请求;PUT.DELETE.PATCH

  原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。

  过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用****requesWrapper的。

  
请求映射原理

  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;

  
我们需要一些自定义的映射处理,我们也可以自己给容器中放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;

  

 

  普通参数与基本注解

  
@ModelAttribute:被@ModelAttribute注解的方法会在Controller每个方法执行之前都执行,因此对于一个Controller中包含多个URL的时候,要谨慎使用。

  
@MatrixVariable:虽然从Spring 3.2就已经支持@MatrixVariable特性,但直至现在其依然为默认禁用的状态。我们需要手工配置开启才能使用。

  
public void configurePathMatch(PathMatchConfigurer configurer) {

   UrlPathHelper urlPathHelper = new UrlPathHelper();

   urlPathHelper.setRemoveSemicolonContent(false);

   configurer.setUrlPathHelper(urlPathHelper);

  

 

 

  
@CookieValue:@RequestHeader以及@CookieValue这两个注解用法类似,属性也相同,所以,写在一起。二者属性和RequestParam的属性一样,用法也几乎一样。

  @RequestHeader注解主要是将请求头的信息区数据,映射到功能处理方法的参数上。@CookieValue注解主要是将请求的Cookie数据,映射到功能处理方法的参数上。

  
@RequestBody:@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个

  
@GetMapping("/car/{id}/owner/{username}")

   public Map String,Object getCar(@PathVariable("id") Integer id,

   @PathVariable("username") String name,

   @PathVariable Map String,String pv,

   @RequestHeader("User-Agent") String userAgent,

   @RequestHeader Map String,String header,

   @RequestParam("age") Integer age,

   @RequestParam("inters") List String inters,

   @RequestParam Map String,String params,

   @CookieValue("_ga") String _ga,

   @CookieValue("_ga") Cookie cookie){

  
public Map postMethod(@RequestBody String content){

   Map String,Object map = new HashMap ();

   map.put("content",content);

   return map;

  
//1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd

   //2、SpringBoot默认是禁用了矩阵变量的功能

   // 手动开启:原理。对于路径的处理。UrlPathHelper进行解析。

   // removeSemicolonContent(移除分号内容)支持矩阵变量的

   //3、矩阵变量必须有url路径变量才能被解析

   @GetMapping("/cars/{path}")

   public Map carsSell(@MatrixVariable("low") Integer low,

   @MatrixVariable("brand") List String brand,

   @PathVariable("path") String path){

   Map String,Object map = new HashMap ();

   map.put("low",low);

   map.put("brand",brand);

   map.put("path",path);

   return map;

   // /boss/1;age=20/2;age=10

   @GetMapping("/boss/{bossId}/{empId}")

   public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,

   @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){

   Map String,Object map = new HashMap ();

   map.put("bossAge",bossAge);

   map.put("empAge",empAge);

   return map;

  

 

 

  Servlet API

  WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

  ServletRequestMethodArgumentResolver 以上的部分参数

  

@Override

 

   public boolean supportsParameter(MethodParameter parameter) {

   Class ? paramType = parameter.getParameterType();

   return (WebRequest.class.isAssignableFrom(paramType)

   ServletRequest.class.isAssignableFrom(paramType)

   MultipartRequest.class.isAssignableFrom(paramType)

   HttpSession.class.isAssignableFrom(paramType)

   (pushBuilder != null pushBuilder.isAssignableFrom(paramType))

   Principal.class.isAssignableFrom(paramType)

   InputStream.class.isAssignableFrom(paramType)

   Reader.class.isAssignableFrom(paramType)

   HttpMethod.class == paramType

   Locale.class == paramType

   TimeZone.class == paramType

   ZoneId.class == paramType);

  

 

  Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

  

Map String,Object map, Model model, HttpServletRequest request 都是可以给request域中放数据,

 

  request.getAttribute();

  

 

  Map、Model类型的参数,会返回 mavContainer.getModel();--- BindingAwareModelMap 是Model 也是Map

  mavContainer.getModel(); 获取到值的

  数据响应与内容协商

  视图解析与模板引擎

  视图解析:SpringBoot默认是不支持JSP, 需要引入第三方模板引擎技术实现页面渲染

  视图解析原理流程

  1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址

  2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer

  3、任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。

  4、****processDispatchResult 处理派发结果(页面改如何响应)

  
1、所有的视图解析器尝试是否能根据当前返回值得到View对象

  2、得到了 redirect:/main.html -- Thymeleaf new RedirectView()

  3、ContentNegotiationViewResolver 里面包含了下面所有的视图解析。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: