springBoot核心原理
Posted 吴二喵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springBoot核心原理相关的知识,希望对你有一定的参考价值。
一、配置文件
yaml的写法
##map的写法1
friends: lastName: zhangsan,age: 18
##map的写法2
friends:
lastName: zhangsan
age: 20
###list、set写法1
pets:
- cat
- dog
- pig
###list、set写法2
pets: [cat,dog,pig]
##单引号会将\\n作为字符串输出,双引号会将\\n作为换行输出
##双引号不会转义,单引号会转义
想要代码配置可以提示,添加如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
在打包的时候可以exclude相关配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
二、Web开发
2.1 静态资源访问
1、静态资源目录
静态资源目录:类路径下如下目录
/static
/public
/resources
/META-INF/resources
访问:当前项目根路径/+静态资源名
原理:静态映射/**
请求进来,先去controller看能不能处理,不能处理的所有请求又都交给静态资源处理器。
2、静态资源访问前缀
默认无前缀,可以在配置文件中修改
访问路径:当前项目+static-path-pattern+静态资源名=静态资源文件夹下找
spring.mvc.static-path-pattern: /res/**
修改静态资源的存放路径
spring:
resources:
static-location: classpath:/haha/
3、webjar
自动映射
WebJars是将web前端资源(js,css等)打成jar包文件,然后借助Maven工具,以jar包形式对web前端资源进行统一依赖管理,保证这些Web资源版本唯一性。WebJars的jar包部署在Maven中央仓库上。
访问地址:webjars/jquery/3.5.1/jquery.js
2.2 欢迎页支持
静态资源路径下 index.html
可以配置静态资源路径;但是不可以配置静态资源的访问前缀,否则导致index.html不能被默认访问。
spring.mvc.static-path-pattern: /res/**
controller能处理/index
2.3 自定义favicon
图标放在静态资源目录下即可
spring.mvc.static-path-pattern: /res/**
也会影响图标的显示
2.4 静态资源配置原理
springBoot启动默认加载xxxAutoConfiguration(自动配置类)
SpringMVC功能的自动配置类 WebMvcAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass(Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class)
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class)
public class WebMvcAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@Import(WebMvcAutoConfiguration.EnableWebMvcConfiguration.class)
@EnableConfigurationProperties(WebMvcProperties.class, ResourceProperties.class)
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer
配置文件的相关属性和xxx进行了绑定:WebMvcProperties(spring.mvc)和ResourceProperties(spring.resources)
配置类只有一个有参构造器
//有参构造器所有参数的值都会从容器中确定
//ResourceProperties 获取和spring.resources绑定的所有值的对象
//WebMvcProperties 获取和spring.mvc绑定的所有值的对象
//ListableBeanFactory beanFactory springbean工厂
//HttpMessageConverters 找到所有的HttpMessageConverters
//resourceHandlerRegistrationCustomizer 找到资源处理器的自定义器
//ServletRegistrationBean 给应用注册sevlet,filter...
@Import(WebMvcAutoConfiguration.EnableWebMvcConfiguration.class)
@EnableConfigurationProperties(WebMvcProperties.class, ResourceProperties.class)
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
private final ResourceProperties resourceProperties;
private final WebMvcProperties mvcProperties;
private final ListableBeanFactory beanFactory;
private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
private final ObjectProvider<DispatcherServletPath> dispatcherServletPath;
private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
2、资源处理的默认规则
public void addResourceHandlers(ResourceHandlerRegistry registry)
if (!this.resourceProperties.isAddMappings())
logger.debug("Default resource handling disabled");
else
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
//webjars的规则
if (!registry.hasMappingForPattern("/webjars/**"))
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]"/webjars/**").addResourceLocations(new String[]"classpath:/META-INF/resources/webjars/").setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern))
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]staticPathPattern).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
##禁用所有静态资源规则
spring:
resources:
add-mappings: false
public class ResourceProperties
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/";
private String[] staticLocations;
private boolean addMappings;
private final ResourceProperties.Chain chain;
private final ResourceProperties.Cache cache;
public ResourceProperties()
this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
3、欢迎页的处理规则
//HandlerMapping 处理器映射,保存了每个Handler能处理哪些请求
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider)
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(this.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());
this.setRootViewName("forward:index.html");
else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext))
//调用controller /index
logger.info("Adding welcome page template: index");
this.setRootViewName("index");
3、请求参数处理
0、请求映射
@xxxmapping
rest风格支持:使用http请求方式动词来表示对资源的操作。
以前:/getUser,/addUser, /deleteUser,/editUser
现在:/user GET–请求 POST-新增 PUT–修改 DELETE–删除
核心filter:HiddenHttpMethodFilter
用法:表单method=put,隐藏域_method=put
//springboot默认不开启
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(
prefix = "spring.mvc.hiddenmethod.filter",
name = "enabled",
matchIfMissing = false
)
<form action="/user" method="post">
<input name="_method" type="hidden" value="delete"/>
<input value="rest-delete提交" type="submit"/>
</form>
rest原理(表单提交使用rest)
表单提交会带上_method=put
请求过来被HiddenHttpMethodFilter
请求是否正常,并且是post
获取_method的值
兼容以下请求:delete,put,patch
原生request(post),包装模式requestWrapper重写了getMethod方法,返回的是传入的值
过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requestWrapper的。
rest使用客户端工具
如postman直接发送put,delete请求,无需filter
请求映射原理
1、httpservlet的doGet方法
2、frameworkservlet的processRequest–>doService
3、Dispatchservlet的doService实现 doDispatch(每个方法都会调用)
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
try
ModelAndView mv = null;
Object dispatchException = null;
try
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//找到当前请求使用哪个handler(controller)处理
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null)
this.noHandlerFound(processedRequest, response);
return;
所有的请求映射都保存在HandlerMapping(处理器映射)中
1、springBoot自动配置欢迎页的WelcomePageHandlerMapping,访问/会访问到index.html
2、RequestMappingHandlerMapping:保存了所有@RequestMapping和handler的映射规则,springBoot自动配置
3、请求进来挨个尝试所有的handlerMapping看是否有请求信息
4、我们也可以自定义handlerMapping
一、普通参数与基本注解
1、注解
@PathVariable 路径变量
@RequestParam 请求参数
@RequestHeader 请求头
@CookieValue cookie值
@RequestAttribute request域属性
@RequestBody 请求体
@MatrixVariable 矩阵变量
@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 Cookie cookie)
@PostMapping("/save")
public Map post(@RequestBody String content)
@Controller
public class RequestController
@GetMapping("/goto")
public String gotoPage(HttpServletRequest request)
request.setAttribute("msg","成功了。。");
return "forward:/success";//转发到/success请求
@ResponseBody
@GetMapping("/success")
public Map success(@RequestAttribute("msg") String msg,
HttpServletRequest request)
Map<String, Object> map = new HashMap<>();
map.put("annotation_msg",msg);
map.put("reqMethod_msg",msg);
return map;
/cars/path?aaa=bbb&ccc=ddd queryString查询字符串 @RequestParam
/cars/path;low=24;brand=byd,audi 矩阵变量
页面开发的时候,如果cookie被禁用了,session里面的内容怎么使用
session.set(a,b)---->jsessionid---->cookie----->每次请求都携带
url重写的方式:/adc;jseesionid=xxx 把cookie的值使用矩阵变量的方式进行传递
如/cars/sell;low=34;brand=byd,audi
springBoot默认禁用了矩阵变量的功能
手动开启的原理:对于路径的处理,urlPathHelper进行解析,setRemoveSemicolonContent设置false来支持矩阵变量
矩阵变量必须有url路径变量才能被解析
@GetMapping("/boss/bossId/empId")
public Map boss(@MatrixVariable(value = "age", pathVar = "bossId") Integer bossAge,
@MatrixVariable(value = "age", pathVar = "empId") Integer empAge)
参数处理的原理
1、HandlerMapping中找到处理请求的Handler(Controller.method())
2、为当前Handler找一个适配器 HandlerAdapter
RequestMappingHandlerAdapter–支持方法上标注@RequestMapping的
HandlerFunctionAdapter–支持函数式编程的
//DispatchServlet中的doDispatch方法中
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//RequestMappingHandlerAdapter的handleInternal方法中
//执行目标方法
mav = this.invokeHandlerMethod(request, response, handlerMethod);
ServletInvocableHandlerMethod
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
//InvocableHandlerMethod
//5、如何确定目标方法的每个参数值
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters))
return EMPTY_ARGS;
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++)
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null)
continue;
if (!this.resolvers.supportsParameter(parameter))
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
try
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
catch (Exception ex)
// Leave stack trace for later, exception may actually be resolved and handled...
if (logger.isDebugEnabled())
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString以上是关于springBoot核心原理的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot核心原理:自动配置、事件驱动、Condition