- 1. 配置
- 2. 自动配置原理
- 2.1 组件添加
- @Configuration (proxyBeanMethods = true)
- @Bean
- @Component、@Controller、@Service、@Repository
- @ComponentScan、@Import
- @Conditional
- 2.2 原生配置文件引入
- @ImportResource
- 2.3 配置绑定
- @ConfigurationProperties
- @EnableConfigurationProperties
- 3. 自动配置原理入门
- 3.1 引导加载自动配置类
- (1)@SpringBootConfiguration
- (2)@ComponentScan
- (3)@EnableAutoConfiguration ***比较重要***
- 3.2 按需开启自动配置项
- 3.3 修改默认配置
- 3.4 最佳实践
- 4. 开发小技巧
- 4.1、Lombok(不建议使用?)
- @Slf4j
- 3. 配置文件
- 4. Web开发
- 1. 请求参数处理
- 1.1 Rest使用
- 1.2 Rest原理
- 1.3 请求映射原理
- 2. 普通参数的基本注解
- 1. 注解
- 2. Servlet API:
- 3. 复杂参数:
- 4. 自定义对象参数:
- 容器 单例模式
- 5. web场景
- 1. thymeleaf
- 2. 拦截器
- 原理
- 总结(别人的):
- 3. 文件上传
- 文件上传自动配置原理
- 4. web原生组件注入
- 配置类方法
- 5. 嵌入式Servlet容器
- 6. 数据访问场景
- 1. 数据源的自动配置
- 2. 分析自动配置
- 3. 修改配置项
- 4. druid配置
- 5. mybatis整合
- 小结
- springboot开发的几个问题
- 📔 controller是什么
- 📘controller和servlet区别
- 📗什么能被注入到IOC容器
- ❓️【提问】thymeleaf能获取controller的什么数据
- ❓️【提问】前端页面如何获取后台数据
- ❓️【提问】域的作用
- 🖕响应式编程
- J2EE
- 自定义starter
- springboot特性
约定>配置>编码
springboot解决乱码问题,这里的乱码是StringHttpMessageConverter解决的,反射获取defaultCharset是UTF-8,如果通过反射set为ISO_8859_1,就又乱码了
2. 自动配置原理 2.1 组件添加 @Configuration (proxyBeanMethods = true)■ 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
■ 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
这个注解用于需要灵活创建组件的场合,组件是方法的返回值,名称是方法名
@Component、@Controller、@Service、@Repository在Stereotype(旧规矩)模式下,Spring为Controller-Service-Dao的分层模型分别提供了@Controller、@Service、@Repository注解,除此之外的组件使用@Component注解。
根据它们的源码可以看到,Controller、Service、Repository其本质就是Component。它存在的本质只是给开发者看的,对Spring而言它们就都是Component。@Controller 控制层类,@Service 业务层类,@Repository 持久层类,@Component 无法归类到前3种时就称为组件。
@ComponentScan:扫描包,如果没有指定包,那么默认会扫描此配置类所在的package。
@Import:自动从类中的无参构造函数创建一个实例注册到 IOC 容器中
【注意】@Import所创建的实例在 IOC 容器中默认的id名为类的全限定名,如 User 类就是:com.atguigu.bean.User,import的好处是可以引入外部类,可以标注在主配置类或者组件上
刚刚测试过,是先判断条件,成立后才会注入本类下的组件。因为是用反射拿的组件方法,所以按字节码顺序来。注册顺序很重要
2.2 原生配置文件引入只有容器中的组件才能享受springboot强大的功能
@ImportResource允许以spring配置文件的方式对组件进行注册。位置在类的上方。
**【提问】**那为什么不直接在类里面创建组件并加入容器呢 是不是因为写在配置文件方便频繁修改
@ImportResource(“classpath:beans.xml”)用来导入指定的配置文件。
@ConfigurationProperties场景例子:我们习惯将经常爱变化的东西写在.properties配置文件中,比如与数据库相关的信息(连接池、URL等)配置到配置文件中,为了方便我们会将配置文件中的内容解析到JavaBean中。这个过程使用java原生代码较为麻烦。
配置绑定:两种方式
1.@Component@ConfigurationProperties(prefix = “mycar”)声明在要绑定的类的上方
2.@ConfigurationProperties(prefix = “mycar”)声明在要绑定的类的上方;
在配置类的上方声明@EnableConfigurationProperties(Car.class),开启对应类的配置绑定功能,把Car这个组件自动注入到容器中;如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入
说明一下为什么需要第二种方法。如果@ConfigurationProperties是在第三方包中,那么@component是不能注入到容器的。只有@EnableConfigurationProperties才可以注入到容器。
@EnableConfigurationProperties@EnableConfigurationProperties的功能是开启类的配置绑定,而且还能自动注册类到容器中,更加方便使用
3. 自动配置原理入门 3.1 引导加载自动配置类 (1)@SpringBootConfiguration@Configuration代表当前是一个配置类,main方法也是个配置类方法
@ SpringBootConfiguration只是Spring标准@Configuration批注的替代方法。 两者之间的唯一区别是@SpringBootConfiguration允许自动找到配置。
指定扫描哪些,Spring注解;
(3)@EnableAutoConfiguration 比较重要包含的核心注解就是@AutoConfigurationPackage
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
这里有两个作用:
- 将指定目录下的所有组件导入到Spring容器中
- 将扫描路径注册到全局,给其他组件查询(例如:JPA)
@Import(AutoConfigurationImportSelector.class)
3.2 按需开启自动配置项1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用Listconfigurations = getCandidateConfigurations(annotationMetadata, attributes)>获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map> 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使用@import将AutoConfigurationPackages包下的Registrar类作为组件导入到容器中,然后使用>Registrar中的方法批量完成组件的注册。这个配置在哪里,就会获取这个类的包名,将指定包下的>所有组件导入进来。@AutoConfigurationPackage注解是指定了默认的包规则,即在该包下的组件>才可以被Springboot扫描后自动装配进IOC容器中。
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先。主要体现在@ConditionalOnMissingBean,如果没有存在这个bean,那么springboot就会自动帮你配置
总结:
● SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
● 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
● 生效的配置类就会给容器中装配很多组件
● 只要容器中有这些组件,相当于这些功能就有了
● 定制化配置
○ 用户直接自己@Bean替换底层的组件
○ 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties
- 引入场景依赖
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter - 查看自动配置了哪些(选做)
自己分析,引入场景对应的自动配置一般都生效了
配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)在application.properties配置文件中新增一行 debug=true,当应用程序运行时,可以在控制台看到哪些组件生效(Positive matches),那些组件不生效(Negative matches) - 是否需要修改
参照文档修改配置项
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
自己分析。xxxxProperties绑定了配置文件的哪些。
自定义加入或者替换组件
@Bean、@Component。。。
自定义器 XXXXXCustomizer;
@Data—帮助生产getset方法和
@ToString—帮助生成ToString方法
@AllArgsConstructor—生成有参构造器
@NoArgsConstructor—生成无参构造方法
@EqualsAndHashCode—生成HashCode方法
log.info(“请求进来了…”);
3. 配置文件yaml语法:
● key: value;kv之间有空格
● 大小写敏感
● 使用缩进表示层级关系
● 缩进不允许使用tab,只允许空格
● 缩进的空格数不重要,只要相同层级的元素左对齐即可
● '#‘表示注释
● 字符串无需加引号,如果要加,’'与""表示字符串内容 会被 转义/不转义
具体例子看语雀文档吧
请求映射是为当前请求找到相应的Handler方法去处理,一般是自己写的方法。把一个Url映射到一个controller方法
1.1 Rest使用@xxxMapping;
Rest风格支持(使用HTTP请求方式动词来表示对资源的 *** 作)
- 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
- 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
- 核心Filter;HiddenHttpMethodFilter
- 用法: 表单method=post,隐藏域 _method=put
SpringBoot中手动开启:
mvc:hiddenmethod:filter:enabled: true 新版本默认开启
扩展:如何把_method 这个名字换成我们自己喜欢的。
新注解@GetMapping();@PostMapping();@PutMapping();@DeleteMapping();
1.2 Rest原理- 表单提交会带上_method=PUT,表单提交才会过filter,表单只能提交post与get两种方式
此处讲解的filter原理,仅针对web端的网页表单提交,因为表单只能GET提交或POST提交。而其他的客户端工具,可以直接发送各种请求方式,因此无需filter做转换。所以,这个filter功能是选择性开启,而不是一定要开启的。
- 请求过来被HiddenHttpMethodFilter拦截
2.1 请求是否正常,并且是POST
2.2 获取到_method的值。
2.3 兼容以下请求;PUT.DELETE.PATCH
2.4 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
2.5 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet—>doDispatch()
2. 普通参数的基本注解 1. 注解
- 找到当前请求使用哪个Handler(Controller的方法)处理
- 而需要使用HandlerMapping来映射到相应的方法
- RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
- 所有的请求映射都在HandlerMapping中
- 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。同样的请求方式,不能有相同的方法处理,简单来说就是方式一样,方法就要唯一
- 如果有就找到这个请求对应的handler, 如果没有就是下一个 HandlerMapping
- SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
@PathVariable(路径变量)、
@RequestHeader(获取请求头)、
@ModelAttribute、
@RequestParam(获取请求参数)、
@MatrixVariable(矩阵变量)、
@CookieValue(获取cookie值)、
@RequestBody
@RequestAttribute(获取request域属性,例如传来的HttpServletRequest)
具体使用可以参考SpringMVC里面
@RestController
public class ParameterTestController {
// car/2/owner/zhangsan
@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){
Map<String,Object> map = new HashMap<>();
// map.put("id",id);
// map.put("name",name);
// map.put("pv",pv);
// map.put("userAgent",userAgent);
// map.put("headers",header);
map.put("age",age);
map.put("inters",inters);
map.put("params",params);
map.put("_ga",_ga);
System.out.println(cookie.getName()+"===>"+cookie.getValue());
return map;
}
@PostMapping("/save")
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;
}
}
2. Servlet API:
WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId
ServletRequestMethodArgumentResolver 能解析以上参数
- 参数解析原理:26个参数解析器,采用循环遍历的方式找对应的参数解析器,(参数解析器完成第一次加载后,会进到缓存中),15个返回值处理器,最常用的返回值类型:ModelAndView, Model, View, ResponseBody
Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
4. 自定义对象参数: 容器 单例模式Bean 默认单例模式,从容器中获取,如果没有则new一个。背后的原理是config类动态代理,动态代理的功能增强,先检查容器中有没有这个实例对象。 如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
5. web场景 1. thymeleaf- 使用th:href="@{/css/style.css}“或者th:src=”@{js/html5shiv.js}"动态绑定资源文件,而且记得加/代表当前项目下的路径
- 记得加xmlns:th=“http://www.thymeleaf.org”
命名空间 - bean的属性名要和表单的name属性一致
- html公共部分抽取 注意include replace insert的区别
- controller里面的数据放入model里面方便thymeleaf在html遍历,添加的是键值对attribute.
- thymeleaf循环语法:
th:each=“当前遍历变量, 变量状态 :待遍历集合”
例如${user,status:users} - ${…}不仅可以用于获取域对象的值,同时可以用于获取普通对象变量的值。
模板引擎在web领域的主要作用:让网站实现界面和数据分离,这样大大提高了开发效率,让代码重用更加容易。
- 引入starter
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
- 自动配置好了thymeleaf
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }
- 自动配好的策略
1、所有thymeleaf的配置值都在 ThymeleafProperties
2、配置好了 SpringTemplateEngine
3、配好了 ThymeleafViewResolver
4、我们只需要直接开发页面
5. ThymeleafViewResolver默认会为视图名称添加前缀和后缀,其中前缀是"classpath:/templates/“;后缀是”.html"。
拦截器得在容器中
- 编写一个拦截器来实现HandlerIntercepter接口
- 拦截器注册到容器中 实现WebMvcConfigurer的addInterceptors
- 指定拦截规则 如果是拦截所有,会拦截静态资源 ,需要单独设置放行静态资源
- 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】
- 先来顺序执行 所有拦截器的 preHandle方法
1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;
- 如果任何一个拦截器返回false。直接跳出不执行目标方法
- 所有拦截器都返回True。执行目标方法
- 倒序执行所有拦截器的postHandle方法。
- 前面的步骤有任何异常都会直接倒序触发 afterCompletion
- 页面成功渲染完成以后,也会倒序触发 afterCompletion
- 调用目标方法前,会顺序执行拦截器链的preHandle()
- 调用完目标方法后,在视图渲染前,会逆序执行调用拦截器链的postHandle()
- 视图渲染完毕后,会调用逆序执行调用拦截器链的afterCompletion()
- 拦截器链的postHandle()只有在所有的preHandle()执行都返回true的情况下才会被执行
- 当拦截器链的preHandle()准备返回false、或在dispatch()中任何一步程序出现异常、或视图成功渲染完毕请求准备返回浏览器时,都会逆序执行调用拦截器链的afterCompletion()。尤其注意,能被调用afterCompletion()的,只有那些preHandle()返回true的拦截器
@PostMapping("/upload")
public String upload(@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestPart("headerImg") MultipartFile headerImg,
@RequestPart("photos") MultipartFile[] photos) throws IOException {
log.info("上传的信息:email={},username={},headerImg={},photos={}",
email,username,headerImg.getSize(),photos.length);
if(!headerImg.isEmpty()){
//保存到文件服务器,OSS服务器
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("H:\\cache\\"+originalFilename));
}
if(photos.length > 0){
for (MultipartFile photo : photos) {
if(!photo.isEmpty()){
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("H:\\cache\\"+originalFilename));
}
}
}
文件上传自动配置原理
文件上传自动配置类-MultipartAutoConfiguration-MultipartProperties
- 自动配置好了 StandardServletMultipartResolver 【文件上传解析器】
- 原理步骤
- 1、请求进来使用文件上传解析器判断(isMultipart)并封装(resolveMultipart,返回MultipartHttpServletRequest)文件上传请求
- 2、参数解析器来解析请求中的文件内容封装成MultipartFile
- 3、将request中文件信息封装为一个Map;MultiValueMap
FileCopyUtils。实现文件流的拷贝
原生就是不会经过DispatcherServlet
@ServletComponentScan(basePackages = “com.atguigu.admin”) :指定原生Servlet组件都放在那里.若不指定basePackages属性,默认是扫描该配置类所属包下的所有内容(包括子包中的内容)。
@WebServlet(urlPatterns = “/my”):效果:直接响应,没有经过Spring的拦截器?
根据精确优先原则,DispatcherServlet处理"/“请求,MyServlet处理”/my"请求,更精确,所以由原生的servlet(Tomcat处理),而只有由DispatcherServlet(Spring)处理的请求才会经过spring的拦截器
@WebFilter(urlPatterns={“/css/“,”/images/”}) Servlet是单*
@WebListener
配置类方法执行顺序:监听器>filter>自定义servlet>dispatchServlet(springMvc)精准匹配情况下
ServletRegistrationBean, FilterRegistrationBean, and ServletListenerRegistrationBean
@Configuration(proxyBeanMethods = true)//保证单实例
public class MyRegistConfig {
@Bean
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my02");
}
@Bean
public FilterRegistrationBean myFilter(){
MyFilter myFilter = new MyFilter();
// return new FilterRegistrationBean(myFilter,myServlet());
//传入方法 实际上会调用其对应的bean
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean myListener(){
MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
return new ServletListenerRegistrationBean(mySwervletContextListener);
}
}
5. 嵌入式Servlet容器
○ SpringBoot应用启动发现当前是Web应用。web场景包-导入tomcat
○ web应用会创建一个web版的ioc容器 ServletWebServerApplicationContext
○ ServletWebServerApplicationContext 启动的时候寻找 ServletWebServerFactory(Servlet 的web服务器工厂—> Servlet 的web服务器)
○ SpringBoot底层默认有很多的WebServer工厂;TomcatServletWebServerFactory, JettyServletWebServerFactory, or UndertowServletWebServerFactory
○ 底层直接会有一个自动配置类。ServletWebServerFactoryAutoConfiguration
○ ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryConfiguration(配置类)
○ ServletWebServerFactoryConfiguration 配置类 根据动态判断系统中到底导入了那个Web服务器的包。(默认是web-starter导入tomcat包),容器中就有 TomcatServletWebServerFactory
○ TomcatServletWebServerFactory 创建出Tomcat服务器并启动;TomcatWebServer 的构造器拥有初始化方法initialize—this.tomcat.start();
○ 内嵌服务器,就是手动把启动服务器的代码调用(tomcat核心jar包存在)
- 首先导入依赖
- 具体依赖分析可以看下源码
数据库驱动?
为什么导JDBC场景,官方不导入驱动?官方不知道我们接下要 *** 作什么数据库。
application.yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/spring5demo1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true&allowPublicKeyRetrieval=true
username: root
password: zwqZWQ,./123
SpringIOC容器将管理数据库连接的数据源当作普通Java Bean一样管理,然后将数据源注入封装类JdbcTemplate中,JdbcTemplate的dataSource属性就是注入配置的数据源
4. druid配置- 一般自动配置都是引入核心starter
- 然后starter调用autoconfigure 来自动加载组件进入容器
- 而组件的自动配置需要引入核心配置文件就是. properties文件 所以大部分情况下需要自己去修改这个文件
- druid作为一个datasource也就是数据库连接池需要配置成bean计入容器,所以是新建一个config类来配置。
- druid监控页配置用到了一个Servlet,Servlet可以被注册到容器中?
- 引入starter
- SqlSessionFactory自动配置好了
- SqlSession:自动配置了 SqlSessionTemplate组合了SqlSession
- @Import({MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class}) 拿写的接口
- Mapper只要我们写的 *** 作MyBatis的接口标注了@Mapper 就会被自动扫描进来
- 表的字段和bean的属性不一致需要开启驼峰命名或者写resultmap
1.导入MyBatis官方Starter。
2. 编写Mapper接口,需@Mapper注解。
3. 编写SQL映射文件(xml文件)并绑定Mapper接口。注意namespace
4. 在application.yaml中指定Mapper配置文件的所处位置,以及指定全局配置文件的信息 建议:配置mybatis.configuration)
5. 调用关系是:实体对象->mapper接口->service层->controller处理请求
6. 简单DAO方法就写在注解上。复杂的就写在配置文件里。
7. 使用@MapperScan(“com.xx.xx.mapper”) 简化,Mapper接口就可以不用标注@Mapper注解。也就是说主启动类标记之后,mapper接口就不用继续标注@Mapper
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml
type-aliases-package: com.atguigu.boot05webadminjam.bean
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath:mybatis/mapper/*.xml
springboot开发的几个问题
- Bean的依赖调用关系?
📔 controller是什么proxyBeanMethods = true 的话 一个user实例会调用一个pet实例,而且唯一。
- 在SpringMVC中,Controller 默认也是单例采用单例模式的最大好处,就是可以在高并发场景下极大地节省内存资源,提高服务抗压能力。
- Controller不是线程安全的,例如使用实例变量会线程共用
- 标上注解之后 被包扫描 加入IOC容器
Spring MVC是基于servlet的,它有一个DispatherServlet,然后它负责处理请求,并且调用了你的controller。controller的前端控制器DispatcherServlet最终是继承了HttpServlet的,只不过springmvc帮助你做好了url和method的映射了(注解实现),不需要你自己在web.xml一个servlet和一个method去配置了
📗什么能被注入到IOC容器@Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
❓️【提问】thymeleaf能获取controller的什么数据- model的数据和request域中数据一样.
- 过HttpServletRequest域对象,因为只有一次请求,所以相同的请求域可以用来存储数据并传输
- ServletContext域(web场景最大的域对象)对象进行数据存储,全局访问
域对象主要用在web应用中,负责存储数据,通俗的讲就是这个对象本身可以存储一定范围内的所有数据,通过它就能获取和存储数据,
可以理解为万能的一个属性,只要调用它就可以获得这个范围(域)内的想要的数据,也可以修改删除数据,当然也可以给这个域添加数据
- getAttribute(String name) 获取对应的数据
- getAttributeNames()获取所有的key
- removeAttribute(String name) 移除对应的数据
- SetAttribute(String name, Object object) 设置数据
- 相较传统开发所普遍采用的“拉”模式,在响应式编程下,基于事件的触发和订阅机制,这就形成了一种类似“推”的工作方式。这种工作方式的优势就在于,生成事件和消费事件的过程是异步执行的,所以线程的生命周期都很短,也就意味着资源之间的竞争关系较少,服务器的响应能力也就越高。
- 流一般是是生产者推给消费者的元素序列,存在一个问题就是消费者处理速度与生产者不匹配,那么就需要流量控制,问题就成为如何设计一个合适的消息队列
- 背压机制 使得消费者可以根据自身当前的处理能力通知生产者来调整生产数据的速度,这种机制就是背压。采用背压机制,消费者会根据自身的处理能力来请求数据,而生产者也会根据消费者的能力来生产数据,从而在两者之间达成一种动态的平衡,确保系统的即时响应性。
一般需要这三个 greeting是具体java代码,starter只有一个pom文件,引用了上面两个文件
- 自动配置 常见的应用功能提供相应的自动配置
- 起步依赖 starter dependence ,需要告诉springboot需要什么库 自动引入需要的依赖库
- 命令行界面 主要针对Groovy语言
- Actuator 深入运行时的springboot程序 查看内部信息
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)