SpringBoot

本文详细介绍了SpringBoot的基本概念、创建项目的步骤、核心特点,包括自动配置、依赖管理、配置文件、多环境设置,以及与Jackson、Gson和Fastjson的整合。通过实例演示,助您快速上手SpringBoot开发。
摘要由CSDN通过智能技术生成

SpringBoot介绍

SpringBoot是由Pivotal团队研发的,SpringBoot并不是一门新技术,只是将之前常用的Spring,SpringMVC,data-jpa等常用的框架封装到了一起,帮助你隐藏这些框架的整合细节,实现敏捷开发。SpringBoot就是一个工具集。

SpringBoot特点:

  • SpringBoot项目不需要模板化的配置。
  • SpringBoot中整合第三方框架时,只需要导入相应的starter依赖包,就自动整合了。
  • SpringBoot默认只有一个.properties的配置文件,不推荐使用xml,后期会采用.java的文件去编写配置信息。
  • SpringBoot工程在部署时,采用的是jar包的方式,内部自动依赖Tomcat容器,提供了多环境的配置。
  • 后期要学习的微服务框架SpringCloud需要建立在SpringBoot的基础上。

创建SpringBoot项目

选择构建项目的类型

选择构建项目的类型
1587376646848

项目的描述

项目的描述
1587376752337

指定SpringBoot版本和需要的依赖

指定SpringBoot版本和需要的依赖
1587376825501

导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 将上述内容修改为下面的效果 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

编写了Controller

@RestController
public class TestController {

    @GetMapping("/test")
    public String test(){
        return "Hello SpringBoot!";
    }

}

测试

效果
1587377297358

好了一个最简单的spring boot项目就创建好了。

定制Banner

我们在启动Spring Boot项目的时候,在控制台会默认输出一个启动图案,如下:
这里写图片描述
当然,这个图案如果你需要的话是可以自己修改的,修改方式很简单:

1.在src/main/resources下新建一个banner.txt文档

2.通过https://www.bootschool.net/ascii网站生成需要的字符,将字符拷贝到步骤1所创建的txt文档中。

Spring Boot的配置文件

Spring Boot使用一个全局的配置文件application.properties或者application.yml,配置文件放在src/main/resources目录下。

YAML语法

  • k:(空格)v:表示一对键值对(空格必须有);

  • 空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的

字符串:默认不用加上单引号或者双引号;

 # “”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思

 name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi

 # ‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

 name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi

对象、Map:键值对:

friends:
		lastName: zhangsan
		age: 20

行内写法:

friends: {lastName: zhangsan,age: 18}

数组

pets:
 - cat
 - dog
 - pig

行内写法:

pets: [cat,dog,pig]

我们在配置文件中配置的这些属性怎么使用呢?

属性的使用

在变量中通过@Value直接注入就行了,如下:

	@Value(value = "${friends.lastName}")
	private String lastName;
	@Value("${friends.age}")
	private Integer age;

刚刚说的这种方式我们在实际项目中使用的时候工作量略大,因为每个项目要注入的变量的值太多了,这种时候我们可以使用基于类型安全的配置方式,就是将properties属性和一个Bean关联在一起,这样使用起来会更加方便。我么来看看这种方式怎么实现。

@Data
@Component
//prefix是指前缀,location指定要注入文件的位置。
@ConfigurationProperties(prefix = "friends",locations = "classpath:friends.properties")
public class Friends {
    private String lastName;
    private Integer age;
}

为什么指定这样配置它就能生效呢?让我们一起去看看底层实现原理

启动类 @SpringBootApplication

每个spring Boot都有一个启动类XXXApplication,打开启动类可以看到,启动类上有个注解@SpringBootApplication。之所以那些配置能生效,就是因为@SpringBootApplication这个注解在启动的时候自动帮我们做了许多事情。

接下来让我们一起来看看这个@SpringBootApplication注解,帮我们做了哪些事情把。

进入@SpringBootApplication注解,这个注解是个复合注解,里面还包含了其他注解。

@Target({ElementType.TYPE})//表示该注解的作用目标为,类,接口或者枚举
@Retention(RetentionPolicy.RUNTIME)//表示在运行时有效
@Documented//表示它的注解在生成文档的时候会保留下来
@Inherited//如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解
@SpringBootConfiguration//底层是一个@Configuration注解 表示它时一个配置类
@EnableAutoConfiguration
@ComponentScan(              
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

其中有两个注解是比较重要的:

  • @ComponentScan:这个就是扫描注解的意思,默认扫描当前类所在的包及其子包下包含的注解,将@Controller,@Service,@Component,@Repository等注解加载到IOC容器中;

  • @EnableAutoConfiguration:这个注解表明启动自动装配,里面包含连个比较重要的注解@AutoConfigurationPackage和@Import。

img

  • @AutoConfigurationPackage:和@ComponentScan一样,也是将主配置类所在的包及其子包里面的组件扫描到IOC容器中,但是区别是@AutoConfigurationPackage扫描@Enitity、@MapperScan等第三方依赖的注解,@ComponentScan只扫描@Controller,@Service,@Component,@Repository这些常见注解。所以这两个注解扫描的对象是不一样的。

  • @Import(AutoConfigurationImportSelector.class):是自动装配的核心注解,AutoConfigurationImportSelector.class中有个selectImports方法

img

selectImports方法还调用了getCandidateConfigurations方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IlpJWTPA-1631056465454)(C:\Users\Administrator\Desktop\笔记\SpringBoot\Pictures\20200721145641124.png)]

getCandidateConfigurations方法中,我们可以看下断言,说找不到META-INF/spring.factories,由此可见,这个方法是用来找META-INF/spring.factories文件的

img

我们可以定位到这个方法所在的类处于spring-boot-autoconfigure-.jar包中,其中spring.factories文件是一组组的key=value的形式,包含了key为EnableAutoConfiguration的全类名,value是一个AutoConfiguration类名的列表,以逗号分隔。

img

项目启动时,它会找到所有JavaConfig配置类全限定名对应的class,然后将所有自动配置类加载到IOC容器中。

那么这些类是如何获取默认属性值的呢?以ServletWebServerFactoryAutoConfiguration为例,它是Servlet容器的自动配置类

img

该类上开启了@EnableConfigurationProperties(ServerProperties.class)注解,最终找到了ServerProperties类。

img

至此,我们大致可以了解。在全局配置的属性如:server.port等,通过@ConfigurationProperties注解,绑定到对应的XxxxProperties配置实体类上封装为一个bean,然后再通过@EnableConfigurationProperties注解导入到Spring容器中。

多环境配置

在实际开发中一般都会有这三种环境:本地环境(自己),开发环境(团队开发),生产环境(线上)。

在application.yml文件中添加一个配置项:

spring:
  profiles:
    active: 环境名 #指定使用哪一个环境

在resource目录下,创建多个application-环境名.yml文件即可

开发环境 application-dev.yml

server:
  # 项目端口
  port: 8080
  servlet:
  # 项目路径
    context-path: /

生产环境 application-prov.yml

server:
  # 项目端口
  port: 8081
  servlet:
  # 项目路径
    context-path: /

本地环境application-local.yml

server:
  # 项目端口
  port: 8082
  servlet:
  # 项目路径
    context-path: /

SpringBoot常用注解

controller层:

  1. @Controller :用来响应页面,表示当前的类为控制器。
  2. @RestController :是@ResponseBody和@Controller的结合,表明当前类是控制器且返回的是一组数据,不是页面。
  3. @Autowired:引入其他的类,接口。
  4. @RequestMapping:作用:URL映射。访问接口的地址

service层:

  1. @service:用于标注业务层组件

dao层:

  1. @Repository:是用来注解接口,表明该类是用来执行与数据库相关的操作(即dao对象)。

config配置:

  1. 1.@Configuration:表明这是一个配置类。@Configuration注解等价 与xml里面的标签
  2. @Bean:是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名

例如:

@Configuration    
public class ExampleConfiguration {    
		    
   @Value("com.mysql.jdbc.Driver")    
   private String driverClassName;       
   @Value("jdbc://xxxx.xx.xxx/xx")    
   private String driverUrl;    
   
   @Value("${root}")    
   private String driverUsername;    
   
   @Value("123456")    
   private String driverPassword;    
   
   @Bean(name = "dataSource")    
   public DataSource dataSource() {    
       BasicDataSource dataSource = new BasicDataSource();    
       dataSource.setDriverClassName(driverClassName);    
       dataSource.setUrl(driverUrl);    
       dataSource.setUsername(driverUsername);    
       dataSource.setPassword(driverPassword);    
       return dataSource;    
   }    
   
   @Bean    
   public PlatformTransactionManager transactionManager() {    
       return new DataSourceTransactionManager(dataSource());    
   }    
   
		}  

这样,在项目中,这个dataSource就是我们在ExampleConfiguration中配的DataSource。

@Autowired
private DataSource dataSource;

启动类:

  1. @SpringBootApplication:启动注解,这个注解在前面已经讲过了,这里就不赘述了。
  2. @MapperScan(“com.Vm.server”) :扫描指定包中的mapper接口,并注入spring容器。
  3. @EnableScheduling: 开启spring自带的定时服务
public class ScheduledTasks {

   @Scheduled(fixedRate = 1000 * 30) //每30秒执行一次
    public void reportCurrentTime(){
    System.out.println ("Scheduling Tasks Examples: The time is now " + dateFormat().format (new Date ()));
	  }
}

@Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。

静态资源

Spring Boot的静态资源 默认都会存在 resources/static 目录,很多小伙伴也知道静态资源只要放到这个目录下,就可以直接访问,除了这里还有没有其他可以放静态资源的位置呢?为什么放在这里就能直接访问了呢?

静态资源存放的目录

首先,在 Spring Boot 中,默认情况下,一共有5个位置可以放静态资源,五个路径分别是如下5个:

  1. classpath:/META-INF/resources/
  2. classpath:/resources/
  3. classpath:/static/
  4. classpath:/public/
  5. /

系统默认创建了 classpath:/static/ , 正常情况下,我们只需要将我们的静态资源放到这个目录下即可,也不需要额外去创建其他静态资源目录。

如果想要使用其它静态资源目录,就需要自己创建。前四个目录好理解只需要在resources目录下创建对应的包,然后将静态资源放入包中即可访问。第5个 / 是啥意思呢?这里第5个 / 其实就是表示 webapp 目录中的静态资源也不被拦截。

如果同一个文件分别出现在五个目录下,那么优先级也是按照上面列出的顺序。

访问静态资源

现在我们知道了静态资源可以存放在哪些静态目录下,那么如何访问这些静态资源呢?

例如我在 classpath:/static/ 目录下放了一张名为1.png 的图片,那么我的访问路径是:

http://localhost:8080/1.png     #这里大家注意,请求地址中并不需要 static,如果加上了static反而多此一举会报404错误。

很多人会觉得奇怪,为什么不需要添加 static呢?资源明明放在 static 目录下。其实Spring Boot 自动帮我们做了资源路径映射。请求地址如果是 http://localhost:8080/1.png 实际上系统会去 /static/1.png 目录下查找相关的文件。

资源路径映射底层原理

通过上面我们知到Spring Boot 自动帮我们做了资源路径映射,那它是如何实现的呢?

首先我们在 WebMvcAutoConfiguration 类中看到了 addResourceHandlers这个方法

QQ截图20210621100557

addResourceHandlers()调用了两个方法getStaticPathPattern() 和getStaticLocations()方法。

我们进入getStaticPathPattern() 这个方法,发现它最终指向的是WebMvcProperties类的staticPathPattern属性,并在构造器中初始化为**/****

QQ截图20210621101803

我们再进入getStaticLocations()这个方法,发现它最终指向的是Resources类的staticLocations属性,并在构造器中初始化为CLASSPATH_RESOURCE_LOCATIONS。而CLASSPATH_RESOURCE_LOCATIONS中有**”classpath:/META-INF/resources/“, “classpath:/resources/“,”classpath:/static/“, “classpath:/public/“,**

QQ截图20210621102546

这样大伙就知道了为什么Spring Boot 中支持这5个静态资源位置。

自定义配置

如果我们并不想将资源放在系统默认的这五个位置上,也可以自定义静态资源位置和映射,自定义的方式也有两种,可以通过 application.properties 来定义,也可以在 Java 代码中来定义,下面分别来看。

application.properties

在配置文件中定义的方式比较简单,如下:

spring.resources.static-locations=classpath:/
spring.mvc.static-path-pattern=/**

第一行配置表示定义资源位置,第二行配置表示定义请求 URL 规则。以上文的配置为例,如果我们这样定义了,表示可以将静态资源放在 resources目录下的任意地方,我们访问的时候当然也需要写完整的路径,例如在resources/static目录下有一张名为1.png 的图片,那么访问路径就是 http://localhost:8080/static/1.png ,注意此时的static不能省略。

Java 代码定义

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/aaa/");
    }
}

这里代码基本和前面一致,比较简单,不再赘述。

码云地址:https://gitee.com/li-jie-jie/springboot0-study/tree/master

本地项目地址:D:\javalab\MyIDEAJavaSpring-Boot\spring-study\exception

路径映射

一般我们可以通过编写一个controller去跳转到页面。当然现在几乎都是前后端分离项目,页面跳转一般是由前端负责。(所以了解即可)

controller去跳转

@Controller
public class HelloController {
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}

hello.html存放在templates目录下

resource

启动项目访问http://localhost:8081/hello这样我们就可以访问到hello.html这个页面了。

路径映射

有时我们的项目有动态的页面模板,==它并不需要去渲染数据。==但是又不可以直接访问,一般我们可以通过编写一个controller去跳转到这个页面。像这种情况其实我们没有必要去写controller,我们可以直接使用路径映射来访问。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }
}

启动项目访问http://localhost:8081/hello这样我们就可以访问到hello.html这个页面了。

SpringBoot整合json

主要介绍如何在Spring Boot中整合几种常用的JSON方案,主要介绍Spring Boot本身提供和Jackson和GSON,以及另一种比较常用的fastjson的整合。

1. SpringBoot整合Jackson

Jackson是Spring Boot中默认的,所以我们不需要导入额外的依赖,只需要导入spring-boot-starter-web就可以使用了。

依赖

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
json01

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String address;
}

controller测试

@RestController()
@RequestMapping("/json")
public class UserController {
    @GetMapping("/jackson")
    private List<User> jacksonTest() {
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            users.add(new User(i, "Jackson" + i, "杭州"));
        }
        return users;
    }
}

启动项目效果:

jackson02

真正在项目中不仅仅是返回json还有上传json,不管是是上传json还是返回json都需要用到HttpMessageConverter。但是我们发现上面我们压根就没有用到HttpMessageConverter,这是因为spring mvc自动配置了jackson和gson的HttpMessageConverter 而spring boot又做了自动化配置。

HttpMessageConverter的作用主要有两个:1.将前端传过来的json字符串反序列化为java对象,2.将后端返回的java对象序列化为json字符串。下面我们对他们进行简单的使用

实体类增加birthday属性:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String address;
    private Date Birthday;
}

修改controller

@RestController()
@RequestMapping("/json")
public class UserController {
    @GetMapping("/jackson")
    public List<User> jacksonTest() {
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            users.add(new User(i, "Jackson" + i, "杭州",new Date()));
        }
        return users;
    }
}

运行效果:

jackson03

我们可以看到时间的格式都是:2021-04-26T05:58:21.497+00:00样的,有时我们不想要这种时间格式。

通过注解@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”)修改时间格式

修改实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String address;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date Birthday;
}

运行效果

jackson04

这样更方便更灵活,但是这样有个不好的地方,就是所有实体类的时间我们都要去给它加上注解。有没有统一的方法呢?

那就需要我们自己定义HttpMessageConverter来给所有的时间统一格式化。

去掉实体类的注解,自定义HttpMessageConverter

@Configuration
public class WebMvcConfig {
    @Bean
    MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter= new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        converter.setObjectMapper(objectMapper);
        return converter;
    }
}

设置时间格式实在ObjectMapper中设置的,那么我们可不可以只提供一个ObjectMapper呢?答案是可以的。

修改WebMvcConfig

@Configuration
public class WebMvcConfig {
     @Bean
    ObjectMapper objectMapper() {
        return new ObjectMapper().setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }
}

2. Spring Boot 整合GSON

GSON也是Spring Boot中提供了自动化配置的,我们需要排除Jackson的依赖并引入GSON依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-json</artifactId>
            </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

实体类和controller和jackson一样,

运行效果:

gson01

自定义HttpMessageConverter

@Configuration
public class WebMvcConfig {
    @Bean
    public GsonHttpMessageConverter gsonHttpMessageConverter() {
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        converter.setGson(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create());
        return converter;
    }
}

同样我们可以只提供一个Gson

@Configuration
public class WebMvcConfig {
    @Bean
    Gson gson(){
        return new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
    }
}

3. SpringBoot整合fastjson

Spring Boot 中并没有提供fastjson的默认支持,所以我们需要自行导入依赖,

   <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>

必须配置FastJsonHttpMessageConverter

@Configuration
public class WebMvcConfig {
@Bean
FastJsonHttpMessageConverter fastJsonHttpMessageConverter(){
    FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
    FastJsonConfig config = new FastJsonConfig();
    config.setDateFormat("yyyy-MM-dd HH:mm:ss");
    // 处理中文乱码问题
    List<MediaType> fastMediaTypes = new ArrayList<>();
    fastMediaTypes.add(MediaType.APPLICATION_JSON);
    converter.setSupportedMediaTypes(fastMediaTypes);
    converter.setFastJsonConfig(config);
    return converter;
}
}

SpringBoot 类型转换器

有时前端会传一下日期给后端,后端直接接受是会报错的。那么后端如何用一个日期对象来接受他呢?

package cn.itxiaoliu;

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

import java.util.Date;

@RestController
public class UserController {
    @GetMapping("/hello")
    public void hello(Date birth){
        System.out.println(birth);
    }
}


启动项目,访问:http://localhost:8081/date?birth=1996-06-14

此时会出现参数类型错误

convert

再新建DateConverter.java

@Component
public class DateConverter implements Converter<String, Date> {
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
    @Override
    public Date convert(String source) {
        if(source!=null&&!"".equals(source)){
            try {
                return sdf.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }
        return null;
    }
}

启动项目,访问:http://localhost:8081/date?birth=1996-06-14

converter

成功

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值