- SpringBoot是整由Spring技术栈的一站式框架
- SpringBoot是简化Spring技术栈的快速开发脚手架
- 1.创建独立的spring应用
- 2.内嵌web服务器
- 3.自动配置spring以及第三方功能
- 4.提供生产级别的监控、健康检查以及外部化配置
- 5.无代码生成,无需编写xml
- jdk:1.8
- Maven:3.8.1
- idea:2021.2
- 使用自己的maven
父项目做依赖管理:
- 1.无需关注版本号,自动仲裁
- 2.可以修改版本号
org.springframework.boot
2.7.14
spring-boot-starter-parent
- 1.只spring-boot-starter-*,表示引入某种场景的依赖
- 2.只要引入starter,这个场景的所有常规依赖都引入了进来
org.springframework.boot
spring-boot-starter-web
@SpringBootApplication:把类标识为主程序类
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
@RestController等价于@Controller+@ResponseBody
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello,SprigBoot";
}
}
直接运行main方法,无需部署
1.默认包扫描规则:主程序所在的包及其下的子包都会被扫描
2.SpringBoot帮我们配置好了所有的web开发的常用场景
3.@SpringBootApplication等同于:
@SpringBootConfiguration、@EnableAutoConfiguration、ComponentScan
4.默认配置最终都是映射到MultipartProperties
- @Configuration:把类标识为配置类,等同于xml配置文件
- @Bean:给容器中添加组件,以方法名作为组件的id;返回类型就是组件的类型,返回值就是组件在容器中的实例
注意:
- 配置类里面使用@Bean标注在方法上给容器注册组件时,默认也是单实例。
- 配置类本身也是组件。
- proxyBeanMethod属性:代理bean方法,默认为true。
- Full(proxyBeanMethod = ture)【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
- Lite(proxyBeanMethod = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
- 配置类组件之间无依赖关系,用Lite模式加速容器启动的过程,减少判断。
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式。
@Configuration(proxyBeanMethods = false)
public class MyConfig {
@Bean
public User user01() {
return new User("张三", "123456");
}
}
给容器自动创建组件,默认组建的名字就是全类名
@Import({User.class})
@Configuration
public class MyConfig {
@Bean
public User user01() {
return new User("张三", "123456");
}
}
引入外部的xml文件
@ImportResource("classpath:bean.xml")
@Configuration
public class MyConfig {
@Bean
public User user01() {
return new User("张三", "123456");
}
}
文件配置绑定:application.propertie和javaban进行绑定
注意:只有在容器中的组件,才会拥有相关功能
与上面作用相似,他作用在配置类上,并且将User这个组件自动注入到容器中
@SpringBootApplication等价于:@SprignBootConfiguration+@EnableAutoConfiguration+@ComponentScan
这个注解封装了@Configruation:标识为一个配置类,说明MainApplication也是个配置类。
@Configuration
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
指定扫描写的包
- 1.@AutoConfigurationPackage
- 2.利用Registrar给容器导入一系列的组件
- 3.将指定的一个包下的所有组件导入进来
- 1.@Import:利用getAutoConfigurationEntry(annotationMetadata)給容器中批量导入一些组件.
- 2.调用List
configurations = 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.
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class>[] exclude() default {};
String[] excludeName() default {};
}
- SpringBoot先加载所有的自动配置类
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件默认的值
- 生效的配置类就会给容器中装配很多组件
- 只要容器中有了这些组件,就相当于这些功能就有了。
- 只要自己配置了,就以自己的优先
- 定制化配置:1.用户直接自己@Bean替换底层的组件;2.用户去看这个组件是获取的配置文件什么值就去修改。
简化javabean开发
org.projectlombok
lombok
- @Data:生成已有属性的get/set方法
- @ToString:生成已有属性的toString方法
- @NoArgsConstructor:无参构造
- @AllArgsConstructor:全参构造
需要指定的构造器方法时也可以自己写~
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
private String password;
public User(String username) {
this.username = username;
}
}
spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署。
好处:提高开发者的开发效率,无需手动重启Spring Boot应用。
org.springframework.boot
spring-boot-devtools
true
说明:ctrl+F9--重启,只要请求路径或类变化,无需重新部署。
注意:Springboot的版本,不然有可能后面会报错!!!
创建完成后,可以将没用的内容删除~
YAML 是 "YAML Ain't Markup Language" (YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是: "Yet Another Markup Language" (仍是一种标记语言)。
- key: value;kv之间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- #表示注释
- ' '与 " "表示字符串内容 会被 转义/不转义
k: v
行内写法: k:{k1:v1,k2:v2,k3:v3}
#或
k:
k1: v1
k2: v2
k3: v3
行内写法: k:【v1,v2,v3】
#或
k:
- v1
- v2
- v3
创建两个实体类
@ConfigurationProperties(prefix = "user")//与配置文件进行绑定
@Component //放到容器中
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
private String pwd;
private String sex;
private Integer age;
private Pet pet;
}
@ConfigurationProperties(prefix = "pet")
@Component
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Pet {
private String pName;
private Integer age;
}
application.yml配置文件
user:
username: jack
pwd: 123
sex: man
age: 18
loves:
- sql
- php
- java
pet:
pName: tom
age: 2
测试
@RestController
public class HelloController {
@Autowired
private User user;
@RequestMapping("/user")
public User user(){
return user;
}
}
结果:
5.4.4注解处理器
之前在yml中没有提示,要想有提示加入下面依赖,然后重启项目
org.springframework.boot
spring-boot-configuration-processor
注意:
这些都是开发小技巧,但是打包的时候不用打包到jar包
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
org.springframework.boot
spring-boot-configuration-processor
- 只要静态资源放在类路径下: called , static , public , resources , META-INF/resources
- 访问:当前根路径+静态资源名
- 原理:静态资源/**.
- 请求进来,先去找Controller,看能不能处理;不能处理的所有请求又都交给静态资源处理器,静态资源找不到就报404
- 默认无前缀
- 配置之后:当前项目+static-path-pattern前缀+资源文件
spring: mvc: static-path-pattern: /res/**
- 静态资源路径下 index.html
- controller能处理/index
注意:可以配置静态资源访问路径,但不可以同时配置静态资源访问前缀,否则导致inde.html不能被默认访问。
- 1.SpringBoot启动默认加载 xxxAutoConfiguration 类(自动配置类)
- 2.SpringMVC功能的的大都数功能都集中在WebMvcAutoConfiguration类中, 根据条件ConditionalOnxxx注册类对象;WebMvcAutoConfiguration满足以下ConditionalOnxxx条件,类是生效的,并把其对象注册到容器中。
@AutoConfiguration(
after = {DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
public class WebMvcAutoConfiguration {
public static final String DEFAULT_PREFIX = "";
public static final String DEFAULT_SUFFIX = "";
public static final PathPatternParser pathPatternParser = new PathPatternParser();
private static final String SERVLET_LOCATION = "/";
WebMvcAutoConfiguration生效给容器中配置了什么呢?
@Configuration( proxyBeanMethods = false ) @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class}) @EnableConfigurationProperties({WebMvcProperties.class, WebProperties.class}) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware { private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class); private final Resources resourceProperties; private final WebMvcProperties mvcProperties; private final ListableBeanFactory beanFactory; private final ObjectProvider
messageConvertersProvider; private final ObjectProvider dispatcherServletPath; private final ObjectProvider > servletRegistrations; private final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; private ServletContext servletContext;
- 配置文件的相关属性和xxx进行了绑定:
- WebMvcProperties==spring.mvc
- ResourceProperties==spring.resources
- WebProperties==spring.web。
配置类只有一个有参构造器:有参构造器所有参数的值都会从容器中找
public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider
messageConvertersProvider, ObjectProvider resourceHandlerRegistrationCustomizerProvider, ObjectProvider dispatcherServletPath, ObjectProvider > servletRegistrations) { this.resourceProperties = webProperties.getResources(); this.mvcProperties = mvcProperties; this.beanFactory = beanFactory; this.messageConvertersProvider = messageConvertersProvider; this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); this.dispatcherServletPath = dispatcherServletPath; this.servletRegistrations = servletRegistrations; this.mvcProperties.checkConfiguration(); }
- ResourceProperties resourceProperties;获取和spring.resources绑定的所有的值的对象
- WebMvcProperties mvcProperties获取和spring.mvc绑定的所有的值的对象
- ListableBeanFactory beanFactory Spring的beanFactory
- HttpMessageConverters 找到所有的HttpMessageConverters6 ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器
- DispatcherServletPath8 //ServletRegistrationBean给应用注册Servlet、FilterI
资源处理的默认规则:
public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); } else { this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); if (this.servletContext != null) { ServletContextResource resource = new ServletContextResource(this.servletContext, "/"); registration.addResourceLocations(new Resource[]{resource}); } }); } }
通过配置add-mapping 禁用所有静态资源
spring: web: resources: add-mappings: false
默认不开起
@Bean @ConditionalOnMissingBean({HiddenHttpMethodFilter.class}) @ConditionalOnProperty( prefix = "spring.mvc.hiddenmethod.filter", name = {"enabled"} ) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); }
手动开启 :
spring: mvc: hiddenmethod: filter: enabled: true
rest原理(表单提交时使用rest的时候)
- 表单提交会带上_method=PUT
- 请求过来被HiddenHttpMethodFilter拦截
- 请求是否正常,并且是POST
- 获取到_method的值。兼容以下请求:PUT,DELETE,PATCH
- 原生request (post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
- 过滤器链放行的时候用wrapper,以后的方法调用getMethod是调用requesWrapper的。
Rest使用客户端工具,如postman直接发送put
测试@PathVarable
、delete即可
通过 @PathVariable :将 请求路径中占位符参数绑定到控制器处理方法的形参中。
测试@PathVarable
@GetMapping("/car/{id}/user/{username}")
public Map getCar(@PathVariable("id") Integer id, @PathVariable("username") String username,) {
Map map = new HashMap<>();
map.put("id", id);
map.put("username", username);
return map;
}
- @RequestBody:用来接收前端传递给后端的json字符串中的数据的(请求体中的数据)
- 使用@RequestBody接收数据时,一般都用POST方式进行提交.
注意:一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam。
@PostMapping("/testPost")
public Map postMethod(@RequestBody String content){
Map map=new HashMap<>();
map.put("content",content);
return map;
}
@RequestAttribute 获取请求域中的值
@GetMapping("/goTo")
public String goToPage(HttpServletRequest request) {
request.setAttribute("msg","小张");
request.setAttribute("code",200);
return "forward:/success";
}
@GetMapping("/success")
@ResponseBody
public Map success(@RequestAttribute("msg") String msg, @RequestAttribute("code") Integer code){
Map map=new HashMap<>();
map.put("msg",msg);
map.put("code",code);
return map;
}
MatrixVariable矩阵变量: /cars/sell;low=34;brand=byd,ben,bm
SpringBoot默认禁用了矩阵变量的功能,需手动设置.
@Configuration(proxyBeanMethods = false)
public class WebConfig {
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//设置为不移除分号后面的内容,矩阵变量生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
}
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//设置为不移除分号后面的内容,矩阵变量生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
测试@MatrixVarable
注意@ResponseBody,响应到浏览器
@ResponseBody
@GetMapping("/cars/{path}")
public Map carsSell(@MatrixVariable("low") Integer low,
@MatrixVariable("brand") List brand,
@PathVariable("path") String path) {
Map map = new HashMap<>();
map.put("low", low);
map.put("brand", brand);
map.put("path", path);
return map;
}
测试@MatrixVarable=====情况二
- 若不指定,默认获取的都是第一个id.
- 通过pathVar属性指定获取的id
@ResponseBody
@RequestMapping("/boss/{bossId}/{empId}")
public Map boss(@MatrixVariable(value = "id", pathVar = "bossId") Integer bossId,
@MatrixVariable(value = "id", pathVar = "empId") Integer empId) {
Map map = new HashMap<>();
map.put("bossId",bossId);
map.put("empId",empId);
return map;
}
视图解析:SpringBoot默认不支持JSP,需要引入第三方模板引擎技术实现页面渲染。
org.springframework.boot
spring-boot-starter-thymeleaf
@AutoConfiguration(
after = {WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class}
)
@EnableConfigurationProperties({ThymeleafProperties.class})
@ConditionalOnClass({TemplateMode.class, SpringTemplateEngine.class})
@Import({ReactiveTemplateEngineConfiguration.class, DefaultTemplateEngineConfiguration.class})
public class ThymeleafAutoConfiguration {
存放在类路径下的templates下,以.html为后缀!!
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
@Controller
public class ViewController {
@RequestMapping("/view")
public String view(Model model){
model.addAttribute("mgs","小张呀");
return "success";
}
}
注意:引入thymeleaf的名称空间
success
public class LoginInterceptor implements HandlerInterceptor {
/**
* 目标方法执行之前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("控制器方法执行前");
return false;
}
/**
* 目标方法执行以后
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("控制器方法执行后");
}
/**
* 页面渲染以后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("视图渲染后");
}
}
指定拦截的规则!!
@Configuration
public class WebConfig {
/**
* 拦截器
*/
@Bean
public WebMvcConfigurer addInterceptors() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")//所有请求都会被拦截,包括静态资源
.excludePathPatterns("/");//放行的请求
}
};
}
通过配置,可以设置上传文件大小:
spring: servlet: multipart: max-file-size: 10MB max-request-size: 100MB
@Controller
public class FormController {
@RequestMapping("/form")
public String form(@RequestPart("photo") MultipartFile photo) throws IOException {
if (!photo.isEmpty()) {
String filename = photo.getOriginalFilename();
photo.transferTo(new File("F:\\" + filename));
}
return "form";
}
}
1.继承httpServlet
2.使用@WebServlet注解
@WebServlet(urlPatterns = "/mv")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("9999");
}
}
@ServletComponentScan:指定原生的Servlet组件放在哪里
@ServletComponentScan(basePackages = "com.xz.demo_03")
@SpringBootApplication
public class Demo03Application {
public static void main(String[] args) {
SpringApplication.run(Demo03Application.class, args);
}
}
自动配置的类:
- DataSourceAutoConfiguration:数据源的自动配置
- 修改数据源相关的配置:spring.datasource
- 数据库连接池的配置,是自己容器中没有DataSource才自动配置的
- 底层配置好的连接池是:HikariDataSource
- DataSourceTransactionManagerAutoConfiguration:事务管理器的自动配置
- JdbcTemplateAutoConfiguration: JdbcTemplate的自动配置,可以来对数据库进行
- crudJndiDataSourceAutoConfiguration: jndi的自动配置
- XADataSourceAutoConfiguration:分布式事务相关的
org.springframework.boot
spring-boot-starter-data-jdbc
导入jdbc场景,但是却没有驱动?需要什么数据库导入什么数据库
mysql
mysql-connector-java
8.0.33
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis
password: 123456
username: root
driver-class-name: com.mysql.cj.jdbc.Driver
com.alibaba
druid-spring-boot-starter
1.2.16
- 扩展配置项 spring.datasource.druid
- DruidSpringAopConfiguration.class,监控SpringBean的;配置项: spring.datasource.druid.aop-patterns
- DruidStatViewServletConfiguration.class,监控页的配置: spring.datasource.druid.stat-view-servlet;默认开启
- DruidWebStatFilterConfiguration.class, web监控配置; spring.datasource.druid.web-stat-filter;默认开启
- DruidFilterConfiguration.class))所有Druid自己filter的配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis
password: 123456
username: root
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
stat-view-servlet:
enabled: true
login-username: admin
login-password: admin
reset-enable: false
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: '*.jsp,*.gif,*.jpg,*.png,*.css,*.ioc,/druid/*'
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.3.1
- 全局配置文件
- SqlSessionFactory: 自动配置好了
- SqlSession:自动配置了 SqlSessionTemplate 组合SqlSession
- @lmport(AutoConfiguredMapperScannerRegistrar.class) ;
- Mapper:只要我们写的操作MyBatis的接口标注@Mapper 就会被自动扫描进来
- 1.导入mybatis官方starter
- 2.编写mapper接口,标注@Mapper注解
- 3.编写sql映射文件并颁定mapper接口
- 4.在application.yml中指定Mapper配置文件的位置,以及全局配置文件的信息
我们可以不写全局配置文件Mybatis-config,所有配置文件的配置全都放在configuration配置项中即可
#配置mybatis
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置,
#映射文件位置
mapper-locations: classpath:mybatis/mapper/*.xml
#指定 mybatis全局配置文件的相关配置
configuration:
#开启驼峰映射
map-underscore-to-camel-case: true
controller:
@Controller
@ResponseBody
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/getAllUser")
public List getUser(){
return userService.getAllUser();
}
}
service:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List getAllUser() {
return userMapper.getAllUser();
}
}
dao:
注意@Mapper注解
@Mapper
public interface UserMapper {
/**
* 查询所有用户
* @return
*/
List getAllUser();
}
映射文件:
controller、service同上
mapper:直接在mapper的方法使用查询类型的注解@Select即可
@Mapper
public interface EmpMapper {
@Select("select * from t_emp")
List getAllEmp();
}
- 简单方法直接使用注解
- 复杂方法的编写mapper.xml进行绑定
- 可以在主程序类上使用@MapperSacn,从而简化mapper接口上的@Mapper注解
@MapperScan("com.xz.mapper")
@SpringBootApplication
public class Demo04Application {
public static void main(String[] args) {
SpringApplication.run(Demo04Application.class, args);
}
}