Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

20191022

开始学习Spring Boot,参考了一些博文,列出以下注意项

jdk 1.8 spring boot 2.2 IDEA Community版本

Tip1:如何新建一个Spring boot项目

  • 借助 https://start.spring.io/ 官网的Spring Initializr新建

    • 选中 Spring Web 依赖
    • 下载后导入Maven即可

    点击IDEA File --> New --> Project from Existing Sources... --> 选择你解压后的项目文件夹目录 --> 点击Ok --> 选择Import project from external model --> 选中Maven --> 一路点击Next直到项目导入成功

  • 借助IDEA新建

和有些博客不同的是,依赖项选择Spring Web(版本更新,所以名字也变了)

其实可以直接创建Maven项目,只要配置好pom.xml就行了。从上面创建的项目下POM中可以看出添加了以下项:

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

引入了一个名为spring-boot-starter-parent的父项目,里面包含了常用的依赖和合适版本

<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>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

两个依赖,主要是spring-boot-starter-web这个web启动器(Strater),具体是啥我还不太清楚(待我先过一遍再来补充),看着应该是包含Spring MVC、RESTful和tomcat。另一个应该是测试相关的依赖吧

看到有地方说,Spring Boot就是把一些应用场景提取出来写成一个个启动器,项目需要哪些场景/功能就引入哪些启动器,也就引入了对应依赖

Tip2:社区版的IDEA缺少Springboot初始化的插件

如图,缺少箭头所指的这个选项,解决办法如下:

  • 进入Settings项(Ctrl+Alter+S
  • 如下图安装Spring Assistant插件,重启即可,然后新建项目就能看到上图所示的选项了

running。。。

先写一个Controller类,如图新建一个包controller,然后定义一个hello的类

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

@RestController
public class hello {
    @RequestMapping(value = "hello/")
    public String Hello() {
        return "Hello SpringBoot";
    }
}

今天看到@RestController是@Controller 和 @ResponseBody的组合注解

运行上图的SpringDemoApplication类的main方法,然后在浏览器访问 localhost:8080/hello/ (默认是8080端口)

Tip3:配置文件和如何添加并获取系统配置

下图中的application.properties文件就是全局配置文件,用来改变Spring Boot中的默认配置项,命名是application(默认)。除此之外,还有application.yml这种格式的配置文件

创建application.properties文件时,会根据不同环境创建application-dev.properties、application-test.properties、application-prod.properties三个配置文件分别用于开发、测试、线上正式运行环境的配置,而application.properties适合任何环境。如果你想测试并读取application-test.properties文件中的配置,只需要在全局配置文件中配置spring.profiles.active=test,同理开发环境就是设成dev

要是部署在服务器上运行打包的jar,可以通过参数设置java -jar XXX.jar --spring.profiles.active=test读取application-test.properties文件中的配置

还有一种是在代码中指定读取哪个配置文件,即在启动类的main方法中改成如下:

public static void main(String[] args) {
		SpringApplicationBuilder builder = new SpringApplicationBuilder(QuickStartDemoApplication.class);
		builder.application().setAdditionalProfiles("dev");// dev表示读取开发环境的配置文件
		builder.run(args);
		//SpringApplication.run(QuickStartDemoApplication.class, args);
	}

java -jar可以通过--spring.config.name=xxx参数指定配置文件的名字,--spring.config.location=xxx指定配置文件的位置

比如说要配置运行环境的ip地址和端口号,我这里没有额外的ip,所以只改变端口号。在application.properties中设置

server.ip=127.0.0.1
server.port=8081
...

一样在Controller控制类中写一个获取当前运行环境的IP地址和端口号的方法,运行后在浏览器可查看(注意端口是8081)

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class hello {
    @Value("${server.ip}")
    public String serverIp;
    @Value("${server.port}")
    public String serverPort;
    
    @RequestMapping(value = "/getip")
    public String getServerIp() {
        return serverIp+":"+serverPort;
    }
}

从上面代码可知,可以通过@Value("${xxx}")这个注解获取配置文件中的值

还有一种把配置赋值给一个javabean的写法,现在还不懂javabean是啥,以后再看吧~~~

20191023

Tip1:配置文件中的属性值注入Java Bean对象

这部分是承接昨天的内容,也就是上面通过@Value注解把配置文件中的值注入bean中。还有另一种方法,通过@ConfigurationProperties注解,这个不同于@Value将属性值一个一个绑定,是类型安全的,适合将批量的配置文件中的数据一一映射到bean中

先看下配置文件怎么个写法:

server.ip=xxx
server.port=8081
...
@Component
@ConfigurationProperties(prefix = "server")
public class ServerProperties{
  private String ip;
  private String port;
  //...
}
  • prefix值是要加载的配置的前缀
  • bean类中的属性名要和配置中属性名对应,但不是很严格,比如port可以对应PORT、po-rt等

Tip2:配置文件的优先级

如图,配置文件(.properties/.yml)的加载位置可以是图中四个地方,数字1代表最高优先级。这里的优先级指的是,如果4个地方的配置文件中都有相同属性值,则1处属性值会覆盖掉其他文件对应的属性值。

Tip3:yaml配置文件的写法

引入的spring-boot-starter-web 依赖间接地引入了 snakeyaml 依赖, snakeyaml 会实现对 yaml 配置的解析。看到很多博客都专门讲了yaml文件的配置,我看了下,确实比properties文件写法简单,省略了很多相同前缀的书写。但是无法使用 @PropertySource 注解加载 yaml 文件

??????????????? 留白待续

Tip4:日志相关

  • Spring Boot支持的日志工具

Logback、Java Util Logging、Log4J2

默认情况下使用Logback作为日志记录工具,会记录ERROR、WARN和INFO级别的日志信息,输出到控制台 ERROR、WARN、INFO这些是日志级别,其次还有DEBUG 和 TRACE。可以设置debug=truetrace=true来开启记录DEBUG、TRACE级别的日志(有啥用不清楚)

  • 配置日志输出到文件

在application.properties中配置logging.file或者logging.path,前者指定日志文件输出到某文件,比如logging.file=logs.log,可以是相对/绝对路径;后者指定输出到某目录下,其下会有spring.log输出,比如logging.path=logs

还有就是二者同时设置,只有logging.file会生效

默认情况下使用Logback记录日志,日志文件大小超过10MB后,日志文件将会被打包成.gz的压缩文件,且压缩文件名称会依时间排序累加。使用Logback时可以通过logging.file.max-size设置文件最大多大,单位是kb、mb、gb。而且日志文件会不断累积,可以设置logging.file.max-history限制历史日志最多多大


大概就这些吧,日志这部分现在还不太作要求 参考:https://blog.csdn.net/qq_24871519/article/details/82194372 ,还涉及了自定义日志配置啥的

20191024

Tip1:静态资源的访问

发现一个神坑,Spring Boot 1.x 对静态资源(图片、js、css代码等)有默认要求:

提供静态资源目录位置需置于classpath(resources目录)下,目录名需符合如下规则:
classpath:/static
classpath:/public
classpath:/resources
classpath:/META-INF/resources

比如说classpath(resource目录)下的static目录下有test.png,则可直接通过localhost:8080/test.png访问 以上对于Spring Boot 2.x没用了,但是网上还是一堆复制粘贴的文章这样写,csdn尤其是。

Spring Boot 2.x版本实现方法:

搜到了两种解决办法,方法一没试通过,但也列在这吧

# application.properties中设置
# 也可以是/public/**
spring.mvc.static-path-pattern=/static/**

方法二 这里说下我查到的原因,spring boot 2.x静态资源会被HandlerInterceptor拦截,因为spring boot 2.x采用的是spring 5.x,会对静态资源拦截

package com.springBootExample.quickStartDemo;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     * 添加静态资源文件,外部可以直接访问地址
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
}

这两函数从源码看都是可变长参数,所以可以设置多个目录来区别哪里放图片哪里放js代码等,如registry.addResourceHandler("/public/**","/static/**").addResourceLocations("classpath:/public/","classpath:/static/");

  /**
	 * Add a resource handler for serving static resources based on the specified URL path patterns.
	 * The handler will be invoked for every incoming request that matches to one of the specified
	 * path patterns.
	 * <p>Patterns like {@code "/static/**"} or {@code "/css/{filename:\\w+\\.css}"} are allowed.
	 * See {@link org.springframework.util.AntPathMatcher} for more details on the syntax.
	 * @return a {@link ResourceHandlerRegistration} to use to further configure the
	 * registered resource handler
	 */
	public ResourceHandlerRegistration addResourceHandler(String... pathPatterns) {
		ResourceHandlerRegistration registration = new ResourceHandlerRegistration(pathPatterns);
		this.registrations.add(registration);
		return registration;
	}

  /**
	 * Add one or more resource locations from which to serve static content.
	 * Each location must point to a valid directory. Multiple locations may
	 * be specified as a comma-separated list, and the locations will be checked
	 * for a given resource in the order specified.
	 * <p>For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}}
	 * allows resources to be served both from the web application root and
	 * from any JAR on the classpath that contains a
	 * {@code /META-INF/public-web-resources/} directory, with resources in the
	 * web application root taking precedence.
	 * <p>For {@link org.springframework.core.io.UrlResource URL-based resources}
	 * (e.g. files, HTTP URLs, etc) this method supports a special prefix to
	 * indicate the charset associated with the URL so that relative paths
	 * appended to it can be encoded correctly, e.g.
	 * {@code [charset=Windows-31J]https://example.org/path}.
	 * @return the same {@link ResourceHandlerRegistration} instance, for
	 * chained method invocation
	 */
	public ResourceHandlerRegistration addResourceLocations(String... resourceLocations) {
		this.locationValues.addAll(Arrays.asList(resourceLocations));
		return this;
	}

参考:

20191027

Tip1:模版引擎???

看别人写的博客中谈到了一个叫thymeleaf的模板引擎,查了一番,发现好像就是一个在前后端不分离的情况下数据渲染的工具吧。有查到一个概念——前后端分离,通过vue.js+SpringBoot作前后端分离,通过fetch ,ajax等异步请求java封装的数据接口。高内聚低耦合,想想还是前后端分离一切组件化更优秀,所以模版引擎只是简单看一下

Thymeleaf模版引擎,官方推荐的视图层模板引擎,提供了对Thymeleaf的自动化配置解决方案。需要在pom中添加该依赖,如下:

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

以下是ThymeleafProperties配置类部分源码

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

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

	public static final String DEFAULT_SUFFIX = ".html";

	/**
	 * Whether to check that the template exists before rendering it.
	 */
	private boolean checkTemplate = true;

	/**
	 * Whether to check that the templates location exists.
	 */
	private boolean checkTemplateLocation = true;

	/**
	 * Prefix that gets prepended to view names when building a URL.
	 */
	private String prefix = DEFAULT_PREFIX;
  //...
}

下图是类中几个属性的默认值,可以在application.properties中通过前缀spring.thymeleaf.xxx自定义配置

属性 默认值 含义
checkTemplate true 注册前是否检测模版存在
checkTemplateLocation true 是否检测模版存在
prefix classpath:/templates/ 模版位置
suffix .html 后缀
mode HTML 模版模型
encoding StandardCharsets.UTF_8 文件编码
cache true 模版是否缓存

Tip2:以json格式向前端返回数据

首先json格式是比较通用的传输数据方式,之前用django时也是用的这个。其次,Spring MVC提供了一个json格式转换的消息转换器(HttpMessageConverter)——jackson-databind。然后也可以使用第三方的fastjsonGson 处理器,fastjson是阿里开源的json处理工具,据说目前是解析json最快的工具,所以这里也看一下

  • jackson-databind的使用
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

上面是这个包的依赖,但spring-boot-starter-web该依赖中默认带了jackson-databind作为json处理工具的,所以也就不用在pom中写入 在搜索jackson这个包的用法时,看到了有关的一些注解:@JsonProperty、@JsonIgnore、@JsonFormat 用法说明

注解 用法
@JsonIgnore 用在属性或方法上,序列化时忽略该属性,也就是生成的json没有该属性
@JsonFormat 用在属性或方法上,用来格式化,像格式化日期属性
@JsonProperty 用在属性上或set/get方法上,该属性序列化后可重命名,也就是json中对应的key改变了,也可用来避免遗漏属性
@JsonIgnoreProperties 作用在类上,批量的@JsonIgnore操作,可列出要忽略的属性,或表示将忽略任何未知的属性。
  • 貌似没讲请@JsonIgnoreProperties的用法
    • 序列化时,通过@JsonIgnoreProperties({“a”,”b”})过滤掉属性a、b
    • 反序列化时,通过@JsonIgnoreProperties(ignoreUnknown=true)过滤掉不含getter/setters的属性

如图,还有很多用法,也可以在这里找到:https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations

/**
 *定义一个User用来测试
 */
public class User {
    @JsonProperty("userName")
    private String name;
    private String city;
    @JsonIgnore
    private int age;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    //省略getter、setters
}

/**
 *定义controller测试
 */
@RequestMapping("/users")
public User getUser() {
    User user = new User();
    user.setName("JosonLee");
    user.setAge(20);
    user.setCity("深圳");
    user.setBirthday(new Date());

    return user;
}

以下内容出自:Spring Boot jackson配置使用详解

  spring:
    jackson:
      # 设置属性命名策略,对应jackson下PropertyNamingStrategy中的常量值,SNAKE_CASE-返回的json驼峰式转下划线,json body下划线传到后端自动转驼峰式
      property-naming-strategy: SNAKE_CASE
      # 空值字段不传递
      default-property-inclusion: non_null
      # 全局设置@JsonFormat的格式pattern
      date-format: yyyy-MM-dd HH:mm:ss
      # 当地时区
      locale: zh
      # 设置全局时区
      time-zone: GMT+8
      # 常用,全局设置pojo或被@JsonInclude注解的属性的序列化方式
      default-property-inclusion: NON_NULL #不为空的属性才会序列化,具体属性可看JsonInclude.Include
      # 常规默认,枚举类SerializationFeature中的枚举属性为key,值为boolean设置jackson序列化特性,具体key请看SerializationFeature源码
      serialization:
        WRITE_DATES_AS_TIMESTAMPS: true # 返回的java.util.date转换成timestamp
        FAIL_ON_EMPTY_BEANS: true # 对象为空时是否报错,默认true
      # 枚举类DeserializationFeature中的枚举属性为key,值为boolean设置jackson反序列化特性,具体key请看DeserializationFeature源码
      deserialization:
        # 常用,json中含pojo不存在属性时是否失败报错,默认true
        FAIL_ON_UNKNOWN_PROPERTIES: false
      # 枚举类MapperFeature中的枚举属性为key,值为boolean设置jackson ObjectMapper特性
      # ObjectMapper在jackson中负责json的读写、json与pojo的互转、json tree的互转,具体特性请看MapperFeature,常规默认即可
      mapper:
        # 使用getter取代setter探测属性,如类中含getName()但不包含name属性与setName(),传输的vo json格式模板中依旧含name属性
        USE_GETTERS_AS_SETTERS: true #默认false
      # 枚举类JsonParser.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonParser特性
      # JsonParser在jackson中负责json内容的读取,具体特性请看JsonParser.Feature,一般无需设置默认即可
      parser:
        ALLOW_SINGLE_QUOTES: true # 是否允许出现单引号,默认false
      # 枚举类JsonGenerator.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonGenerator特性,一般无需设置默认即可
      # JsonGenerator在jackson中负责编写json内容,具体特性请看JsonGenerator.Feature
  • fastjson的使用

集成fastjson后,还需提供相应的 HttpMessageConverter 后才能使用(jackson-databind是因为Spring默认提供的 MappingJackson2HttpMessageConverter 来实现)

  1. 引入fastjson依赖,接触默认的jackson-databind依赖
  2. 配置 fastjson 的 HttpMessageConverter
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
  	<exclusion>
  		<groupId>com.fasterxml.jackson.core</groupId>
  		<artifactId>jackson-databind</artifactId>
  	</exclusion>
  </exclusions>
</dependency>

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

以上pom写法看不懂可以参考我之前的笔记:?????????

这里需要注意,fastjson 1.2.7之后改动了很多,像FastJsonConfig类都没了。暂时先留个问题在这~

配置 HttpMessageConverter 有两种方法,方法一:

// 新建一个类
@Configuration
public class FastJsonConfigs {
    @Bean
    FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig config = new FastJsonConfig();
        config.setSerializerFeatures(
                SerializerFeature.PrettyFormat,
                SerializerFeature.WriteClassName,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.WriteNullNumberAsZero,
                SerializerFeature.WriteNullStringAsEmpty
        );
        config.setCharset(Charset.forName("UTF-8"));
        config.setDateFormat("yyyy-MM-dd HH:mm:ss");
        converter.setFastJsonConfig(config);
        return converter;
    }
}

测试结果如图:

中文无法显示,需要加上全局配置spring.http.encoding.force-response=true

fastjson 又有新的注解,其次也没比 jackson 快很多,所以还是推荐使用 jackson


参考: