spring-boot常用基本功能总结

springBoot 静态资源配置

springBoot这个框架的确不错,可以减少很多配置.下面记录下我做的vr后台系统中使用到的springBoot相关技术点,我也是第一次使用(在摸索中进步).
首先要说的是,springBoot会扫描入口类的同级以及子级package, 我的入口类写法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Created by xiehui1956(@)gmail.com on 16-12-26.
*/
@SpringBootApplication
@EnableTransactionManagement // 开启事务管理
@EnableConfigurationProperties({UserCenterConfig.class, WiselySettings.class})
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

SpringBootApplication : 说明这个类是springBoot的启动类
EnableTransactionManagement : 开启事务管理设置
EnableConfigurationProperties : 开启静态属性配置设置
UserCenterConfig, WiselySettings :静态属性对应的实体

代替原spring的xml配置文件中的bean标签

实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Created by xiehui1956(@)gmail.com on 16-12-28.
*/
@Configuration
public class DataPointRuleConfig {

@Bean
public HttpApiClient getHttpApiClient() {
return new HttpApiClient();
}

@Bean
public Gson getGson() {
return new Gson();
}

}

Configuration: 说明这个类是配置类
Bean : 说明这个方法返回的是个实体,这个注解就是代替原xml配置的Bean标签,部分源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 * @author Rod Johnson
* @author Costin Leau
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0
* @see Configuration
* @see Scope
* @see DependsOn
* @see Lazy
* @see Primary
* @see org.springframework.stereotype.Component
* @see org.springframework.beans.factory.annotation.Autowired
* @see org.springframework.beans.factory.annotation.Value
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {

都是基本注解的配置
上面两个Bean分别作用是,交由spring管理HttpApiClient和Gson实例,使用的方式如下:

1
2
@Autowired
private Gson gson;

跨域设置

跨域问题主要是浏览器同源策略限制的,浏览器限制跨域访问前会和服务器沟通所以也可以在服务端进行设置.这个只要明白跨域问题和怎么解决,springBoot提供的解决方案就没啥好说的.具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Created by xiehui1956(@)gmail.com on 16-12-27.
*/
@Configuration
public class CorsConfig {

private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}

@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}

}

Jsonp支持及Jsonp中文乱码处理

Jsonp一个提供给浏览器使用为了解决跨域问题的协议,jquery这个js库提供的Jsonp支持.具体细节此处不谈,实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Created by xiehui1956(@)gmail.com on 16-9-8.
*/
@ControllerAdvice(basePackages = "com.chinaredstar.vr.mng.controller")
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

public JsonpAdvice() {
super("callback", "jsonp");
}

@Override
protected MediaType getContentType(MediaType contentType, ServerHttpRequest request, ServerHttpResponse response) {
return MediaType.APPLICATION_JSON_UTF8;
}
}

JsonpAdvice : 构造函数声明回调函数名的关键字,spring源码如下:

1
2
3
4
protected AbstractJsonpResponseBodyAdvice(String... queryParamNames) {
Assert.isTrue(!ObjectUtils.isEmpty(queryParamNames), "At least one query param name is required");
this.jsonpQueryParamNames = queryParamNames;
}

由此可以看出spring提供的回调函数声明关键字是支持多个的.
getContentType : 浏览器解析头部信息这个大家都懂的,是用来告诉浏览器怎么解析服务数据.防止乱码就是在这里设置的,spring默认携带了很多自带的MediaType信息.

Interceptor拦截器设置

拦截器这个很多框架都提供了,基础servlet中的filter过滤器很类似.spring中的拦截器实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* Created by xiehui1956(@)gmail.com on 17-1-9.
*/
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {

private static final Logger LOGGER = LoggerFactory.getLogger(LoginInterceptor.class);

@Autowired
private UserCenterConfig userCenterConfig;

@Autowired
private Gson gson;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Map<String, String> headers = CookieUtils.getHeaders(request);

return true;
}


}

我这里准备做登录操作,但是这个功能排期在后面.
Component : 声明拦截器组件并且继承HandlerInterceptorAdapter, 重写拦截器方法,spring提供的拦截器方法也叫通知(前置通知, 后置通知, 环绕通知, 异常通知),preHandle前置通知.

默认静态资源和自定义静态资源加载方案

springBoot默认会加载application.properties配置中的属性,当然也可以手动指定外部静态资源文件.实例如下:
application.properties中的设置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#tomcat
server.port=8067
#db
spring.datasource.username=
spring.datasource.password=
spring.datasource.url=
#spring.datasource.username=
#spring.datasource.password=
#spring.datasource.url=
#spring.datasource.driver-class-name=
#user center
security.userCenter.baseUri=
security.userCenter.checkLogin=
security.userCenter.loginUri=
security.userCenter.logoutUri=

spring开头的数据库配置是springBoot默认链接数据库的配置,security开头的是自定义配置.在这里配置后创建对应的实体就可以spring就会自动注入静态属性值,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
* Created by xiehui1956(@)gmail.com on 17-1-11.
*/
@Component
@ConfigurationProperties(prefix = "security.userCenter")
public class UserCenterConfig {

private String baseUri;
private String checkLogin;
private String loginUri;
private String logoutUri;
private String findUserDatas;
private String redirectURL;
private String appId;
private String appSecret;

public String getBaseUri() {
return baseUri;
}

public void setBaseUri(String baseUri) {
this.baseUri = baseUri;
}

public String getCheckLogin() {
return checkLogin;
}

public void setCheckLogin(String checkLogin) {
this.checkLogin = checkLogin;
}

public String getLoginUri() {
return loginUri;
}

public void setLoginUri(String loginUri) {
this.loginUri = loginUri;
}

public String getLogoutUri() {
return logoutUri;
}

public void setLogoutUri(String logoutUri) {
this.logoutUri = logoutUri;
}

public String getFindUserDatas() {
return findUserDatas;
}

public void setFindUserDatas(String findUserDatas) {
this.findUserDatas = findUserDatas;
}

public String getRedirectURL() {
return redirectURL;
}

public void setRedirectURL(String redirectURL) {
this.redirectURL = redirectURL;
}

public String getAppId() {
return appId;
}

public void setAppId(String appId) {
this.appId = appId;
}

public String getAppSecret() {
return appSecret;
}

public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}

/**
* 跳转至用户中心
*
* @return
*/
public String jump2userCenter() {
StringBuilder url = new StringBuilder(this.getBaseUri());
url.append(this.getLoginUri());
url.append(this.getAppSecret());
url.append("?redirectURL=");
url.append(this.getRedirectURL());
return url.toString();
}

@Override
public String toString() {
return "UserCenterConfig{" +
"baseUri='" + baseUri + '\'' +
", checkLogin='" + checkLogin + '\'' +
", loginUri='" + loginUri + '\'' +
", logoutUri='" + logoutUri + '\'' +
", findUserDatas='" + findUserDatas + '\'' +
", redirectURL='" + redirectURL + '\'' +
", appId='" + appId + '\'' +
", appSecret='" + appSecret + '\'' +
'}';
}
}

Component : 基本注解
ConfigurationProperties : 静态属性注入注解,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {
@AliasFor("prefix")
String value() default "";

@AliasFor("value")
String prefix() default "";

boolean ignoreInvalidFields() default false;

boolean ignoreNestedProperties() default false;

boolean ignoreUnknownFields() default true;

boolean exceptionIfInvalid() default true;

/** @deprecated */
@Deprecated
String[] locations() default {};

/** @deprecated */
@Deprecated
boolean merge() default true;
}

prefix : 匹配的前缀,我这里是security.userCenter

上面的静态属性配置是放在spring默认配置文件中,如果使用自定义的配置文件如下:
xh.properties

1
2
xh.name=bruce
xh.gender=male

对应的实体:
XhSettings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* Created by xiehui1956(@)gmail.com on 17-2-24.
*/
@ConfigurationProperties(prefix = "xh", locations = "classpath:xh.properties")
public class XhSettings {

private String name;
private String gender;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

@Override
public String toString() {
return "XhSettings{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
'}';
}
}

这里要特别说明的时locations这个参数设置,这里这样配置启动的时候并没有问题.问题是如果把properties静态属性配置文件提取出来使用脚本启动时系统会找不到文件位置无法注入数据.
正常jar程序启动命令是java -jar 项目名就可以了,如果在同级路径下有application.properties文件系统是可以获取到配置的数据如果是自定义的数据就需要使用springBoot官网默认提供的命令了,相关的官网地址: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
命令:

1
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

这个命令前提是你把配置文件打包到了classpath下,如果你像我说的抽取出来了的话这个命令时无效的需要使用下面的命令:

1
java -jar myproject.jar --spring.config.file=/apps/xxx.properties,/apps/xxx.properties

统一异常处理

这个应该没啥说的,直接上代码吧
ServiceException.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    
/**
* Created by xiehui1956(@)gmail.com on 17-2-9.
*/
public class ServiceException extends Exception {

public ServiceException() {
}

public ServiceException(String message) {
super(message);
}

}

GlobalExceptionHandler.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Created by xiehui1956(@)gmail.com on 17-2-9.
*/
@ControllerAdvice
public class GlobalExceptionHandler {

public static final String DEFAULT_ERROR_VIEW = "error";

@ResponseBody
@ExceptionHandler(value = ServiceException.class)
public CommonResult defaultErrorHandler(HttpServletRequest request, Exception exception) throws Exception {
CommonResult commonResult = new CommonResult();
commonResult.setCodeAndMessage(ApiStatusCode.FAIL_SYSTEM_ERROR, exception.getMessage());
commonResult.setData(request.getRequestURL().toString());
return commonResult;
}
}