SpringBoot简介
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
Spring Boot特点:
1. 遵循“习惯优于配置”的原则,使用Spring Boot只需很少的配置,大部分时候可以使用默认配置。
2. 项目快速搭建,可无配置整合第三方框架。
3. 可完全不使用xml配置,只使用自动配置和Java config。
4. 内嵌Servlet容器(如Tomcat),应用可用jar包运行(java-jar)。
5. 运行中应用状态的监控。
SpringBoot基础
pom文件
<!-- springboot的父目录,包含大量默认配置,简化开发 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>
<properties>
<!-- 编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- jdk版本 -->
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- junit测试依赖包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot的web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot热启动工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- springboot插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
代码示例
/**
* 用户控制器
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Value(value="${aric.secret}")
private String secret;
@Value(value="${aric.number}")
private int id;
@Value(value="${aric.desc}")
private String desc;
@RequestMapping
public String index(){
return "hello world !";
}
//@RequestParam 简单类型的绑定
@RequestMapping("/get")
public Map<String,Object> get(@RequestParam String name){
Map<String,Object> map = new HashMap<String,Object>();
map.put("title", "spring boot");
map.put("name", name);
map.put("secret", secret);
map.put("id", id);
map.put("desc", desc);
return map;
}
// @PathVariable 获取请求url中的动态参数
@RequestMapping("/get/{id}/{name}")
public User getUser(@PathVariable int id, @PathVariable String name){
User user = new User();
user.setId(id);
user.setName(name);
user.setDate(new Date());
return user;
}
}
/**
* SpringBoot 启动
*/
@SpringBootApplication
public class App {
public static void main( String[] args ){
SpringApplication.run(App.class, args);
}
}
/**
* springboot测试类
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {
private MockMvc mvc;
@Before
public void setUp(){
this.mvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
}
@Test
public void contextLoads() throws Exception{
RequestBuilder request = get("/user");
mvc.perform(request).andExpect(status().isOk()).andExpect(content().string("hello world !"));
request = get("/user/get").param("name","张三");
mvc.perform(request).andExpect(status().isOk()).andExpect(content().string("{\"author\":\"张三\",\"title\":\"spring boot\"}"));
}
}
运行项目:
直接运行main方法或者使用maven命令: spring-boot:run
配置文件
一、配置文件的生效顺序,会对值进行覆盖:
1. @TestPropertySource 注解
2. 命令行参数
3. Java系统属性(System.getProperties())
4. 操作系统环境变量
5. 只有在random.*里包含的属性会产生一个RandomValuePropertySource
6. 在打包的jar外的应用程序配置文件(application.properties,包含YAML和profile变量)
7. 在打包的jar内的应用程序配置文件(application.properties,包含YAML和profile变量)
8. 在@Configuration类上的@PropertySource注解
9. 默认属性(使用SpringApplication.setDefaultProperties指定)
二、配置随机值:
#
32位随机字符串
aric.secret=${random.value}
#
int类型的随机数字
aric.number=
random.int读取使用注解:@Value(value=”
{aric.secret}”)
private String secret;
三、属性占位符
当application.properties里的值被使用时,它们会被存在的Environment过滤,所以你能够引用先前定义的值(比如,系统属性)。
aric.name=www.aric.com
`#`属性占位符属性
aric.desc=the domain is ${aric.name}
四、Application属性文件,按优先级排序,位置高的将覆盖位置低的
1. 当前目录下的一个/config子目录
2. 当前目录
3. 一个classpath下的/config包
4. classpath根路径(root)
五、服务端口和其他配置
#
端口配置:
server.port=8090
#
时间格式化
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#
时区设置
spring.jackson.time-zone=Asia/BeiJing
六、使用YAML代替Properties
#配置文件环境配置
spring:
profiles:
active: dev
#jackson
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Chongqing
#端口
server:
port: 8888
---
spring:
profiles: dev
server:
port: 8080
---
spring:
profiles: prod
server:
port: 8082
---
spring:
profiles: test
server:
port: 8081
多环境配置
一. 多环境配置的好处:
1.不同环境配置可以配置不同的参数
2.便于部署,提高效率,减少出错
二. Properties多环境配置
1. 配置激活选项,主配置文件配置这个会优先读取里面的属性覆盖主配置文件的属性
spring.profiles.active=dev
2.添加其他配置文件
application-dev.properties
application-prod.properties
application-test.properties
三.YAML多环境配置
1.配置激活选项
spring:
profiles:
active: dev
2.在配置文件添加三个英文状态下的短横线即可区分
---
spring:
profiles: dev
四.两种配置方式的比较
1.Properties配置多环境,需要添加多个配置文件,YAML只需要一个配件文件
2.书写格式的差异,yaml相对比较简洁,优雅
3.YAML的缺点:不能通过@PropertySource注解加载。如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件。
五.使用对应的环境
java -jar myapp.jar --spring.profiles.active=dev
配置日志
支持日志框架:Java Util Logging, Log4J2 and Logback,默认是使用logback
配置方式:默认配置文件配置和引用外部配置文件配置
一、 默认配置文件配置(不建议使用:不够灵活,对log4j2等不够友好)
#
日志文件名,比如:aric.log,或者是 /var/log/aric.log
logging.file=aric.log
#
日志级别配置,比如: logging.level.org.springframework=DEBUG
logging.level.*=info
logging.level.org.springframework=DEBUG
二、 引用外部配置文件
2.1 logback配置方式:
spring boot默认会加载classpath:logback-spring.xml或者classpath:logback-spring.groovy
使用自定义配置文件,配置方式为:
logging.config=classpath:logback-aric.xml
注意:不要使用logback这个来命名,否则spring boot将不能完全实例化
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 文件输出格式 -->
<property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n" />
<!-- test文件路径 -->
<property name="TEST_FILE_PATH" value="e:/develop/logs" />
<!-- pro文件路径 -->
<property name="PRO_FILE_PATH" value="/develop/aric/logs" />
<!-- 开发环境 -->
<springProfile name="dev">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${PATTERN}</pattern>
</encoder>
</appender>
<logger name="com.roncoo.education" level="debug"/>
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<!-- 测试环境 -->
<springProfile name="test">
<!-- 每天产生一个文件 -->
<appender name="TEST-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>${TEST_FILE_PATH}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${TEST_FILE_PATH}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="TEST-FILE" />
</root>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<appender name="PROD_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${PRO_FILE_PATH}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${PRO_FILE_PATH}/warn.%d{yyyy-MM-dd}.log</fileNamePattern>
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<root level="warn">
<appender-ref ref="PROD_FILE" />
</root>
</springProfile>
</configuration>
2.2 log4j配置
1. 去除logback的依赖包,添加log4j2的依赖包
2. 在classpath添加log4j2.xml或者log4j2-spring.xml(spring boot 默认加载)
3. 自定义配置文件
SpringBoot自定义配置Json转换器
引入fastJson的maven依赖
<!-- fastJson依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
第一种方式,继承WebMvcConfigurerAdapter,重写configureMessageConverters方法。
public class AricApplication extends WebMvcConfigurerAdapter {
/**
* 自定义json转换器
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
//1.定义一个converter转换消息对象
FastJsonHttpMessageConverter fjhmc = new FastJsonHttpMessageConverter();
//2.fastjson配置信息
FastJsonConfig jsonConfig = new FastJsonConfig();
//添加配置信息
jsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
//3.在conver中添加配置信息
fjhmc.setFastJsonConfig(jsonConfig);
//4.将converter添加到converters中
converters.add(fjhmc);
}
}
第二种方式,使用@Bean注解注入fastjsonHttpMessageConverter。
/**
* 自定义json转换器
* 使用@Bean注入fastjsonHttpMessageConverter
* @param args
*/
@Bean
public HttpMessageConverters fastJsonHttpMessage(){
//1.定义一个converter转换消息对象
FastJsonHttpMessageConverter jsonConverter = new FastJsonHttpMessageConverter();
//2.fastjson配置信息
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
jsonConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = jsonConverter;
return new HttpMessageConverters(converter);
}
SpringBoot核心
SpringBoot注解
@SpringBootApplication注解是Spring Boot的核心注解,该注解主要组合了以下注解:
1. @SpringBootConfiguration:这是Spring Boot项目的配置注解,这也是一个组合注解。在Spring Boot项目中推荐使用@ SpringBootConfiguration替代@Configuration。
2. @EnableAutoConfiguration:启用自动配置,该注解会使Spring Boot根据项目中依赖的jar包自动配置项目的配置项。如添加了spring-boot-starter-web的依赖,项目中也就会引入SpringMVC的依赖,Spring Boot就会自动配置tomcat和SpringMVC。
3. @ComponentScan:默认扫描@SpringBootApplication所在类的同级目录以及它的子目录。
关闭自动配置
Spring Boot会根据项目中的jar包依赖,自动做出配置,如果不需要自动配置可手动关闭。
//启动类
@SpringBootApplication(exclude={MongoAutoConfiguration.class})//关闭Mongo自动配置
public class AricApplication{
}
自定义Banner
将banner.txt拷贝到项目的resources目录中可自定义banner。
设置关闭banner
public class Main {
public static void main( String[] args ) throws SchedulerException, InterruptedException{
SpringApplication app = new SpringApplication(AricApplication.class);
//设置关闭Banner
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
}
全局配置文件
- 修改tomcat的端口:server.port=8003
- 修改进入DispatcherServlet的规则:server.servlet-path=*.do
- 更多配置可参考官方文档
加载xml配置
实际项目中,可能有一些需要必须加载xml配置,可以通过spring提供的@ImportResource来加载xml配置。
@ImportResource({"classpath:logback-dev.xml","classpath:logback-test.xml"})
日志
Spring Boot对各种日志框架都做了支持,我们可以通过配置来修改默认的日志的配置。上面多配置文件方式可以根据环境选择日志输出方式。
设置日志输出级别:
logging.level.org.springframework=DEBUG
Spring Boot的自动配置的原理
Spring Boot在进行SpringApplication对象实例化时会加载META-INF/spring.factories文件,将该配置文件中的配置载入到Spring容器。
条件注解
SpringBoot异常处理
一、Spring Boot 将所有的错误默认映射到/error, 实现ErrorController
@Controller
@RequestMapping(value = "/error")
public class BaseErrorController implements ErrorController {
private static final Logger logger = LoggerFactory.getLogger(BaseErrorController.class);
@Override
public String getErrorPath() {
logger.info("出错,错误异常处理器!");
return "error/error";
}
@RequestMapping
public String error(){
return getErrorPath();
}
}
方法二:添加自定义的错误页面
2.1 html静态页面:在resources/public/error/ 下定义
如添加404页面: resources/public/error/404.html页面,中文注意页面编码
2.2 模板引擎页面:在templates/error/下定义
如添加500页面: templates/error/500.ftl
注意事项:templates/error/ 这个的优先级比较 resources/public/error/高
方法三:使用注解@ControllerAdvice
/**
* 异常消息处理类
*/
@ControllerAdvice
public class GlobalDefaultExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalDefaultExceptionHandler.class);
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public String defaultExceptionHandler(HttpServletRequest req,Exception e){
logger.error("自定义异常-RuntimeException");
return "该功能出现异常!";
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.OK)
public ModelAndView doExceptionHandler(HttpServletRequest req,Exception e){
logger.error("自定义异常-Exception");
ModelAndView mav = new ModelAndView();
mav.addObject("aricException", e.getMessage());
mav.setViewName("exception/500");
return mav;
}
}
SpringBoot的Web开发
一.spring boot的web应用开发,是基于spring mvc
二.Spring boot 在spring默认基础上,自动配置添加了以下特性:
1. 包含了ContentNegotiatingViewResolver和BeanNameViewResolver beans。
2. 对静态资源的支持,包括对WebJars的支持。
3. 自动注册Converter,GenericConverter,Formatter beans。
4. 对HttpMessageConverters的支持。
5. 自动注册MessageCodeResolver。
6. 对静态index.html的支持。
7. 对自定义Favicon的支持。
8. 主动使用ConfigurableWebBindingInitializer bean
三.模板引擎的选择
FreeMarker
Thymeleaf
Velocity (1.4版本之后弃用,Spring Framework 4.3版本之后弃用)
Groovy
Mustache
jsp应该尽量避免使用,原因如下:
1. jsp只能打包为:war格式,不支持jar格式,只能在标准的容器里面跑(tomcat,jetty都可以)
2. 内嵌的Jetty目前不支持JSPs
3. Undertow不支持jsps
4. jsp自定义错误页面不能覆盖spring boot 默认的错误页面
模板引擎FreeMarker
一.FreeMarker Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
二. application.properties 中配置
#freemarker 配置
spring.freemarker.allow-request-override=false
spring.freemarker.cache=true
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false
三. 代码示例
@Controller
@RequestMapping("/templates")
public class TemplatesController {
/**
* 访问ftl文件
* @return
*/
@RequestMapping("/hello")
public String hello(Map<String,Object> map){
map.put("name", "curry");
return "hello";
}
}
resource下的templates中hello.ftl文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
</head>
<body>
<h1>Hello,${name} !</h1>
</body>
</html>
模板引擎Thymeleaf
一. maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
二. application.properties配置
#thymeleaf 配置
#开发过程建议关闭缓存
#spring.thymeleaf.cache=false
三. 代码示例
@Controller
@RequestMapping("/templates")
public class TemplatesController {
/**
* 访问html页面
* @return
*/
@RequestMapping("/index")
public String index(Map<String,Object> map){
map.put("name", "james");
return "index";
}
}
resource下的templates中index.html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title here</title>
</head>
<body>
<h1>Hello,thymeleaf !</h1>
<br/>
welcome <span th:text="${name}"></span>
</body>
</html>
模板引擎jsp
一. maven依赖
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- 内嵌的tamcat不支持jsp页面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
二. application.properties配置
#jsp 配置
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
三. 代码示例
@Controller
@RequestMapping("/testJsp")
public class JspController {
@RequestMapping("/demo")
public String test(Map<String,Object> map){
map.put("name", "messi");
return "demo";
}
}
webapp下的WEB-INF下的jsp文件中demo.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jsp demo</title>
</head>
<body>
<h2>hello ${name } !</h2>
</body>
</html>
资源路径和配置文件
Web开发的自动配置类:org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration自动配置ViewResolver。
自动配置静态资源:
如果进入SpringMVC的规则为/时,Spring Boot的默认静态资源的路径为:
#配置进入sprngmvc规则
server.servlet-path=/
#静态资源路径
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
进入规则为*.xxx 或者 不指定静态文件路径时,将静态资源放置到webapp下的static目录中即可通过地址访问。
读取外部的配置文件:
@PropertySource(value = {"classpath:jdbc.properties", "classpath:env.properties",
"classpath:httpclient.properties", "classpath:redis.properties", "classpath:rabbitmq.properties" },
ignoreResourceNotFound = true) //读取外部配置文件,如果不存在则忽略
@ComponentScan(basePackages = "cn.aric") //扫描包
public class AricApplication {
自定义消息转换器
自定义消息转化器,只需要在@Configuration的类中添加消息转化器的@bean加入到Spring容器,就会被Spring Boot自动加入到容器中。
/**
* 自定义消息转换器
* @return
*/
@Bean
public StringHttpMessageConverter stringHttpMessageConverter(){
StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
SpringBoot整合Servlets、Filters、listeners
自定义Servlet、Filter、Listener
@WebServlet
public class CustServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet get method");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet post method");
resp.getWriter().write("hello world");
}
}
/**
* 自定义过滤器
*/
@WebFilter
public class CustFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init filter");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("do filter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("destory filter");
}
}
/**
* 自定义监听器
*/
@WebListener
public class CustListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
方法一:通过注册ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制
/**
* 注入自定义servlet
* @return
*/
@Bean
public ServletRegistrationBean servletRegistrationBean(){
return new ServletRegistrationBean(new CustServlet(),"/aric");
}
/**
* 注入自定义过滤器
* @return
*/
@Bean
public FilterRegistrationBean filterRegistrationBean(){
return new FilterRegistrationBean(new CustFilter(), servletRegistrationBean());
}
/**
* 注入自定义监听器
* @return
*/
@Bean
public ServletListenerRegistrationBean<CustListener> servletListenerRegistrationBean(){
return new ServletListenerRegistrationBean<CustListener>(new CustListener());
}
方法二:通过实现 ServletContextInitializer 接口直接注册
/**
* 实现ServletContainerInitializer实现注册 servlet、filter、listener
*/
public class MyServletcontainerInitializer implements ServletContainerInitializer{
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
//注册自定义servlet
ctx.addServlet("custServlet", new CustServlet()).addMapping("/aric");
//注册自定义filter
ctx.addFilter("custFilter", new CustFilter()).
addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true, "custFilter");
//注册自定义listener
ctx.addListener(new CustListener());
}
}
方法三:在 SpringBootApplication 上使用@ServletComponentScan 注解后,直接通过@WebServlet、@WebFilter、@WebListener 注解自动注册
SpringBoot自定义拦截器
/**
* 自定义拦截器
*/
@Component
public class UserLoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("登陆拦截器...");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
/**
* 注册自定义拦截器
*/
@Configuration
public class SpringMvcConfig extends WebMvcConfigurerAdapter{
//注入用户登陆拦截器
@Autowired
private UserLoginHandlerInterceptor userLoginHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//判断用户是否登陆的拦截器
registry.addInterceptor(userLoginHandlerInterceptor).addPathPatterns("/user/**");
}
}
CORS支持 ###
一、Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等
CORS与JSONP相比:
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS
二、在spring MVC 中可以配置全局的规则,也可以使用@CrossOrigin注解进行细粒度的配置。
/**
* Cors全局配置
*/
@Configuration
public class CustCorsConfiguration {
@Bean
public WebMvcConfigurerAdapter corsConfigurer(){
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**").allowedOrigins("http://127.0.0.1:8002");
}
};
}
}
或者
/**
* Cors自定义全局配置
*/
@Configuration
public class CustomCorsConfiguration extends WebMvcConfigurerAdapter{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**").allowedOrigins("http://127.0.0.1:8002");
}
}
定义方法:
/**
* api控制器,定义方法
*/
@RestController
@RequestMapping("/api")
public class ApiController {
@RequestMapping("/get")
public Map<String,Object> get(@RequestParam String name){
Map<String,Object> map = new HashMap<String,Object>();
map.put("title", "spring boot");
map.put("name", name);
return map;
}
}
细粒度控制:
/**
* @CrossOrigin 进行Cors细粒度控制
*/
@RestController
@RequestMapping(value = "/api",method=RequestMethod.POST)
public class ApiThinController {
@CrossOrigin(origins="http://localhost:8002")
@RequestMapping("/get")
public Map<String,Object> get(@RequestParam String name){
Map<String,Object> map = new HashMap<String,Object>();
map.put("title", "spring");
map.put("name", name);
return map;
}
}
文件上传
一、Spring Boot 默认使用springMVC包装好的解析器进行上传
二、配置
#上传文件配置
#默认支持文件上传
spring.http.multipart.enabled=true
#支持文件写入磁盘
spring.http.multipart.file-size-threshold=0
#上传文件的临时目录
spring.http.multipart.location=
#最大支持文件大小
spring.http.multipart.max-file-size=1Mb
#最大支持请求大小
spring.http.multipart.max-request-size=10Mb
三、代码示例
jsp文件夹下的upload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传测试</title>
</head>
<body>
<div>
<form method="post" enctype="multipart/form-data" action="/file/upload">
文件:<input type="file" name="aricFile"><br>
<input type="submit" value="上传">
</form>
</div>
</body>
</html>
上传文件后台处理代码:
/**
* 文件Contrller
*/
@Controller
@RequestMapping("/file")
public class FileController {
private static Logger logger = LoggerFactory.getLogger(FileController.class);
@RequestMapping("/toPage")
public String toPage(){
return "upload";
}
@RequestMapping("/upload")
@ResponseBody
public String upload(@RequestParam("aricFile") MultipartFile file){
if (file.isEmpty()) {
return "文件为空!";
}
//获取文件名
String filename = file.getOriginalFilename();
logger.info("上传文件名称: " + filename);
//获取文件后缀名
String suffixName = filename.substring(filename.lastIndexOf("."));
logger.info("文件后缀名: " + suffixName);
//上传文件地址
String filePath = "e:/develop/temp/";
//文件名称加密
filename = UUID.randomUUID() + suffixName;
//目标文件
File dest = new File(filePath,filename);
//检查是否存在目录
if(!dest.getParentFile().exists()){
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest);
return "上传成功!";
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "上传失败!";
}
}
SpringBoot的数据访问
SpringBoot集成Spring Data Jpa
引入Maven依赖
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- spring-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
实现接口:
/**
* 继承CrudRepository,具有增删查功能
*/
public interface CatDao extends CrudRepository<Cat,Integer>{
}
/**
* 继承PagingAndSortingRepository,具有分页和排序功能
*/
public interface CatsDao extends PagingAndSortingRepository<Cat,Integer>{
public Cat findByName(String name);
@Query(" from Cat where age=:a")
public List<Cat> findByAge(@Param("a") Integer age);
}
SpringBoot中使用JdbcTemplate
引入Maven依赖
<!-- jdbc依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
代码:
@Repository
public class PersonDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void save(Person person){
if (null != person) {
String sql = "insert into person(name,birth_day,remark) values(";
if (!StringUtils.isEmpty(person.getName())) {
sql += "'" + person.getName() + "',";
}
if (null != person.getBirthDay()) {
sql += person.getBirthDay() + ",";
}
if (!StringUtils.isEmpty(person.getName())) {
sql += "'" + person.getRemark() + "',";
}
if (sql.endsWith(",")){
sql = sql.substring(0, sql.length()-1);
}
sql += ")";
jdbcTemplate.execute(sql);
}
}
}
SpringBoot集成MyBatis
引入mybatis和分页工具的Maven依赖
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mybatis分页工具依赖 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
代码配置:
/**
* MyBatis配置
*/
@Configuration
public class MyBatisConfig {
/**
* 注入分页工具
* @return
*/
@Bean
public PageHelper pageHelper(){
System.out.println("MyBatisConfig.PageHelper");
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
properties.setProperty("offsetAsPageNum", "true");
properties.setProperty("rowBoundsWithCount", "true");
properties.setProperty("reasonable", "true");
pageHelper.setProperties(properties);
return pageHelper;
}
}
/**
* Mapper文件配置
*/
@Configuration
@AutoConfigureAfter(MyBatisConfig.class) //保证在MyBatisConfig实例化之后再实例化该类
public class MapperConfig {
}
在启动类上添加注解扫描mapper
@SpringBootApplication
@MapperScan("cn.aric.*.mapper") //扫描该包下响应的class,Mybatis的持久化类
public class AricApplication{
}
Mapper文件
/**
* Cat实体的mapper文件
*/
public interface CatMapper {
//#{name}命名占位符
@Select("select * from Cat where name = #{name} ")
public List<Cat> getByName(String name);
/**
* 保存操作
* @param cat
*/
@Insert("insert into Cat(name) values(#{name})")
@Options(useGeneratedKeys=true,keyProperty="id",keyColumn="id")//设置id自增长
public void save(Cat cat);
}
service略
controller代码
@RestController
public class MyCatController {
@Autowired
private MyCatService myCatService;
@RequestMapping("/getByName")
public List<Cat> getByName(String name){
//设置分页
PageHelper.startPage(1, 2);
return myCatService.getByName(name);
}
}
事务管理
引入maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
当引入jdbc依赖之后,SpringBoot会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager,所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。
@Transactional不仅可以注解在方法上,也可以注解在类上。注解在类上时,此类的所有public方法都是开启事务的。如果类级别和方法级别同时使用@Transactional注解,则使用在方法级别的注解会重载类级别的注解。
SpringBoot整合Druid连接池
引入maven依赖
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
配置文件,只写了部分,详细参考druid资料
#指定mysql数据库连接消息
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
#spring.datasource.useGlobalDataSourceStat=true
配置过滤器
@SpringBootApplication
public class AricApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//设置启动类,用于独立tomcat运行的入口
return builder.sources(AricApplication.class);
}
@Bean
public FilterRegistrationBean fileterRegistrationBean(){
FilterRegistrationBean filter = new FilterRegistrationBean();
filter.setFilter(new WebStatFilter());
filter.setName("druidWebStatFilter");
filter.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
filter.addUrlPatterns("/");
return filter;
}
@Bean
public ServletRegistrationBean servletRegistrationBean(){
ServletRegistrationBean servlet = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
servlet.setName("druidStatViewServlet");
servlet.addInitParameter("restEnable", "false");
return servlet;
}
}
访问url:http://ip地址:端口号/druid/
SpringBoot开发部署
SpringBoot热部署
第一种方式,springloader插件。
<!-- springloader plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- springloaded hot deploy -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
第二种方式,devtools工具。
<!-- devtools依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<!-- spring boot devtools plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- fork:没有配置,应用不会restart -->
<fork>true</fork>
</configuration>
</plugin>
修改tomcat
/**
* 修改tomcat配置
* @return
* @throws SchedulerException
* @throws InterruptedException
*/
@Bean
public EmbeddedServletContainerFactory servletContainer(){
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(8001);
factory.setSessionTimeout(10,TimeUnit.SECONDS);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,"/notfound.html"));
return factory;
}
将spring-boot-starter-tomcat的范围设置为provided,设置为provided是在打包时会将该包排除,因为要放到独立的tomcat中运行,是不需要的。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
设置启动配置
集成SpringBootServletInitializer,然后重写configure,将Spring Boot的入口类设置进去。
@SpringBootApplication
public class AricApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//设置启动类,用于独立tomcat运行的入口
return builder.sources(AricApplication.class);
}
}