一、maven构建
1.1 继承boot超级parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
这样,其他依赖不需要写版本号,如果一定要写,配置在properties即可,如:
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
默认版本号可以在下面配置找到: https://github.com/spring-projects/spring-boot/blob/v1.4.1.RELEASE/spring-boot-dependencies/pom.xml
1.2 不继承parent
如果不继承parent,可以使用一下配置完成:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
但是,不能在properties特殊指定版本,如果需要,可以在生dependencyManagement
并列添加对应依赖;
例如:
<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1.3 指定jdk版本
<properties>
<java.version>1.8</java.version>
</properties>
1.4 打包
添加以下配置后,会生成一个可执行jar包
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
1.5 俩个常用包
spring-boot-starter-actuator
:管理配置和监控
spring-boot-starter-remote-shell
:远程shell
二、代码结构
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
Application.java
:启动类
package com.example.myproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication
可以代替上面三个注解;
@ComponentScan
:默认只扫描main下面的包,方便起见,最好是自己配@ComponentScan(“com.henry.exameple”)
@ImportResource
:引入xml配置文件
三、启动和部署
3.1 开发启动
- 运行main方法
- 执行jar包:
java -jar target/myproject-0.0.1-SNAPSHOT.jar
- 远程调试:
java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar target/myproject-0.0.1-SNAPSHOT.jar
3.2 热启动
3.2.1 添加依赖
添加以下依赖,当代码变动时,它会自动进行重启应用
注:这个插件会导致dubbo调用失败,具体原因未查)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
或者使用springloaded插件来实现,这种情况下,只有debug时自动加载。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
3.2.2 IDE 自动加载
- eclipse:保存文件即可
- idea:
Build
→Make Project
注:使用java -jar
启动时,自动认为是生产环境,自动重启/加载将会失效。
3.2.3 配置
- 排除自动加载路径
spring.devtools.restart.exclude=static/**,public/**
- 如果不希望每次保存文件都启动,可以通过trigger-file
spring.devtools.restart.trigger-file
3.2.3 关闭restart
application.properties
spring.devtools.restart.enabled = false
3.2.4 美化配置
- 在resources下添加banner.txt,里面的内容将在启动时输出
- 实现
org.springframework.boot.ExitCodeGenerator
可以自定义应用关闭时的返回
3.3 生产环境部署
3.3.1 init.d
启停
spring boot可以直接用nohup jar -jar myqpp.jar >/dev/null 2>&1 &
但是不好优雅stop,在有acutor时,可以通过如下方式
1.Maven pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.application.properties:
endpoints.shutdown.sensitive=false
endpoints.shutdown.enabled=true
3.Send a post method to shutdown the app:
curl -X POST localhost:port/shutdown
但是不方便,推荐init.d。
启停可以自己写脚本实现,spring boot init.d
服务,只要jar包是通过spring-boot-maven-plugin
打包。
ln -s /var/myapp/myapp.jar /etc/init.d/myapp
service myapp start|stop|restart
- PID文件:/var/run/appname/appname.pid
- 启动日志:/var/log/appname.log
调整JVM启动参数:
新建一个同名.conf
文件。
myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
个性化调整,可以配置
四、spring-boot配置
4.1 application.properties
详细见github https://github.com/ErDaoYa/spring-learn/blob/master/spring-boot/application.properties
4.2 环境相关配置
可以定义application-dev.properties,在启动时加载,application.properties,没有的配置,继续沿用。
java -jar target/***.jar --spring.profiles.active=dev
还可以直接指定配置文件启动
java -jar ***.jar --spring.config.name=myproject
五、个性化
5.1 处理错误页面
public class ContainerConfig {
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(){
return new MyCustomizer();
}
private static class MyCustomizer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/500"));
}
}
@RestController
public class ExceptionController {
@RequestMapping("/exception")
public void catchException() {
throw new RuntimeException("error occur");
}
@RequestMapping("/500")
public void showServerError() {
throw new C403Exception("资源不可用",null);
}
}
5.2 MessageConverters个性化配置
4.2.1 自带Jackson配置
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.List;
/**
* <p>jackson个性化配置</p>
* @author zhaozhou
* Created on 2016/10/31.
*/
@Configuration
public class Jackson2HttpMessageConverter extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(createFastJsonHttpMessageConverter());
super.configureMessageConverters(converters);
}
private MappingJackson2HttpMessageConverter createFastJsonHttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jsonConverter.setObjectMapper(objectMapper);
return jsonConverter;
}
}
4.2.1 扩展fastjson
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* <p>fastjson配置类</p>
* @since 1.0
*/
@Configuration
//@EnableWebMvc
public class FastJsonHttpMessageConfig extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(createFastJsonHttpMessageConverter());
super.configureMessageConverters(converters);
}
private FastJsonHttpMessageConverter4 createFastJsonHttpMessageConverter() {
//spring mvc 4x 应该使用FastJsonHttpMessageConverter4
FastJsonHttpMessageConverter4 fastJsonHttpMessageConverter4= new FastJsonHttpMessageConverter4();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//特色配置
fastJsonConfig.setSerializerFeatures(
// SerializerFeature.PrettyFormat,/
SerializerFeature.DisableCircularReferenceDetect, //关闭引用支持
SerializerFeature.BrowserCompatible,
SerializerFeature.SkipTransientField,
SerializerFeature.QuoteFieldNames
);
fastJsonHttpMessageConverter4.setFastJsonConfig(fastJsonConfig);
//属性过滤器
/* PropertyFilter filter = new PropertyFilter() {
public boolean apply(Object source, String name, Object value) {
if (null == name) {
return false;
}
return true;
}
};*/
// fastJsonConfig.setSerializeFilters(filter);
// 设置MediaTypes
List<MediaType> mediaTypes =new ArrayList<MediaType>();
mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastJsonHttpMessageConverter4.setSupportedMediaTypes(mediaTypes);
return fastJsonHttpMessageConverter4;
}
}
5.3 静态文件目录和欢迎页设置
同样在config中重写addResourceHandlers
和addViewControllers
方法;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter
{
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/dist/", "classpath:/public/" };
// @Value("${property:default value}")
@Value("${dubbor.web.welcome-file:index.html}")
private String welcomeFile;
...
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
if(!StringUtils.isEmpty(welcomeFile) || !"index.html".equals(welcomeFile)){
registry.addViewController("/").setViewName("forward:"+welcomeFile);
registry.setOrder( Ordered.HIGHEST_PRECEDENCE );
}
super.addViewControllers( registry );
}