原文:https://dzone.com/articles/why-springboot
作者:SivaPrasadReddyKatamreddy
译者:Oopsguy本文将介绍各种Spring的配置方式,帮助你了解配置Spring应用的复杂性。
Spring是一个非常受欢迎的Java框架,它用于构建Web和企业应用。不像许多其他框架只关注一个领域,Spring框架提供了各种功能,通过项目组合来满足当代业务需求。
Spring框架提供了多种灵活的方式来配置Bean。例如XML、注解和Java配置。随着功能数量的增加,复杂性也随之增加,配置Spring应用将变得乏味且容易出错。
针对上述问题,Spring团队创建了SpringBoot以解决配置复杂的问题。
但在开始将SpringBoot之前,我们将快速浏览一下Spring框架,看看SpringBoot正在决解什么样的问题。
在本文中,我们将介绍:
Spring框架概述 一个使用了SpringMVC和JPA(Hibernate)的Web应用 快速尝试SpringBoot如果你是一名Java开发人员,那你很可能听说过Spring框架,甚至可能已经在自己的项目中使用了它。Spring框架主要是作为依赖注入容器,但它的作用远不止这些。
连同Spring一起的,还有许多其他的Spring姊妹项目,可以帮助构建满足当代业务需求的应用:
SpringData:简化关系数据库和NoSQL数据存储的数据访问 SpringBatch:提供强大的批处理能力 SpringSecurity:用于保护应用安全框架 SpringSocial:支持与Facebook、Twitter、Linkedin、Github等社交网站集成 SpringIntegration:实现了企业集成模式,以便于使用轻量级消息和声明式适配器与其他企业应用集成还有许多其他有趣的项目涉及各种其他当代应用开发需求。有关更多信息,请查看http://spring.io/projects。
刚开始,Spring框架只提供了基于XML的方式来配置bean。后来,Spring引入了基于XML的DSL、注解和基于Java配置的方式来配置bean。
让我们快速了解一下这些配置风格的大概模样。
Spring提供了多种方式来做同样的事,我们甚至可以混合使用,在同一个应用中使用基于Java配置和注解配置的方式。
这非常灵活,但它有好有坏。刚开始接触Spring的新人可能会困惑应该使用哪一种方式。到目前为止,Spring团队建议使用基于Java配置的方式,因为它更具灵活性。
没有哪一种方案是万能,我们应该根据自己的需求来选择合适的方式。
到此,你已经了解了多种SpringBean配置方式的基本形式。
让我们快速地了解一下典型的SpringMVC+JPA/HibernateWeb应用的配置。
在了解SpringBoot是什么以及它提供了什么样的功能之前,我们先来看一下典型的SpringWeb应用配置是怎样的,哪些是痛点,然后我们将讨论SpringBoot是如何解决这些问题的。
首先需要做的是配置pom.xml中所需的依赖:
<?xmlversion="1.0"encoding="UTF-8"?> <projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sivalabs</groupId> <artifactId>springmvc-jpa-demo</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>springmvc-jpa-demo</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.9.2.RELEASE</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.13</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.13</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.13</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.190</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.11.Final</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring4</artifactId> <version>2.1.4.RELEASE</version> </dependency> </dependencies> </project>我们配置了所有的Mavenjar依赖,包括SpringMVC、SpringDataJPA、JPA/Hibernate、Thymeleaf和Log4j。
在AppConfig.java配置类中,我们完成了以下操作:
使用@Configuration注解标记为一个Spring配置类 使用@EnableTransactionManagement开启基于注解的事务管理 配置@EnableJpaRepositories指定去哪查找SpringDataJPA资源库(repository) 使用@PropertySource注解和PropertySourcesPlaceholderConfigurerBean定义配置PropertyPlaceHolderbean从application.properties文件加载配置 为DataSource、JAP的EntityManagerFactory和JpaTransactionManager定义Bean 配置DataSourceInitializerBean,在应用启动时,执行data.sql脚本来初始化数据库我们需要在application.properties中完善配置,如下所示:
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test jdbc.username=root jdbc.password=admin init-db=true hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.hbm2ddl.auto=update我们可以创建一个简单的SQL脚本data.sql来将演示数据填充到USER表中:
deletefromuser; insertintouser(id,name)values(1,Siva); insertintouser(id,name)values(2,Prasad); insertintouser(id,name)values(3,Reddy);我们可以创建一个附带基本配置的log4j.properties文件,如下所示:
log4j.rootCategory=INFO,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p%t%c{2}:%L-%m%n log4j.category.org.springframework=INFO log4j.category.com.sivalabs=DEBUG我们必须配置Thymleaf的ViewResolver、处理静态资源的ResourceHandler和处理I18n的MessageSource等。
@Configuration @ComponentScan(basePackages={"com.sivalabs.demo"}) @EnableWebMvc publicclassWebMvcConfigextendsWebMvcConfigurerAdapter { @Bean publicTemplateResolvertemplateResolver(){ TemplateResolvertemplateResolver=newServletContextTemplateResolver(); templateResolver.setPrefix("/WEB-INF/views/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode("HTML5"); templateResolver.setCacheable(false); returntemplateResolver; } @Bean publicSpringTemplateEnginetemplateEngine(){ SpringTemplateEnginetemplateEngine=newSpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver()); returntemplateEngine; } @Bean publicThymeleafViewResolverviewResolver(){ ThymeleafViewResolverthymeleafViewResolver=newThymeleafViewResolver(); thymeleafViewResolver.setTemplateEngine(templateEngine()); thymeleafViewResolver.setCharacterEncoding("UTF-8"); returnthymeleafViewResolver; } @Override publicvoidaddResourceHandlers(ResourceHandlerRegistryregistry) { registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); } @Override publicvoidconfigureDefaultServletHandling(DefaultServletHandlerConfigurerconfigurer) { configurer.enable(); } @Bean(name="messageSource") publicMessageSourceconfigureMessageSource() { ReloadableResourceBundleMessageSourcemessageSource=newReloadableResourceBundleMessageSource(); messageSource.setBasename("classpath:messages"); messageSource.setCacheSeconds(5); messageSource.setDefaultEncoding("UTF-8"); returnmessageSource; } }在WebMvcConfig.java配置类中,我们完成了以下操作:
使用@Configuration注解标记为一个Spring配置类 使用@EnableWebMvc注解启用基于注解的SpringMVC配置 通过注册TemplateResolver、SpringTemplateEngine和`hymeleafViewResolverBean来配置Thymeleaf视图解析器 注册ResourceHandlerBean将URI为/resource/**的静态资源请求定位到/resource/目录下 配置MessageSourceBean从classpath中加载messages-{国家代码}.properties文件来加载I18n配置现在我们没有配置任何I18n内容,因此需要在src/main/resources文件夹下创建一个空的messages.properties文件。
在Servlet3.x规范之前,我们必须在web.xml中注册Servlet/Filter。由于当前是Servlet3.x环境,我们可以使用ServletContainerInitializer以编程的方式注册Servlet/Filter。
SpringMVC提供了一个惯例类AbstractAnnotationConfigDispatcherServletInitializer来注册DispatcherServlet。
publicclassSpringWebAppInitializerextendsAbstractAnnotationConfigDispatcherServletInitializer { @Override protectedClass<?>[]getRootConfigClasses() { returnnewClass<?>[]{AppConfig.class}; } @Override protectedClass<?>[]getServletConfigClasses() { returnnewClass<?>[]{WebMvcConfig.class}; } @Override protectedString[]getServletMappings() { returnnewString[]{"/"}; } @Override protectedFilter[]getServletFilters(){ returnnewFilter[]{newOpenEntityManagerInViewFilter()}; } }在SpringWebAppInitializer.java配置类中,我们完成了以下操作:
我们将AppConfig.class配置为RootConfigurationClass,它将成为包含所有子上下文(DispatcherServlet)共享的Bean定义的父ApplicationContext 我们将WebMvcConfig.class配置为ServletConfigClass,它是包含了WebMvcBean定义的子ApplicationContext 我们将/配置为ServletMapping,这意味所有的请求将由DispatcherServlet处理 我们将OpenEntityManagerInViewFilter注册为Servlet过滤器,以便在渲染视图时可以延迟加载JPAEntity的延迟集合为User实体创建一个JPA实体User.java和一个SpringDataJPA资源库。
@Entity publicclassUser { @Id@GeneratedValue(strategy=GenerationType.AUTO) privateIntegerid; privateStringname; //settersandgetters } publicinterfaceUserRepositoryextendsJpaRepository<User,Integer> { }创建一个SpringMVC控制器来处理URL为/,并渲染一个用户列表。
@Controller publicclassHomeController { @AutowiredUserRepositoryuserRepo; @RequestMapping("/") publicStringhome(Modelmodel) { model.addAttribute("users",userRepo.findAll()); return"index"; } }所有都配置好了,可以启动应用了。但在此之前,我们需要在IDE中下载并配置像Tomcat、Jetty或者Wildfly等服务器。
你可以下载Tomcat8并配置在你喜欢的IDE中,之后运行应用并将浏览器指向http://localhost:8080/springmvc-jpa-demo。你应该看到一个以表格形式展示的用户详细信息列表。
真激动,我们做到了!
但是等等,做了那么多的工作仅仅是为了从数据库中获取用户信息然后展示一个列表?
让我们坦诚公平地来看待,所有的这些配置不仅仅是为了这次示例,这些配置也是其他应用的基础。
但我还是想说,如果你想早点起床跑步,那对不起,你还有太多的工作要做。
另一个问题是,假设你想要开发另一个SpringMVC应用,你会使用类似的技术栈?
好,你要做的就是复制粘贴配置并调整它。对么?请记住一件事:如果你一次又一次地做同样的事情,你应该寻找一种自动化的方式来完成它。
除了一遍又一遍地编写相同的配置,你还能发现其他问题么?
这样吧,让我列出我从中发现的问题。
你需要寻找特定版本的Spring以便完全兼容所有的类库,并进行配置。 我们花费了95%的时间以同样的方式配置DataSource、EntityManagerFactory和TransactionManager等bean。如果Spring能自动帮我们完成这些事,是不是非常棒? 同样,我们大多时候以同样的方式配置SpringMVC的bean,比如ViewResolver、MessageResource等。如果Spring可以自动帮我做这些事情,那真的是非!常!棒!
想象一下,如果Spring能够自动配置bean呢?如果你可以使用简单的自定义配置方式来定义自动配置又将会怎么?
例如,你可以将DispatcherServlet的url-pattern映射到/app/,而不是/。你可以将Theymeleaf视图放在/WEB-INF/template/文件夹下,而不是/WEB-INF/views中。
所以基本上你希望Spring能自动执行这些操作,Spring它有没有提供一个简单灵活的方式来覆盖掉默认配置呢?
很好,你即将踏进入SpringBoot的世界,你将梦想成真!
欢迎来到SpringBoot世界!SpringBoot正是你一直在寻找的。它可以自动为你完成某些事情,但如果有必要,你可以覆盖掉这些默认配置。
与其夸夸而谈,不如来点案例实战。
创建一个Maven项目并配置如下依赖:
<?xmlversion="1.0"encoding="UTF-8"?> <projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sivalabs</groupId> <artifactId>hello-springboot</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>hello-springboot</name> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.2.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> </project>太神奇了,我们的pom.xml文件一下子变小了许多!
你可以将相同的data.sql文件拷贝到src/main/resources文件加中。
与springmvc-jpa-demo应用一样,创建User.java、UserRepository.java和HomeController.java。
从springmvc-jpa-demo项目中复制之前创建的/WEB-INF/views/index.html到src/main/resources/template文件夹中。
创建一个含有main方法的Java类Application.java,如下所示:
@SpringBootApplication publicclassApplication { publicstaticvoidmain(String[]args) { SpringApplication.run(Application.class,args); } }现在把Application.java当作一个Java应用运行,并将你的浏览其指向http://localhost:8080/。
不出意外,你将看到一个以表格的形式展示的用户列表,真的很酷!
我仿佛听到你在喊:“这到底发生了什么事?”。
让我解释刚刚所发生的事情。
简单的依赖管理
首先要注意的是我们使用了一些名为spring-boot-start-*的依赖。记住我说过我花费95%的时间来配置同样的配置。当你在开发SpringMVC应用时添加了spring-boot-start-web依赖,它已经包含了一些常用的类库,比如spring-webmvc、jackson-json、validation-api和tomcat等。 我们添加了spring-boot-starter-data-jpa依赖。它包含了所有的spring-data-jpa依赖,并且还添加了Hibernate库,因为很多应用使用Hibernate作为JPA实现。自动配置
spring-boot-starter-web不仅添加了上面所说的这些库,还配置了经常被注册的bean,比如DispatcherServlet、ResourceHandler和MessageSource等bean,并且应用了合适的默认配置。 我们还添加了spring-boot-starter-Thymeleaf,它不仅添加了Thymeleaf的依赖,还自动配置了ThymeleafViewResolverbean。 虽然我们没有定义任何DataSource、EntityManagerFactory和TransactionManager等bean,但它们可以被自动创建。怎么样?如果在classpath下没有任何内存数据库驱动,如H2或者HSQL,那么SpringBoot将自动创建一个内存数据库的DataSource,然后应用合适的默认配置自动注册EntityManagerFactory和TransactionManager等bean。但是我们使用的是MySQL,因此我们需要明确提供MySQL的连接信息。我们已经在application.properties文件中配置了MySQL连接信息,SpringBoot将应用这些配置来创建DataSource。支持嵌入式Servlet容器
最重要且最让人惊讶的是,我们创建了一个简单的Java类,标记了一个神奇的注解@SpringApplication,它有一个main方法。通过运行main方法,我们可以启动这个应用,并可通过http://localhost:8080/来访问。 Servlet容器来自哪里?我们添加了spring-boot-starter-web,它会自动引入spring-boot-starter-tomcat。当我们运行main()方法时,它将tomcat作为一个嵌入式容器启动,我们不需要部署自己的应用到外部安装好的tomcat上。
顺便说一句,你看到我们在pom.xml中配置的打包类型是jar而不是war,真有趣!
**非常好,但如果我想使用jetty服务器而不是tomcat呢?**很简单,只需要从spring-boot-starter-web中排除掉sprig-boot-starter-tomcat,并包含spring-boot-starter-jetty依赖即可。
就是这样。
但这看起来真的很神奇!
我可以想象此时你在想什么。你正在感叹SpringBoot真的很酷,它为你自动完成了很多事情。但是,你还没了完全明白它幕后是怎样工作的,对不对?
我可以理解,就像观看魔术表演,过程非常有趣,但你不知道魔术师是如何做到的。软件开发则不一样,你不用担心,未来我们还将看到各种新奇的东西,并在以后的文章中详细地解释它们幕后的工作原理。很遗憾的是,我不能在这篇文章中把所有的东西都教给你。
在本文中,我们快速介绍了Spring的各种配置风格,并了解了配置Spring应用的复杂性。此外,我们通过创建一个简单的Web应用来快速了解SpringBoot。
在下一篇文章中,我们将深入了解SpringBoot,了解它的工作原理。
本文内容总结:Spring框架概述,Spring很受欢迎的原因有几点:,基于XML的配置,基于注解的配置,基于Java代码的配置,一个使用了SpringMVC和JPA(Hibernate)的Web应用,步骤1、配置Maven依赖,步骤2、使用Java配置配置Service/DAO层的Bean,步骤3、配置SpringMVCWeb层的Bean,步骤4、注册SpringMVC的前端控制器DispatcherServlet,步骤5、创建一个JPA实体和SpringDataJPA资源库,步骤6、创建一个SpringMVC控制器,步骤7、创建一个Thymeleaf视图/WEB-INF/views/index.html来渲染用户列表,快速尝试SpringBoot,步骤1、创建一个基于Maven的SpringBoot应用,步骤2、如下在application.properties中配置DataSoure/JPA,步骤3、为实体创建一个JPA实体和SpringDataJPA资源库接口,步骤4、创建用于显示用户列表的Thymeleaf视图,步骤5、创建SpringBoot入口类,总结,
原文链接:https://www.cnblogs.com/oopsguy/p/7305136.html