一位阿里 Java 工程师的技术小站。作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!(关注公众号后回复”Java“即可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南、Java程序员面试指南等干货资源)

SpringBoot详解(一)-快速入门

SpringBoot详解系列文章:
SpringBoot详解(一)-快速入门
SpringBoot详解(二)-Spring Boot的核心
SpringBoot详解(三)-Spring Boot的web开发
SpringBoot详解(四)-优雅地处理日志

一、Spring Boot

久闻Spring Boot大名,这两天终于得空,学习了一把,发觉Spring Boot确实好用,那Spring Boot到底是什么,又是怎么好用呢?

什么是Spring Boot

目前ssm框架还是比较常用的,其中的ss指的无非就是Spring 和 SpringMVC,我们可以简单的认为 "Spring Boot ≥ Spring + SpringMVC",没错,用了Spring Boot中涵盖了Spring和SpringMVC等大量常用开发配置,而且Spring Boot的配置极其简单,可以让你不用或者只需要很少的Spring配置就可以让你的项目快速运行起来。

Spring Boot的优缺点

优点

  1. 快速构建项目
  2. 对主流开发框架的无配置集成
  3. 项目可独立运行,无须外部依赖Servlet容器(Spring Boot默认自带了一个Tomcat)
  4. 提供运行时的应用监控
  5. 极大地提高了开发、部署效率
  6. 与云计算的天然集成

缺点

  1. 坑有些多, 文档略少

二、快速入门

1、Spring的Java配置方式

上面已经提到了,使用Spring Boot,可以让你不用或者只需要很少的Spring配置就可以让你的项目快速运行起来,说的就是使用代码注解来取代xml配置。其实从Spring3.x开始就已经提供了java配置方式,使用java配置方式可以更好的理解你配置的Bean,而如今的Spring4.x更是推荐java配置方式,java配置方式可以完全替代xml配置,下面就先来看看两个最基本的注释:

1)@Configuration 和 @Bean

Spring的java配置方式是通过@Configuration 和 @Bean这两个注释实现的:

  • @Configuration 作用于类上,相当于一个xml配置文件
  • @Bean 作用于方法上,相当于xml配置中的

2)小示例

该示例将通过java配置方式配置Spring,实现Spring IOC功能。

这是一个简单的模拟从数据库获取User数据的Dao类(注意,它并没有使用任何注解,也就是说UserDao目前并没有交给Spring容器管理)。

  1. public class UserDao {
  2. public List<String> queryUserList() {
  3. List<String> list = new ArrayList<>();
  4. for (int i = 0; i < 10; i++) {
  5. list.add("User " + i);
  6. }
  7. return list;
  8. }
  9. }

这是一个最最常见的Service,通过注入UserDao,使用UserDao的方法获取用户数据。

  1. @Service
  2. public class UserService {
  3. @Autowired
  4. UserDao userDao;
  5. public void getUserList() {
  6. List<String> list = userDao.queryUserList();
  7. for (int i = 0; i < list.size(); i++) {
  8. System.out.println(list.get(i));
  9. }
  10. }
  11. }

从这里开始就跟以往的Spring开发不一样了,这个类使用了2个新的注解,其中@Configuration表明该相当于Spring的一个xml配置文件,@Bean将一开始的UserDao配置给Spring管理.

  1. @Configuration// 通过注解来表明该类是一个Spring的配置,相当于一个xml文件
  2. public class SpringConfig {
  3. @Bean// 这里要注意,方法名"getUserDao"将作为UserDao在容器中的id
  4. public UserDao getUserDao() {
  5. return new UserDao();
  6. }
  7. }

接下来就是获取Spring容器,从容器中拿到UserService,并调用其获取用户数据的方法,代码如下:

  1. public class Test {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(SpringConfig.class);
  4. UserService userService = (UserService) acac.getBean("userService");
  5. userService.getUserList();
  6. }
  7. }

像普通的java程序一样,直接运行Test类中的main方法即可在控制台看到用户数据输出了。

细心的你应该发现了,以往获取Spring容器使用到的类要么是ClassPathXmlApplicationContext 或是 FileSystemXmlApplicationContext,但Spring Boot使用的却是AnnotationConfigApplicationContext,原因也好理解,因为我们Spring Boot使用的是java配置的方式,而以往使用的是Spring的xml配置方式.

2、第一个Web应用

通过上面的示例,我们已经知道了java配置方式是怎么回事了,那接下来便正式开始使用Spring Boot来开发我们的第一个web应用了.

1)pom.xml配置

设置spring boot的parent

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>1.5.2.RELEASE</version>
  5. </parent>

说明:Spring boot的项目必须要将parent设置为spring boot的parent,该parent包含了大量默认的配置,大大简化了我们的开发。

导入spring boot的web支持

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>

添加Spring boot的插件

  1. <plugin>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-maven-plugin</artifactId>
  4. </plugin>

通过上面简单的3步配置,Spring Boot就配置完毕了,相比以往的Spring、SpringMVC配置是不是要简洁的多呢?

2)小示例

  1. @SpringBootApplication// Spring Boot项目的核心注解,主要目的是开启自动配置
  2. @Controller//标明这是一个SpringMVC的Controller控制器
  3. public class HelloApplication {
  4. @RequestMapping("/hello")
  5. @ResponseBody
  6. public String hello() {
  7. return "hello world";
  8. }
  9. // 在main方法中启动一个应用,即:这个应用的入口
  10. public static void main(String[] args) {
  11. SpringApplication.run(HelloApplication.class, args);
  12. }
  13. }

一般Spring Boot的Web应用都有一个xxxApplication类,并使用@SpringBootApplication注解标记,作为该web应用的加载入口。此外,还需要在main方法中(可以是任意一个类)使用SpringApplication.run(xxxApplication.class, args)来启动该web应用。

运行HelloApplication中的main()方法,启动该web应用后,在地址栏输入"http://localhost:8080/hello",就可以看到输出结果了。

3)运行报错

如果你项目中没有其他配置,那在运行这个简单的项目时一般是不会报错的,但如果很不幸你第一次运行就报错的话,也不用着急,大部分问题百度即可,本人在启动项目过程中遇到就"Cannot determine embedded database driver class for database type NONE"这样的错误,这样就记录一下,报错截图如下:

原因是:springboot启动时会自动注入数据源和配置jpa。

解决方法:在@SpringBootApplication中排除其注入

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})

所以,上面的代码修改如下即可:

  1. @SpringBootApplication(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
  2. @Controller
  3. public class HelloApplication {
  4. ...
  5. }

三、疑问

到这里是不是已经大概感觉到了Spring Boot的高效和简洁了呢?配置就是如此简单,功能就是如此强大,但通过上面一系列的讲解,你是不是也产生一些疑惑呢,比如:

  1. Spring Boot的WEB应用默认端口就是8080,那这个端口要怎么修改呢?
  2. 为什么会出现"Cannot determine embedded database driver class for database type NONE"这样的错误?(或者说为什么springboot启动时会自动注入数据源和配置jpa)
  3. 为什么@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})就可以解决"Cannot determine embedded database driver class for database type NONE"这样的错误呢?
  4. 既然Spring Boot的WEB应用默认使用的是自带的Tomcat,那要怎么部署到外部的Servlet容器呢?
  5. ...

不急,后续文章将会对这些问题一一解释清楚。

SpringBoot详解(二)-Spring Boot的核心

SpringBoot详解系列文章:
SpringBoot详解(一)-快速入门
SpringBoot详解(二)-Spring Boot的核心
SpringBoot详解(三)-Spring Boot的web开发
SpringBoot详解(四)-优雅地处理日志

Spring Boot的核心

在上篇中我们成功运行了一个简单的web应用,其中有一个注解被轻易的带过了,但它在Spring Boot中是最重要的注解,没有之一,它就是@SpringBootApplication,本篇将对它与Spring Boot的配置进行深入的介绍。

1、@SpringBootApplication

前面已经说过了,一般Spring Boot的Web应用都有一个xxxApplication类,并使用@SpringBootApplication注解标记,作为该web应用的加载入口。那这个@SpringBootApplication注解到底是何方神圣?通过查看它的源码,可以发现它是一个组合注解:

@SpringBootApplication这个Spring Boot核心注解是由其它三个重要的注解组合,分别是: @SpringBootConfiguration 、 @EnableAutoConfiguration 和 @ComponentScan。

1)@SpringBootConfiguration

@SpringBootConfiguration是Spring Boot项目的配置注解,这也是一个组合注解。

通过上图代码,结合前面所讲的知识,不难猜测出@SpringBootConfiguration与@Configuration存在着某种关系,可以认为@SpringBootConfiguration就相当于@Configuration,在Spring Boot项目中推荐使用@SpringBootConfiguration替代@Configuration,不过因为注释长度问题,往往@Configuration较为常用。

2)@EnableAutoConfiguration

@EnableAutoConfiguration注解用于启用自动配置,该注解会使Spring Boot根据项目中依赖的jar包自动配置项目的配置项。

例如:上篇中,我们在编写第一个WEB应用时,就在pom.xml中引入了spring-boot-starter-web的依赖,所以项目中就会引入SpringMVC的依赖,就会自动配置tomcat和SpringMVC。

还有后面使用事务时,会引入spring-boot-starter-jdbc的依赖,让Spring Boot自动配置DataSourceTransactionManager或JpaTransactionManager,等等。。

3)@ComponentScan

@ComponentScan是组件扫描注解,不配置默认扫描@SpringBootApplication所在类的同级目录以及它的子目录(这很重要,后面很应用到这个特性)。当然你也可以自己指定要扫描的包目录,例如:

  1. @ComponentScan(basePackages = "com.lqr.demo1")

2、取消部分自动配置

上面说了,Spring Boot根据项目中依赖的jar包自动配置项目的配置项,而Spring Boot支持的自动配置非常之多,如下图所示(只是其中的一部分):

当自动配置的东西一多了,就容易出问题,上篇中最后出现的"Cannot determine embedded database driver class for database type NONE"错误,就是因为springboot启动时会自动注入数据源和配置jpa,所以我们就需要取消Spring Boot的部分自动配置。至于取消自动配置的方式也相当简单,就是对@SpringBootApplication注解的exclude进行赋值即可,如:

  1. @SpringBootApplication(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
  2. @Controller
  3. public class HelloApplication {
  4. ...
  5. }

其他的取消自动配置以此类推。

3、自定义Banner

这个知识点其实对开发意义不太,但不妨了解下(可以装个逼~~)。在Spring Boot项目启动时,控制台会输出一个"spring>>>"的banner文字图案,如:

这个banner是可以自定义的,自定义的方法很简单:只需要把想输出的文字保存在banner.txt文件中,然后把这个banner.txt放到resources目录下即可:

运行项目,然后控制台就可以输出banner.txt中的文字了。

Text to ASCII Art Generator (TAAG)这个网站可以得到文字图案。

4、Starter pom

Spring Boot为我们提供了简化企业级开发绝大多数场景的start pom(类似于组件),只要使用了对应的starter pom,Spring Boot就会为我们提供自动配置的Bean。

这里官方给出的starter,以下是"好心人"对这些Starter pom做的翻译:

怎么使用?直接在pom.xml中引入依赖即可(不懂请参考上篇中“第一个Web应用”中pom.xml配置的第二部分,或请自行百度)。

5、使用Xml配置文件

常规开发中,java配置方式已经可以完全取代xml配置方式了,但有时我们并不想使用java配置,而是继续沿用之前的xml配置方式,或者出于其他原因,一定要在xml中进行配置,那该怎么办呢,很简单,使用@ImportResource注解即可:

  1. @ImportResource(value = {"classpath:xxx1.xml","classpath:xxx2.xml"})

6、全局配置文件

Spring Boot项目使用一个全局的配置文件application.properties或者是application.yml,在resources目录下或者类路径下的/config下,一般我们放到resources下。

我们知道Spring Boot会根据在pom.xml中依赖的jar包进行自动配置,当我们要对这些jar包对应的框架进行配置又该怎么办呢,没错,可以在全局配置文件(application.properties或者是application.yml)中进行配置,如tomcat的端口配置等。

1)全局配置文件的基本使用(application.properties)

这部分使用application.properties中的书写方式来介绍。

①tomcat端口配置

  1. server.port=8888

②修改Spring MVC拦截路径规则

默认Spring MVC拦截路径规则是/,如果要修改成*.html的话,可以在全局配置文件中进行如下设置:

  1. server.servlet-path=*.html

③视图解析器配置

一样的,Spring Boot也可以通过全局配置文件对视图解析器进行配置:

  1. spring.mvc.view.prefix=/WEB-INF/views/
  2. spring.mvc.view.suffix=.jsp

④日志输出

Spring Boot对各种日志框架都做了支持,我们可以通过配置来修改默认的日志的配置:

  1. #设置日志级别
  2. logging.level.org.springframework=DEBUG

2)全局配置文件的进阶使用(application.yml)

这部分使用application.yml中的书写方式来介绍。

properties与yml文件在形式上有所差别,yml文件的书写方式比较简洁,类似eclipse中package的flag呈现方式(而properties文件则像Hierarchical方式)。如上面properties文件中的属性配置使用yml文件来写:

  1. server:
  2. port: 8080
  3. context-path: /
  4. spring:
  5. mvc:
  6. view:
  7. prefix: /WEB-INF/views/
  8. suffix: .jsp
  9. logging:
  10. level: debug

yml文件在书写时,需要注意一个地方:冒号与值中间是存在空格的!

①自定义属性

全局配置文件并不只是配置Spring Boot中已经存在的属性,我们也可以自定义属性(别忘了,它本身就是一个properties文件),代码需要使用@Value("${xxx}")注解来获取这些属性,如:

②属性引用属性

属性引用属性也简单,使用${xxx}就可以引用配置文件中的属性了。

  1. lqr: 666
  2. content: "${lqr} is six six six"

③属性转对象

这个就比较有看点了,以上面的"server.port: 8080"为例,我们可以认为是Server这个类中有一个port属性,其值为8080。可以使用@ConfigurationProperties(prefix = "属性名前缀")这个注解作为配置文件中属性转对象属性的桥梁,具体如图所示:

Spring Boot的全局配置很强大,同时它可以配置的属性也很多,以上只列出几个常用的属性配置,如需查看完整的全局属性配置,请到spring-boot官方配置文档查看。好了,本篇到此结束,主要介绍了Spring Boot中几个核心注解与自动配置,同时解决上篇中的几个问题,从下篇开始,将针对Spring Boot的web开发进行介绍。

SpringBoot详解(三)-Spring Boot的web开发

SpringBoot详解系列文章:

SpringBoot详解(一)快速入门

SpringBoot详解(二)-Spring Boot的核心

SpringBoot详解(三)-Spring Boot的web开发

一、web基础配置

1、访问静态资源

1)进入规则为 / 时

如果进入SpringMVC的规则为/时,Spring Boot的默认静态资源的路径为:

  1. spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

也就是说,在默认的Spring MVC进入规则下,classpath下的META-INF/resources目录、resources目录、static目录和public目录中的静态资料是可以直接通过 "http: // xxx.com/静态资源" 的方式访问到的。如:

2)进入规则为*.xxx 或者 不指定静态文件路径时

如果进入SpringMVC的规则为*.xxx时(如:*.html),则上述目录下的静态资源将无法直接访问,需要将静态资源放置到webapp下的static目录中即可通过 "http://xxx.com/static/静态资源" 访问。此外,默认不配置SpringMVC的规则下也可以如此访问,也就是说这种访问静态资源的方式是通用的。如图所示:

2、自定义拦截器

增加一个拦截器,需要通过继承WebMvcConfigurerAdapter然后重写父类中的方法进行扩展。

  1. @Configuration
  2. public class MySpringMvcConfig extends WebMvcConfigurerAdapter {
  3. @Override
  4. public void addInterceptors(InterceptorRegistry registry) {
  5. HandlerInterceptor handlerInterceptor = new HandlerInterceptor() {
  6. @Override
  7. public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
  8. System.out.println("自定义拦截器。。。");
  9. return true;
  10. }
  11. @Override
  12. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  13. }
  14. @Override
  15. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  16. }
  17. };
  18. // 添加拦截器并设置拦截规则
  19. registry.addInterceptor(handlerInterceptor).addPathPatterns("/**");
  20. }
  21. }

3、自定义消息转化器

自定义消息转化器有两种实现方式,一种是@Bean方式,另一种是自定义拦截器。

1)@Bean方式

只需要在@Configuration的类中添加消息转化器的@bean加入到Spring容器,就会被Spring Boot自动加入到容器中。

  1. // spring boot默认就有消息转化器,其编码格式为utf-8
  2. @Bean
  3. public StringHttpMessageConverter stringHttpMessageConverter() {
  4. StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
  5. return stringHttpMessageConverter;
  6. }

2)自定义拦截器方式

WebMvcConfigurerAdapter的功能很强大,除了可以配置拦截器外,还可以配置消息转换器。

  1. @Configuration
  2. public class MySpringMvcConfig extends WebMvcConfigurerAdapter {
  3. @Override
  4. public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  5. StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
  6. converters.add(stringHttpMessageConverter);
  7. }
  8. }

4、读取外部的配置文件

  1. @Configuration
  2. @PropertySource(value = { "classpath:jdbc.properties", "classpath:base.properties" }, ignoreResourceNotFound = true)
  3. public class 任意类 {
  4. }

5、Druid DataSource的配置

Druid提供了一个高效、功能强大、可扩展性好的数据库连接池,常用于替换DBCP和C3P0。但在Spring Boot上配置比较“恶心”,这里就简单的贴出个人参照网上的配置代码,不必深究。

1)引入依赖

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>druid</artifactId>
  4. <version>1.0.11</version>
  5. </dependency>

2)jdbc.properties

项目中一般会创建一个jdbc.properties文件来记录数据库的连接信息。

  1. #MySQL
  2. jdbc.url=jdbc:mysql://127.0.0.1:3306/dbxxx?useUnicode=true&characterEncoding=utf-8
  3. jdbc.username=root
  4. jdbc.password=123456
  5. #Druid
  6. jdbc.initialSize=0
  7. jdbc.minIdle=0
  8. jdbc.maxActive=150

3)配置Druid数据源

建议将配置Druid数据源的操作放在@SpringBootApplication注解的类中。

  1. @SpringBootApplication
  2. @Configuration
  3. @PropertySource(value = {"classpath:jdbc.properties"})
  4. public class MyWebApplication{
  5. @Value("${jdbc.url}")
  6. public String jdbcUrl;
  7. @Value("${jdbc.username}")
  8. public String jdbcUsername;
  9. @Value("${jdbc.password}")
  10. public String jdbcPassword;
  11. @Value("${jdbc.initialSize}")
  12. public int jdbcInitialSize;
  13. @Value("${jdbc.minIdle}")
  14. public int jdbcMinIdle;
  15. @Value("${jdbc.maxActive}")
  16. public int jdbcMaxActive;
  17. @Bean
  18. public ServletRegistrationBean druidServletRegistrationBean() {
  19. ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
  20. servletRegistrationBean.setServlet(new StatViewServlet());
  21. servletRegistrationBean.addUrlMappings("/druid/*");
  22. return servletRegistrationBean;
  23. }
  24. @Bean
  25. public FilterRegistrationBean duridFilterRegistrationBean() {
  26. FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
  27. filterRegistrationBean.setFilter(new WebStatFilter());
  28. HashMap<String, String> initParams = new HashMap<>();
  29. // 设置忽略请求
  30. initParams.put("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
  31. filterRegistrationBean.setInitParameters(initParams);
  32. filterRegistrationBean.addUrlPatterns("/*");
  33. return filterRegistrationBean;
  34. }
  35. @Bean(initMethod = "init", destroyMethod = "close")
  36. public DruidDataSource druidDataSource() {
  37. DruidDataSource druidDataSource = new DruidDataSource();
  38. druidDataSource.setUrl(jdbcUrl);
  39. druidDataSource.setUsername(jdbcUsername);
  40. druidDataSource.setPassword(jdbcPassword);
  41. druidDataSource.setInitialSize(jdbcInitialSize);
  42. druidDataSource.setMinIdle(jdbcMinIdle);
  43. druidDataSource.setMaxActive(jdbcMaxActive);
  44. return druidDataSource;
  45. }
  46. }

之后就可以通过@AutoWried注解得到数据源(druidDataSource)了。

6、数据库框架集成

1)jpa集成

Jpa在使用上跟Hibernate很像,因为它们之前的关系非同一般,有兴趣可以看看《Hibernate与Jpa的关系,终于弄懂》这篇文章。Spring Boot对jpa的支持也是很好的,配置起来非常简单。

在pom.xml中引用jpa及数据库驱动(如:mysql)依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jpa</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>mysql</groupId>
  7. <artifactId>mysql-connector-java</artifactId>
  8. </dependency>

在application.yml文件中配置

  1. spring:
  2. datasource:
  3. driver-class-name: com.mysql.jdbc.Driver
  4. url: jdbc:mysql://127.0.0.1/dbgirl
  5. username: root
  6. password: 123456
  7. jpa:
  8. hibernate:
  9. ddl-auto: update #第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
  10. show-sql: true

2)MyBatis集成

Mybatis和Spring Boot的整合有两种方式:

第一种:使用mybatis官方提供的Spring Boot整合包实现,地址:spring-boot-starter

第二种:使用mybatis-spring整合的方式,也就是我们传统的方式

这里推荐并使用第二种方式,因为可以很方便的控制Mybatis的各种配置。这里假设你已经配置过数据源了(数据源可以是druid、dbcp、c3p0...)。

首先,需要在pom.xml文件中引用mybatis依赖

  1. <dependency>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.mybatis</groupId>
  8. <artifactId>mybatis-spring</artifactId>
  9. <version>1.2.2</version>
  10. </dependency>

然后,创建一个Mybatis的配置类:

  1. @Configuration
  2. public class MybatisConfig {
  3. @Autowired
  4. DruidDataSource druidDataSource;
  5. @Bean
  6. @ConditionalOnMissingBean// 当Spring容器中没有SqlSessionFactoryBean时才创建
  7. public SqlSessionFactoryBean sqlSessionFactoryBean() {
  8. SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
  9. // 设置数据源
  10. sqlSessionFactory.setDataSource(druidDataSource);
  11. // 设置别名扫描包
  12. sqlSessionFactory.setTypeAliasesPackage("com.lqr.demo3.bean");
  13. // 设置Mybatis的配置文件位置
  14. PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  15. Resource mybatisConfigXml = resolver.getResource("classpath:mybatis-config.xml");
  16. sqlSessionFactory.setConfigLocation(mybatisConfigXml);
  17. return sqlSessionFactory;
  18. }
  19. }

最后,创建Mapper接口的扫描类MapperScannerConfig:

  1. @Configuration
  2. @AutoConfigureAfter(MybatisConfig.class)// Mybatis的扫描配置必须在SqlSessionFactory被创建之后
  3. public class MapperScanConfig {
  4. @Bean
  5. public MapperScannerConfigurer mapperScannerConfigurer() {
  6. MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
  7. mapperScannerConfigurer.setBasePackage("com.lqr.demo3.mapper");
  8. return mapperScannerConfigurer;
  9. }
  10. }

7、设置事务管理

Spring Boot中推荐使用@Transactional注解来申明事务。

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-jdbc</artifactId>
  4. </dependency>

当引入jdbc依赖之后,Spring Boot会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager,所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。

  1. @Service
  2. @Transactional
  3. public class GirlService {
  4. @Transactional
  5. public void insertGirl() {
  6. Girl girlA = new Girl();
  7. girlA.setCupSize("A");
  8. girlA.setAge(18);
  9. girlRespository.save(girlA);
  10. }
  11. }

@Transactional不仅可以注解在方法,也可以注解在类上。当注解在类上时,意味着此类所有public方法都会开启事务。如果类级别和方法级别同时使用了@Transactional注解,则使用在类级别的注解会重载方法级别的注解。

8、开启jsp支持

Spring boot默认内嵌的tomcat是不支持jsp页面的,如果项目中使用到了jsp,需要导入如下依赖才能正常访问。

  1. <dependency>
  2. <groupId>org.apache.tomcat.embed</groupId>
  3. <artifactId>tomcat-embed-jasper</artifactId>
  4. <scope>provided</scope>
  5. </dependency>

二、Web编码进阶

这部分可能跟Spring Boot的关系并不是很大(或者说,并非Spring Boot特有),但很值得我们在编码方面作为参考。

1、Spring MVC中新的注解

1)@RestController

现在的Web项目已经越来越趋向于将后端与前端分别开发了,如果贵公司的项目就是使用json来进行前后端交互,且使用Spring MVC来开发的话,就一定会用到下面这2个注解:

  1. @Controller
  2. @ResponseBody
  3. public class GirlController {
  4. ...
  5. }

而在Spring MVC4之后,我们可以使用@RestController 注解来开发基于Spring MVC4的REST风格的JSON服务。

通俗的说就是@RestController = @Controller + @ResponseBody。

@Controller和@RestController的区别:

如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。 例如:本来应该到success.jsp页面的,则其显示success.

2)http组合注解

Spring4.3中引进了{@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping},来帮助简化常用的HTTP方法的映射,并更好地表达被注解方法的语义。

  1. @GetMapping =>
  2. @RequestMapping(value = "/xxx",method = RequestMethod.GET)
  3. @PostMapping =>
  4. @RequestMapping(value = "/xxx",method = RequestMethod.POST)
  5. @PutMapping =>
  6. @RequestMapping(value = "/xxx",method = RequestMethod.PUT)
  7. @DeleteMapping =>
  8. @RequestMapping(value = "/xxx",method = RequestMethod.DELETE)
  9. ...

2、数据校验

Web开发中,对从前端传过来的数据做数据校验已经是家常便饭的事了,但如果校验的数据很多,那么,一方面在开发上就需要做很多if判断,另一方面则是代码上显得不再简洁。其实,使用@Valid + BindingResult就可以优雅地解决这样的问题。使用示例如下:

1)@Valid + BindingResult

首先,使用一个Java Bean来接收前端提交的数据。在这个Java Bean之前加上@Valid,在这个Java Bean之后加上BindingResult(BindingResult参数必须紧跟在@Valid参数之后。)

  1. /**
  2. * 添加一个女生
  3. */
  4. @PostMapping(value = "/girls")
  5. public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult) {
  6. if (bindingResult.hasErrors()) {
  7. return ResultUtils.error(-1, bindingResult.getFieldError().getDefaultMessage());
  8. }
  9. return ResultUtils.success(girlRespository.save(girl));
  10. }

2)设置校验规则

然后,需要在@Valid注解的Java Bean中,使用各种"规则注解"对其中的属性进行校验规则的设定。示例如下:

  1. public class Girl {
  2. private Integer id;
  3. @NotBlank(message = "这个字段必传")
  4. private String cupSize;
  5. @Min(value = 18, message = "未成年少女禁止入内")
  6. private Integer age;
  7. @NotNull(message = "金额必传")
  8. private Double money;
  9. ...
  10. }

示例中,"规则注解"的message值可以在Controller中通过bindingResult.getFieldError().getDefaultMessage()获取。

这类用于数据校验的注解还有很多,有兴趣的可以好好研究一下:

注解 类型 说明
@AssertFalse Boolean,boolean 验证注解的元素值是false
@AssertTrue Boolean,boolean 验证注解的元素值是true
@NotNull 任意类型 验证注解的元素值不是null
@Null 任意类型 验证注解的元素值是null
@Min(value=值) BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型 验证注解的元素值大于等于@Min指定的value值
@Max(value=值) 和@Min要求一样 验证注解的元素值小于等于@Max指定的value值
@DecimalMin(value=值) 和@Min要求一样 验证注解的元素值大于等于@ DecimalMin指定的value值
@DecimalMax(value=值) 和@Min要求一样 验证注解的元素值小于等于@ DecimalMax指定的value值
@Digits(integer=整数位数, fraction=小数位数) 和@Min要求一样 验证注解的元素值的整数位数和小数位数上限
@Size(min=下限, max=上限) 字符串、Collection、Map、数组等 验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
@Past java.util.Date,java.util.Calendar;Joda Time类库的日期类型 验证注解的元素值(日期类型)比当前时间早
@Future 与@Past要求一样 验证注解的元素值(日期类型)比当前时间晚
@NotBlank CharSequence子类型 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格
@Length(min=下限, max=上限) CharSequence子类型 验证注解的元素值长度在min和max区间内
@NotEmpty CharSequence子类型、Collection、Map、数组 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@Range(min=最小值, max=最大值) BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型 验证注解的元素值在最小值和最大值之间
@Email(regexp=正则表达式,flag=标志的模式) CharSequence子类型(如String) 验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式
@Pattern(regexp=正则表达式,flag=标志的模式) String,任何CharSequence的子类型 验证注解的元素值与指定的正则表达式匹配
@Valid 任何非原子类型 指定递归验证关联的对象;如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

3、面积切面编程(AOP配置)

AOP是Spring中一大核心,若在SpringBoot中要使用AOP只需两步:

1)引入AOP的starter依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>

2)编写切面类

  1. @Aspect
  2. @Component
  3. public class HttpAspect {
  4. private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
  5. @Pointcut("execution(public * com.lqr.controller.GirlController.*(..))")
  6. public void log() {
  7. }
  8. @Before("log()")
  9. public void deBefore(JoinPoint joinPoint) {
  10. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  11. HttpServletRequest request = attributes.getRequest();
  12. // url
  13. logger.info("url={}", request.getRequestURL());
  14. // method
  15. logger.info("method={}", request.getMethod());
  16. // ip
  17. logger.info("ip={}", request.getRemoteAddr());
  18. // 类方法
  19. logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
  20. // 参数
  21. logger.info("args={}", joinPoint.getArgs());
  22. }
  23. @After("log()")
  24. public void doAfter() {
  25. logger.info("doAfter...");
  26. }
  27. @AfterReturning(returning = "object", pointcut = "log()")
  28. public void doAfterReturning(Object object) {
  29. if (object != null)
  30. logger.info("response={}", object.toString());
  31. }
  32. }

4、统一异常处理(配置通知Advice)

1)自定义异常

这里之所以继承RuntimeException,是为了方便事务回滚。而自定义异常的好处在于:一方面可以使代码语义化,另一方面使得我们编码更加方便。

  1. public class GirlException extends RuntimeException {
  2. private Integer code;
  3. public GirlException(ResultEnum resultEnum) {
  4. super(resultEnum.getMsg());
  5. this.code = resultEnum.getCode();
  6. }
  7. public Integer getCode() {
  8. return code;
  9. }
  10. public void setCode(Integer code) {
  11. this.code = code;
  12. }
  13. }

2)配置全局异常捕获器

使用全局异常捕获器,一方面可以捕获到整个项目中的Exception及其子类(包含RuntimeException等),另一方面可以对异常进行统一处理并返回统一的数据格式,为前端提供友好的数据交互。

  1. @ControllerAdvice
  2. public class ExceptionHandle {
  3. private final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
  4. @ExceptionHandler(value = Exception.class)
  5. @ResponseBody
  6. public Result handle(Exception e) {
  7. if (e instanceof GirlException) {
  8. GirlException girlException = (GirlException) e;
  9. return ResultUtils.error(girlException.getCode(), girlException.getMessage());
  10. } else {
  11. logger.error("【系统异常】{}", e);
  12. return ResultUtils.error(-1, "未知错误");
  13. }
  14. }
  15. }

三、开发与生产

1、热部署

Web开发中,没有热部署怎么能行呢?所以,下面就介绍下Spring Boot的热部署配置。

1)在pom.xml中配置热部署需要的依赖与插件

  1. <dependencies>
  2. ...
  3. <!--spring boot 热部署-->
  4. <dependency>
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-devtools</artifactId>
  7. <optional>true</optional>
  8. </dependency>
  9. </dependencies>
  10. <build>
  11. <plugins>
  12. <!--spring boot 热部署-->
  13. <plugin>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-maven-plugin</artifactId>
  16. <configuration>
  17. <fork>true</fork>
  18. </configuration>
  19. </plugin>
  20. </plugins>
  21. ...
  22. </build>

2)开启自动编译

打开Idea的Settings界面,找到"Build,Execution,Depolyment",在Compiler中将"Build project automatically"打钩。

3)修改pom.xml的维护(Maintenance)登记项

使用快捷键 "ctrl+shift+alt+/" 打开pom.xml的维护(Maintenance)菜单,找到登记(registry)项,单击打开。

4)允许应用程序运行时自动编译

在登记(registry)中找到"compiler.automake.allow.when.app.running"这一项打钩,关闭。最后重启项目即可!!!

2、发布到独立的tomcat中运行

尽管Spring Boot项目会内置一个tomcat,仅只需通过一个简单的指令便可启动项目,但在生产环境下,我们还是习惯将项目发布到第三外的servlet容器中,下面将介绍如果将一个Spring Boot项目团部署到第三方tomcat中运行。

1)修改工程的打包方式为war

2)将spring-boot-starter-tomcat的范围设置为provided

spring-boot-starter-tomcat是Spring Boot默认就会配置的,即上面说到的内嵌tomcat,将其设置为provided是在打包时会将该包(依赖)排除,因为要放到独立的tomcat中运行,Spring Boot内嵌的Tomcat是不需要用到的。

  1. <!--spring boot tomcat(默认可以不用配置,但当需要把当前web应用布置到外部servlet容器时就需要配置,并将scope配置为provided)-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-tomcat</artifactId>
  5. <scope>provided</scope>
  6. </dependency>

3)修改代码,设置启动配置

需要继承SpringBootServletInitializer,并重写configure()方法,将Spring Boot的入口类设置进去。

  1. // 若要部署到外部servlet容器,需要继承SpringBootServletInitializer并重写configure()
  2. @SpringBootApplication
  3. @Configuration
  4. public class MyWebApplication extends SpringBootServletInitializer
  5. {
  6. @Override
  7. protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
  8. // 设置启动类,用于独立tomcat运行的入口
  9. return builder.sources(MyWebApplication.class);
  10. }
  11. }

4)打war包并部署到tomcat

微信公众号【黄小斜】大厂程序员,互联网行业新知,终身学习践行者。关注后回复「Java」、「Python」、「C++」、「大数据」、「机器学习」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「笔试」、「面试」、「面经」、「计算机基础」、「LeetCode」 等关键字可以获取对应的免费学习资料。 

走进JavaWeb技术世界16:极简配置的SpringBoot的更多相关文章

  1. 走进JavaWeb技术世界3:JDBC的进化与连接池技术

    走进JavaWeb技术世界3:JDBC的进化与连接池技术 转载公众号[码农翻身] 网络访问 随着 Oracle, Sybase, SQL Server ,DB2,  Mysql 等人陆陆续续住进数据库 ...

  2. 走进JavaWeb技术世界1:JavaWeb的由来和基础知识

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  3. 走进JavaWeb技术世界14:Mybatis入门

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  4. 走进JavaWeb技术世界7:Tomcat和其他WEB容器的区别

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  5. 走进JavaWeb技术世界开篇:JavaWeb技术汇总

    微信公众号[Java技术江湖]一位阿里 Java 工程师的技术小站.(关注公众号后回复”Java“即可领取 Java基础.进阶.项目和架构师等免费学习资料,更有数据库.分布式.微服务等热门技术学习视频 ...

  6. 走进JavaWeb技术世界9:Java日志系统的诞生与发展

    本文转自[码农翻身] ## 一个著名的日志系统是怎么设计出来的? # 1前言 Java帝国在诞生之初就提供了集合.线程.IO.网络等常用功能,从C和C++领地那里吸引了大量程序员过来加盟,但是却有意无 ...

  7. 走进JavaWeb技术世界2:JSP与Servlet的曾经与现在

    转载自:码农翻身 转自: 刘欣 码农翻身 1周前 我是Servlet, 由于很多框架把我深深地隐藏了起来,我变得似乎无关紧要了,很多人也选择性的把我给遗忘了. 其实,我还活得好好的呢, 只不过是从前台 ...

  8. 走进JavaWeb技术世界1:Web后端与J2EE的由来

    转自:微信公众号 码农翻身 这个问题来自于QQ网友,一句两句说不清楚,索性写个文章. 我刚开始做Web开发的时候,根本没有前端,后端之说. 原因很简单,那个时候服务器端的代码就是一切:接受浏览器的请求 ...

  9. 走进JavaWeb技术世界5:初探Tomcat的HTTP请求过程

    初探Tomcat的HTTP请求过程 前言:1.作为Java开发人员,大多都对Tomcat不陌生,由Apache基金会提供技术支持与维护,因为其免费开源且易用,作为Web服务器深受市场欢迎,所以有必要对 ...

随机推荐

  1. mac os安装mtr

    MTR是Linux平台上一款非常好用的网络诊断工具,集成了traceroute.ping.nslookup的功能,用于诊断网络状态非常有用 现使用的方法是下载pkg包手动安装 mtr的pkg下载地址 ...

  2. Python实现YOLO目标检测

    作者:R语言和Python学堂 链接:https://www.jianshu.com/p/35cfc959b37c 1. 什么是目标检测? YOLO目标检测的一个示例 啥是目标检测? 拿上图 (用YO ...

  3. Vue指令之`v-text`和`v-html`

    v-text: 没有加载闪烁问题,它会覆盖元素中原本的内容,但是插值表达式,只会替换自己的这个占位符,不会把 整个元素的内容清空. v-html: 使用v-html可以把标签元素也能显示在元素上 &l ...

  4. springcloud 之Ribbon客户端负载均衡配置使用

    pom.xml添加配置说明:这里服务注册与发现用的是Eureka,所以消费者端需要引入eureka,使用EurekaClient来调用服务 <dependency> <groupId ...

  5. Typora数学公式

    LaTeX编辑数学公式基本语法元素 LaTeX中的数学模式有两种形式: inline 和 display. 前者是指在正文插入行间数学公式,后者独立排列,可以有或没有编号. 行间公式(inline) ...

  6. Django的安装和使用

    一.安装 ① 命令行安装 # 命令提示符下 # 方式一 pip install django==1.11.16 -i https://pypi.tuna.tsinghua.edu.cn/simple ...

  7. xlsxwriter写入Excel文件

    #coding=utf-8 import xlsxwriter #加载包 myWorkbook = xlsxwriter.Workbook(opath+'/'+file_name+'.xlsx') # ...

  8. querySelector和getElementById方法的区别

    一.querySelector() 的定义 querySelector() 方法选择指定 CSS 选择器的第一个元素 querySelectorAll() 方法选择指定的所有元素 二.与 getEle ...

  9. Write-Off

    What is a Write-Off? Write-offis an accounting term referring to an action whereby the book value of ...

  10. 手写butterknife来剖析其原理

    基本使用: 对于butterknife库我想基本上都非常熟了,如今在项目中用它也用得非常之频繁了,不过为了学习的完整性,先来简单的回顾一下基本用法,先新建一个工程: 然后给textview增加一个点击 ...