Spring boot 笔记

Spring Boot

(后面有时间再更新吧)

spring boot 入门篇

一、spring boot >hello spring

1、导入spring boot 需要得依赖
<!--
  导入spring boot 为父项目
  -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.10</version>
    </parent>


<!--   导入spring boot 场景启动器    -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

构建应用程序主要入口:

@SpringBootApplication
/*
*
* @SpringBootApplication: 标注为该程序是spring boot程序
* */
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }
}

创建控制器(web 逻辑)

@RestController
/*
 @Controller
 @ResponseBody
* @RestController: 是@Controller和@ResponseBody结合体

声明这个类是一个控制器类并且这个类只会返回字符信息给浏览器
* */
public class messageHandle {
    @RequestMapping("/hello")
    public String handle01() {
           return "hello spring boot 2!";
    }
}

spring boot 配置简化

在资源路径下创建 application.properties(固定名称)

即可(该配置文件可以配置sprng mvc以及tomcat等等)

server.port=8000 //修改tomcat端口

spring boot 部署 导出为可执行jar包

<!--  放在dependencies中导入
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
           <version>2.5.1</version>
       </dependency>-->
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


也可在放在dependencies中导入
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
           <version>2.5.1</version>
       </dependency>

后在maven管理中选中生命周期下得clean 与package 运行打包即可

找到jar包后 cmd窗口运行 java -jar 名字.jar

注意点 springboot 打包后jar包很多 所以体积较大

二、自动配置原理

1、依赖管理:在依赖管理中spring boot 得父项目中构建了大量常用的依赖版本 所以在导入依赖时无需关心版本

如果想要自定义自己的需要的依赖版本 需要在maven 文件中创建

<properties>
<mysql.version>需要的版本好</mysql.version>
</properties>

2、场景启动

spring-boot-start-* 代表某个场景的启动器

比如spring-boot-start-web 将会把web所需要的启动场景全部引入

spring-boot 所有能支持的场景 在官网中

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

   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.5.10</version>
      <scope>compile</scope>
    </dependency>

因为springboot 自动配置帮我们指定了一个包扫描 所以我们无需指定包的扫描路径

自己指定可以采用

@SpringBootApplication(basePackages="自定义包名")


同时也可以将@SpringBootApplication(basePackages="自定义包名")改为
    
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("包名")  
三、底层注解 详解
1、@Configuration
package org.Dwx.boot.config;

import org.Dwx.boot.bean.Pet;
import org.Dwx.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
/*
告诉spring boot 这是一个配置组件
*/
public class MyConfig {
    @Bean
    /*
    告诉spring 这个是一个<bean>  bean的id就是方法名  返回类型就是<bean>的
    */
    public User userVip (){
        return  new User("zhansan",18);
    }
    @Bean
    /*
    * 也可以自定义组件名
    *
    * @Bean("name")
    * */
    public Pet tomcat(){
        return  new Pet("Tomcat");
    }
}

如果 @Configuration(proxyBeanMethods=true时)

spring 启动代理对象我们每次从spring容器中获取的对象都是单实例 所以不管获取多少次 对象都是同一个

如果 @Configuration(proxyBeanMethods=false时)

不启动代理将返回单独的对象

2、@import({User.class…})

可以给容器中导入多个组件

容器自动创建出这两个类型的组件

3、 @Conditional 条件装配 满足Conditional 指定条件则进行组件注入

run.contaunsBean(“”) 判断容器中是否存在容器中

4、@ImportResource(“classpath:*.xml”)

将beans文件中的bean添加到容器中

5、配置绑定

方法一:

@Compoent // 注入到ioc容器

@ConfigurationProperties(prefix=“前缀”)

@Autowired
Car car;
@RequestMapping("/car")
public Car car(){
    return car;
}

方法二

@EnableConfigurationProperties(Car.class)
//开启的组件配置绑定功能
//把car组件自动注入ioc
@ConfigurationProperties(prefix="前缀")


@RequestMapping("/car")
public Car car(){
    return car;
}
四、自动配置原理剖析

关键注解:

@SpringBootConfiguration   //告诉spring 这个是一个配置类
@EnableAutoConfiguration
@ComponentScan   //指定包扫描

@EnableAutoConfiguration

  • @AutoConfigurationPackage 将指定包下的所有组件全部导入ioc(main程序所在包)

    • @Import({Registrar.class}) //利用 registrar 导入一系列组件
  • AutoConfigurationImportSelector.class

    • this.getAutoConfigurationEntry(annotationMetadata); 利用该方法到一系列组件

      • this.getCandidateConfigurations(annotationMetadata, attributes);
      • 利用他来获取所有需要导入到容器的配置组件
      • SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
      • 使用spring的工厂加载器加载组件
      • 利用工厂加载 Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
      • 从META-INF/spring.factories位置来加载一个文件。
        默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
        spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
      • 文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
        spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
      • Auto Configure 的127个配置项 最后也会按需加载
      • 最后根据按需装配 导入场景需要的组件
五、修改默认配置

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

使用@Bean 导入用户所配置的组件即可

总结:

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

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

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

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

  • 定制化配置

    • 用户直接自己@Bean替换底层的组件
    • 用户去看这个组件是获取的配置文件什么值就去修改。

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

六、最佳实践

打开debug模式将会开启自动配置报告 negative 不生效的 / positive 生效的

参照文档修改配置项

案例修改banner 图 spring.banner.image.loacation=资源路径下的图片

自定义加入组件或替换组件

使用@Bean @Compent

自定义器 XXXXCustomizer;

开发小技巧

lombok 插件:

1、导入lombok依赖

  <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

2、安装插件

idea 搜索lombok

3、使用

在实体上@Data 生产get set@toString @AllArgsConstructor @NolArgsConstructor

源代码不会有相应的代码生成 在字节码文件中是存在的

@Slf4j 日志记录

dev-tools 插件
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

ctrl+F9 使项目重编译(快捷重启)

使用热更新 安装JRebel

spring initaillzr

快速创建spring boot 引用

springboot2 核心功能

1、配置文件
1、yaml配置

YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。

语法:

  • key: value;kv之间有空格

  • 大小写敏感

  • 使用缩进表示层级关系

  • 缩进不允许使用tab,只允许空格

  • 缩进的空格数不重要,只要相同层级的元素左对齐即可

  • '#'表示注释

  • 字符串无需加引号,如果要加,''与""表示字符串内容 会被 转义/不转义

  • 字面量:单个的、不可再分的值。date、boolean、string、number、null

  • k: v
    

    ●对象:键值对的集合。map、hash、set、object

    YAML

    复制代码

    1

    行内写法:  k: {k1:v1,k2:v2,k3:v3}
    

    2

    #或
    

    3

    k: 
    

    4

      k1: v1
    

    5

      k2: v2
    

    6

      k3: v3
    

    ●数组:一组按次序排列的值。array、list、queue

    YAML

    复制代码

    行内写法:  k: [v1,v2,v3]
    
    #或者
    
    k:
    
     - v1
    
     - v2
    
     - v3
    

样例:

# 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}]
2、web文件开发

1、静态资源目录 类路径下 /static or /public or /resource /META-INF/resource

​ 只要资源放在静态资源目录下就可访问到

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

原理:静态映射/**

请求进来,先找动态资源看能不能处理。不能处理的所有请求又交给静态资源处理器。静态资源处理器也无法处理 就返回404页面

静态资源访问前缀:默认无

配置修改

spring
  mvc:
    static-path-pattern:/res/**
    //静态资源放行规则
    
    //配置静态资源路径
    spring:
  mvc:
    static-path-pattern: /res/**

  resources:
    static-locations: [classpath:/haha/]

webJARS 把常用的静态文件做成jar包 导入以后会自动映射

2、欢迎页设置

在静态资源路径下 index.html

spring
  mvc:
    static-path-pattern:/res/**
    
    会导致静态资源失效(html)

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

动态下路由为index 所返回的欢迎页

3、自定义Favicon (网站icon )

放在静态资源中 命名为favicon.ico

4、静态配置原理

  • springboot启动默认加载 自动配置类
  • springMVC功能自动配置 WebMvcAutoCon…
3、请求参数处理

采用Rest风格

/user get 获取用户 delete 删除用户 put修改用户 post 保存用户

核心Filter;HiddenHttpMethodFilter(拦截器)

  • 用法 表单method=post,隐藏域 _method=put

  • 手动开启

    spring:
    mvc:
    hiddenmethod:
    filter:
    enabled: true #开启页面表单的Rest功能

    Rest原理:

    • 表单提交一个 name=”_method“ value=”PUT“

    • 请求发送到服务器后被HiddenHttpMethodFilter拦截

      关键点

      • 获取到_method的值

      • 兼容 PUT,DELETE,PATCH

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

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

2、请求映射原理

​ 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;
	}
普通参数 与基本注解

1、注解

@PathVariable、 获取路径变量

   @RequestMapping("/User/{id}/{username}")
    public Map<String, Object> handle01(@PathVariable Integer id,
                                        @PathVariable String username,
                                        @PathVariable Map<String, String> hash ){
        Map<String, Object> map = new HashMap<>();
        map.put("id",id);
        map.put("username",username);
        map.put("hash",hash);
        return map;
    }

@RequestHeader、获取请求头

  @RequestMapping("getHeard")
      public Map<String, Object> handle02(@RequestHeader("User-Agent") String userAgent,
                                          @RequestHeader Map<String,String> headers){
        Map<String, Object> map = new HashMap<>();
                     map.put("User-Agent",userAgent);
                     map.put("headers",headers);
        return map;
    }

@RequestParam、获取请求参数

 @RequestMapping("getUser")
    public String handle03(@RequestParam String username){
        return username;
    }
/*
自动封装数组以及对象
*/

@CookieValue、 获取cookie的值

 @RequestMapping("getCookie")
    public Map<String, Object> handle03(@CookieValue("_ga") String value,
                           @CookieValue("_ga") Cookie c
                           ){
        Map<String, Object> Map = new HashMap<>();
            Map.put("_ga",value);
            Map.put("cookie",c);
        return  Map;
    }

@RequestBody 获取请求体(只有post才有请求体)

@MatrixVariable、 矩阵变量 (key=value;key=value;…)

   @RequestMapping("/cars/{path}")
    public Map Test01(@MatrixVariable("low") String low,
                      @MatrixVariable("price") String price,
                      @MatrixVariable("list") List<String> list,
                      @PathVariable("path") String path
                      ){
        HashMap<String, Object> hashMap = new HashMap<>();
         hashMap.put("low",low);
         hashMap.put("price",price);
         hashMap.put("list",list);
         hashMap.put("path",path);
        return hashMap;
    }



@GetMapping("boos/{boosId}/{emId}")
    public Map Test02(@MatrixVariable(value = "age",pathVar = "boosId") Integer boos,
                      @MatrixVariable(value = "age",pathVar = "emId") Integer em){
        HashMap<String, Object> hashMap = new HashMap<>();
                    hashMap.put("boos",boos);
                    hashMap.put("em",em);
        return hashMap;
    }


配置类
        @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return  new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
    }

@ModelAttribute、

@RequestAttritbut 获取Attritbute域中的值

    @GetMapping("/gotoPage")
    public String goToPage(HttpServletRequest request){
        request.setAttribute("msg","我们都是好孩子---王菲");
        request.setAttribute("code",200);
        return "forward:success";
    }

    @ResponseBody
    @GetMapping("/success")
    public Map<String,Object> showData(@RequestAttribute("msg") String msg, @RequestAttribute("code") Integer code,HttpServletRequest httpServlet ){
        Map<String, Object> string = new HashMap<>();
        string.put("msg",msg);
        string.put("code",code);
        string.put("__attribute",httpServlet.getAttribute("msg"));
        return  string;
    }

2、POJO封装过程

3、参数处理

  • handlerMapping中找到处理请求的Handler

  • 为当前Handler找一个适配器HandlerAdapt

  • 适配器执行目标方法并确定方法参数的每一个值

    1、HandlerAdapter

    0-支持方法上标注@RequestMapping

    1-支持函数式编程的

    xxxxxx

    2、执行目标方法

    // Actually invoke the handler.
    //DispatcherServlet -- doDispatch
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    
    mav = invokeHandlerMethod(request, response, handlerMethod); //执行目标方法
    
    
    //ServletInvocableHandlerMethod
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    //获取方法的参数值
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    
    

    3、参数解析器

    确定将要执行的目标方法的每一个参数值是什么

    SpringMVC 目标方法能写多少个参数

    image.png

  • 当前解析器是否支持解析这种参数

  • 支持就调用 resolveArgument

    4、返回值处理器

    image.png

5、视图解析

1、thymeleaf简介

Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.

现代化、服务端Java模板引擎

2、基本语法

1、表达式
表达式名字语法用途
变量取值${…}获取请求域、session域、对象等值
选择变量*{…}获取上下文对象值
消息#{…}获取国际化等值
链接@{…}生成链接
片段表达式~{…}jsp:include 作用,引入公共页面片段
2、字面量

文本值: ‘one text’ , ‘Another one!’ **,…**数字: 0 , 34 , 3.0 , 12.3 **,…**布尔值: true , false

空值: null

变量: one,two,… 变量不能有空格

3、文本操作

字符串拼接: +

变量替换: |The name is ${name}|

4、数学运算

运算符: + , - , * , / , %

5、布尔运算

运算符: and , or

一元运算: ! , not

6、比较运算

比较: > , < , >= , <= ( gt , lt , ge , le **)**等式: == , != ( eq , ne )

7、条件运算

If-then: (if) ? (then)

If-then-else: (if) ? (then) : (else)

Default: (value) ?: (defaultvalue)

8、特殊操作

无操作: _

3、设置属性值-th:attr

设置单个值

<form action="subscribe.html" th:attr="action=@{/subscribe}">

  <fieldset>

    <input type="text" name="email" />

    <input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>

  </fieldset>

</form>

设置多个值

<img src="../../images/gtvglogo.png"  th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

以上两个的代替写法 th:xxxx

<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>

<form action="subscribe.html" th:action="@{/subscribe}">

所有h5兼容的标签写法

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes

4、迭代

<tr th:each="prod : ${prods}">

        <td th:text="${prod.name}">Onions</td>
        <td th:text="${prod.price}">2.41</td>

        <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>

</tr>
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">

  <td th:text="${prod.name}">Onions</td>
  <td th:text="${prod.price}">2.41</td>

  <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>

</tr>

5、条件运算

<a href="comments.html"

th:href="@{/product/comments(prodId=${prod.id})}"

th:if="${not #lists.isEmpty(prod.comments)}">view</a>
<div th:switch="${user.role}">

  <p th:case="'admin'">User is an administrator</p>

  <p th:case="#{roles.manager}">User is a manager</p>

  <p th:case="*">User is some other thing</p>

</div>

6、属性优先级

Order

Feature

AttrIbutes

Fragmentinclusion

th:insert

th:replace

Fragmentiteration

th:each

Conditionalevaluation

th:if

th:unless

th:switch

butes

th:case

th:object

Localvariabledefinition

th:with

Generalattributemodification

th:attr

th:attrorepend

th:attrappend

Specificattributemodification

th:value

th:href

th:src

Text(tagbodymodification)

th:text

th:utext

Fragmentspecification

th:fragment

Fragmentremoval

th:remove

image.png

3、thymeleaf使用

1、引入Starter

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>

        </dependency>

2、自动配置好了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、我们只需要直接开发页面

    public static final String DEFAULT_PREFIX = "classpath:/templates/";

    public static final String DEFAULT_SUFFIX = ".html";  //xxx.html

3、页面开发

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 th:text="${msg}">哈哈</h1>
<h2>
    <a href="www.atguigu.com" th:href="${link}">去百度</a>  <br/>
    <a href="www.atguigu.com" th:href="@{link}">去百度2</a>
    </h2>
</body>
</html>
3、数据访问
4、单元测试
  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值