Spring Boot 学习(2)
文 by / 林本托
Tips
做一个终身学习的人。
源代码:github下的/code01/ch2。
配置 Web 应用程序
在上一章中,我们学习了如何创建一个基本的应用程序模板,并添加了一些基本功能,并建立与数据库的连接。 在本章中,我们将继续增强BookPub
应用程序,并提供 Web 支持。
在本章,主要包括以下内容:
- 创建一个基本的 RESTful 风格的应用程序;
- 创建一个 Spring Data REST 服务;
- 配置一个自定义的 Servlet 的过滤器;
- 配置一个自定义的拦截器;
- 配置一个HttpMessageConverters的转换器;
- 配置一个自定义的PropertyEditors编辑器;
- 配置一个自定义的类型格式化类。
一. 创建一个基本的 RESTful 风格的应用程序
虽然命令行应用程序确实有其用途,但今天的大多数应用程序开发都围绕着 Web,REST 和数据服务。 我们开始增强 BookPub 应用程序,提供一个基于Web 的 API,以便访问图书目录。
我们继续使用前一章创建的应用程序框架,其中定义了实体对象和存储库服务,并配置了与数据库的连接。
首先,第一件事情是我们需要在build.gradle 文件中添加新的依赖模块spring-boot-starter-web,以便获取基于 web 服务的所需的类库。具体的代码片段如下:
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-jdbc")
compile("org.springframework.boot:spring-boot-starter-web")
runtime("com.h2database:h2")
testCompile("org.springframework.boot:spring-boot-
starter-test")
}
接下来,创建一个 Spring 控制器,用于处理我们应用程序中获取目录数据的 Web 请求。 新建一个包目录来存放控制器相关的 Java 程序,以便我们的代码按照适当的目的分组。 在 src/main/java/org/test/bookpub 目录下创建一个名为 controllers的包目录。
因为需要暴露图书的数据,所以,在新建的包下,创建一个控制器类BookController
。
package org.test.bookpub.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.test.bookpub.entity.Book;
import org.test.bookpub.entity.Reviewer;
import org.test.bookpub.repository.BookRepository;
import java.util.Collections;
import java.util.List;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookRepository bookRepository;
@RequestMapping(value = "", method = RequestMethod.GET)
public Iterable<Book> getAllBooks() {
return bookRepository.findAll();
}
@RequestMapping(value = "/{isbn}", method =
RequestMethod.GET)
public Book getBook(@PathVariable String isbn) {
return bookRepository.findBookByIsbn(isbn);
}
}
然后, 使用 ./gradlew clean bootRun.
命令启动应用程序。
最后,当应用程序程序启动以后,在浏览器中输入:http://localhost:8080/books, 然后会在页面上显示“[]”,表示目前没有图书的数据。
获取暴露于Web请求的服务的关键是@RestController注解。这是一个元注解使用的例子,正如Spring文档指出的那样,我们在以前的代码看到过。 在@RestController中,定义了两个注解:@Controller和@ResponseBody。 所以我们可以轻松给BookController
类添加注解,如下所示:
@Controller
@ResponseBody
@RequestMapping("/books")
public class BookController {...}
@Controller是一个类似于@Bean 和@Repository的Spring的元注解,并将已经添加注解的类声明为 MVC 控制器。
@ResponseBody是一个Spring MVC的注解,指示来自Web请求映射方法的响应,构成HTTP响应主体有效负载的整个内容,这是RESTful应用程序比较典型的使用场景。
二. 创建一个 Spring Data REST 服务
在上一个例子中,我们使用REST控制器来展示我们的BookRepository,通过Web RESTful API访问后台的数据。 虽然这是数据访问的一种快捷方便的方式,但它要求我们手动创建一个控制器并定义所有所需操作的映射。 为了最小化代码,Spring为我们提供了一种更方便的方法:spring-boot-starter-data-rest模块。 这允许我们简单地向存储库接口添加一个注解,而Spring将做剩下的事情用以将数据暴露给Web。
首先,我们需要在build.gradle文件中添加spring-boot-starter-data-rest模块。
dependencies {
...
compile("org.springframework.boot:spring-boot-starter-data-rest")
...
}
第二步,在src/main/java/org/test/bookpub/repository目录下新建AuthorRepository接口,代码如下:
package org.test.bookpub.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.stereotype.Repository;
import org.test.bookpub.entity.Author;
@RepositoryRestResource
public interface AuthorRepository extends PagingAndSortingRepository<Author, Long> {
}
接下来为剩下的实体模型创建对应的接口,
package org.test.bookpub.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.test.bookpub.entity.Publisher;
@RepositoryRestResource
public interface PublisherRepository extends PagingAndSortingRepository<Publisher, Long> {
}
package org.test.bookpub.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.test.bookpub.entity.Reviewer;
@RepositoryRestResource
public interface ReviewerRepository extends PagingAndSortingRepository<Reviewer, Long> {
}
代码完成后,执行./gradlew clean bootRun
。当启动成功以后,访问http://localhost:8080/profile/authors,在 Chrome 浏览器下,显示如下内容:
{
"_embedded" : {
"authors" : [ ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/authors{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/authors"
}
},
"page" : {
"size" : 20,
"totalElements" : 0,
"totalPages" : 0,
"number" : 0
}
}
从浏览器里显示的内容可以看出,我们将获得比我们编写BookController控制器更多的信息。 之所以显示了更多的信息,由于我们没有扩展CrudRepository接口,而是扩展了PagingAndSortingRepository,而它又是CrudRepository的扩展。 这样做的原因是获得PagingAndSortingRepository提供的额外好处。 这将添加额外的功能,使用分页检索实体,并能够对它们进行排序。
@RepositoryRestResource注解是可选项,但可以让我们更好地控制作为Web数据服务的存储库的暴露。 例如,如果我们要将URL路径由“authers”改成“rel”,则可以此注解调整,如下所示:
@RepositoryRestResource(collectionResourceRel = "writers", path = "writers")
修改以后,之前的 url 现在改完“http://localhost:8080/reviewers”。
由于我们在构建依赖项中包含spring-boot-starter-data-rest模块,我们还获得spring-hateoas类库的支持,此库给我们提供了很好的ALPS元数据,比如_links对象。 这在构建API驱动的UI时可能非常有用,这可以从元数据推导出导航功能并以适合的方式呈现它们。
Tips
关于更多 ALPS 元数据的信息,请参考https://spring.io/blog/2014/07/14/spring-data-rest-now-comes-with-alps-metadata。
三. 配置一个自定义的 Servlet 的过滤器
在一个真实的Web应用程序中,我们几乎总是需要为服务请求添加装饰器或包装器,用来记录它们,过滤XSS(跨站脚本攻击)的非法字符,执行认证等。Spring Boot自动添加OrderedCharacterEncodingFilter和HiddenHttpMethodFilter 两个过滤器,除此之外,还有其他的过滤器。 让我们看看Spring Boot如何帮助我们实现这个任务。
在Spring Boot,Spring Web,Spring MVC等的各种框架中,已经有各种不同的servlet过滤器可用,我们所要做的就是将它们作为一个bea定义到配置中。 假设应用程序将在负载平衡器代理之后运行,并且当我们的应用程序实例收到请求时,我们希望将用户使用的实际请求IP转换为代理的IP。 幸运的是,Tomcat 8已经为我们提供了一个实现:RemoteIpFilter。 我们需要做的就是将其添加到我们的过滤器链中。
根据功能的不同,便于管理和职责清晰,我们需要把不同的类放在不同的包下,我们创建一个WebConfiguration.java
的文件,放在src/main/java/org/test/bookpub 目录下。
package org.test.bookpub;
import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public RemoteIpFilter remoteIpFilter() {
return new RemoteIpFilter();
}
}
第二步,执行./gradlew clean bootRun
命令,在启动中,查看 log,会出现以下信息,表示过滤器已经添加:
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'remoteIpFilter' to: [/*]
这个功能背后的功能其实很简单。 我们从单独的配置类开始,并且将我们的方法用于过滤器bean的检测。
我们看看主类BookPubApplication,这个类添加了@SpringBootApplication注解,此注解是是一个元注解,它声明了@ComponentScan等其他注解。@ComponentScan的存在指示Spring Boot将WebConfiguration类检测为@Configuration注解的标记类,并将其定义添加到应用程序上下文中。所以,我们将在WebConfiguration类中声明的任何事情就好像我们将它放在BookPubApplication类中是一样的。
@Bean public RemoteIpFilter remoteIpFilter(){...}
声明为RemoteIpFilter类创建一个Spring bean。当Spring Boot 检测到javax.servlet.Filter的所有bean时,它将自动将它们添加到过滤器链中。所以我们要做的就是,如果要添加更多的过滤器,那就是将它们声明为@Bean配置。例如,对于更高级的过滤器配置,如果希望特定的过滤器仅适用于特定的URL模式,可以创建一个FilterBistrationBean类型的@Bean配置,并用来配置精确的设置。
四. 配置一个自定义的拦截器
Servlet过滤器是Servlet API的一部分,与Spring完全没有任何关系,除了自动添加到过滤器链中,Spring MVC为我们提供了另一种方式来包装Web请求:HandlerInterceptor拦截器。根据文档,HandlerInterceptor就像一个Filter,但是,拦截器不是在嵌套链中包含请求,而是在处理请求、处理视图或在页面渲染之前,在不同的阶段向我们提供了拦截点,对请求进行拦截。到最后,请求已经完成。它不改变有关请求的任何内容,但是如果拦截器逻辑返回false,它允许我们通过抛出异常来停止执行。
与过滤器的情况类似,Spring MVC附带了一些预定义的HandlerInterceptor。常用的是LocaleChangeInterceptor和ThemeChangeInterceptor。接下来在应用程序中添加LocaleChangeInterceptor,看看它是如何完成的。
添加一个拦截器并不像刚才声明一个bean那么简单。 实际上需要通过实现WebMvcConfigurer接口或重写WebMvcConfigurationSupport来实现。
第一步,WebConfiguration
类继承WebMvcConfigurerAdapter
类。
public class WebConfiguration extends
WebMvcConfigurerAdapter {…}
接下来,为LocaleChangeInterceptor
拦截器增加@Bean注解,
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
return new LocaleChangeInterceptor();
}
这实际上只会创建拦截 Spring bean,但不会将其添加到请求处理链中。 为了实现这一点,我们需要重写addInterceptors方法,注册拦截器。
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
整个代码如下:
package org.test.bookpub;
import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public RemoteIpFilter remoteIpFilter() {
return new RemoteIpFilter();
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
return new LocaleChangeInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
执行 ./gradlew clean bootRun
。
应用程序启动以后,在浏览器中输入http://localhost:8080/books?locale=foo。
这时,浏览器报错:
后台的错误 log 如下:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
Tips
上面的错误不是因为我们输入了无效的区域设置,而是因为默认语言环境解析策略不允许重置浏览器请求的语言环境。出现一个错误,实际上是证明了拦截器已经生效了。
当涉及到配置Spring MVC内部组件时,它并不像只是定义一堆bean那样简单—— 至少不总是这样。 这是因为需要向请求提供更精细的MVC组件映射。 为了简化难度,Spring为我们提供了WebMvcConfigurerAdapter适配器,它是WebMvcConfigurer接口实现,我们可以扩展和覆盖我们需要的设置。
在配置拦截器的特定情况下,我们可以重写addInterceptors(InterceptorRegistry registry)
方法。 这是一个典型的回调方法,我们给予一个注册类,以便根据需要注册多个附加拦截器。 在MVC自动配置阶段,Spring Boot就像过滤器一样检测到WebMvcConfigurer的实例,并依次调用所有这些回调方法。 这意味着如果需要其他逻辑分离,可以有多个WebMvcConfigurer类的实现。
五. 配置一个HttpMessageConverters转换器
在构建RESTful Web服务时,我们定义了控制器,资源库,并在其上面添加了注解,但是从Java实体bean到HTTP数据流输出没有任何类型的对象转换。 实际上,Spring Boot自动配置了HttpMessageConverters转换器将实体bean对象转换为使用了Jackson类库的JSON的格式,将生成的JSON数据写入HTTP响应输出流。 当多个转换器可用时,根据消息对象类和请求的内容类型选择最适用的转换器。
HttpMessageConverters的目的是将各种对象类型转换为相应的HTTP输出格式。 转换器可以支持一系列多种数据类型或多种输出格式,或两者的组合。 例如,MappingJackson2HttpMessageConverter类可以将任何Java对象转换为application/json的格式,而ProtobufHttpMessageConverter类只能对com.google.protobuf.Message的实例进行操作,但可以将其作为application/json,application/xml,text/plain或application/xprotobuf格式。 HttpMessageConverters不仅支持写入HTTP流,还支持将HTTP请求转换为适当的Java对象。
我们可以通过多种方式配置转换器。 这一切都取决于你喜欢哪一个,或者想要实现多少控制。
首先,我们在WebConfiguration类中增加ByteArrayHttpMessageConverter,并加上@Bean注解。
@Bean
public
ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
return new ByteArrayHttpMessageConverter();
}
另一种实现方式是重写WebConfiguration类中的configureMessageConverters方法,首先需要继承WebMvcConfigurerAdapter类,具体的代码如下:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ByteArrayHttpMessageConverter());
}
如果想获取更多的控制,还可以重写extendMessageConverters
方法。
@Override
public void
extendMessageConverters(List<HttpMessageConverter<?>>
converters) {
converters.clear();
converters.add(new ByteArrayHttpMessageConverter());
}
如上所示,Spring给了我们多种方式来实现同样的事情,这一切都取决于我们的偏好或具体的实现细节。
我们介绍了将HttpMessageConverter添加到应用程序中的三种不同的方法。 那有什么区别呢?
将HttpMessageConverter声明为@Bean是向应用程序添加自定义转换器的最快捷,最简单的方法。 它类似于我们在前面的例子中添加了Servlet过滤器。 如果Spring检测到一个HttpMessageConverter类型的bean,它将自动将其添加到列表中。 如果WebConfiguration类没有继承WebMvcConfigurerAdapter父类,那么这是首选方法。
当应用程序需要指定WebMvcConfigurerAdapter的扩展以配置其他的东西,如拦截器,那么重写configureMessageConverters
方法并将我们的转换器添加到列表将更为协调一致。可以从Spring Boot 的模块中添加多个WebMvcConfigurers实例并自动配置,但是不能保证我们的方法可以以任何特定的顺序被调用。
如果我们需要做一些更加具体的事情,比如从列表中删除所有其他转换器或清除重复的转换器,这需要重写extendMessageConverters方法的地方。 所有WebMvcConfigurer被调用到configureMessageConverter方法并且转换器列表被完全填充后调用此方法。 当然,WebMvcConfigurer的其他一些实例完全可以重写extendMessageConverters, 但是这样做的机会并不多。
六. 配置一个自定义的PropertyEditors编辑器
在前面的例子中,我们学习了如何为HTTP请求和响应数据配置转换器。 还有其他类型的转换,特别是在将参数动态转换为各种对象时,例如String类型转换为Date或Integer。
当我们在控制器中声明一个映射方法时,Spring使用确切的对象类型来自由定义方法签名。 这个方式是通过使用PropertyEditor实现的。 PropertyEditor是一个默认概念,定义为JDK的一部分,旨在允许将文本值转换为给定类型。 它最初用于构建Java Swing / AWT GUI,后来被证明是适合Spring需要将Web参数转换为方法参数类型的需要。
Spring MVC已经为很多常见类型(如布尔型,货币型和类)提供了大量的PropertyEditor实现。 假设我们要创建一个Isbn类对象,并在我们的控制器中使用它,而不是一个纯粹的String类型。
首先,我们需要在WebConfiguration
类中移除extendMessageConverters
方法,因为调用converters.clear()
这段代码会中断渲染,因为删除了所有支持的类型转换器。
然后,定义Isbn
类,和对应的IsbnEditor
属性编辑器,以及重写initBinde
方法给我们的BookController
类,使用以下内容配置IsbnEditor
:
public class Isbn {
private String isbn;
public Isbn(String isbn) {
this.isbn = isbn;
}
public String getIsbn() {
return isbn;
}
}
public class IsbnEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
setValue(new Isbn(text.trim()));
}
else {
setValue(null);
}
}
@Override
public String getAsText() {
Isbn isbn = (Isbn) getValue();
if (isbn != null) {
return isbn.getIsbn();
}
else {
return "";
}
}
}
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Isbn.class, new IsbnEditor());
}
第三步,在BookController
类中修改getBook
方法,以便可以接受 Isbn
类型的对象,
@RequestMapping(value = "/{isbn}", method = RequestMethod.GET)
public Book getBook(@PathVariable Isbn isbn) {
return bookRepository.findBookByIsbn(isbn.getIsbn());
}
第四步,启动./gradlew clean bootRun
,启动成功以后,在浏览器中输入http://localhost:8080/books/978-1-78528-415-1。
虽然我们不会观察到任何可见的更改,但IsbnEditor
确实在工作,从{isbn}参数中创建Isbn类对象实例。我们打印了传递过来的Isbn实例,重写了toString()
方法。
Spring自动配置大量的默认编辑器,但是对于自定义类型,我们必须明确地为每个Web请求实例化新的编辑器。 这是在控制器中使用@InitBinder注解的方法完成的。 扫描此注解,所有检测到的方法应具有接受WebDataBinder作为参数的签名。 除此之外,WebDataBinder还为我们提供了注册尽可能多的自定义编辑器的能力,要求控制器的方法被正确绑定。
Tips
PropertyEditor不是线程安全的!
因此,我们必须为每个Web请求创建一个新的自定义编辑器实例,并将其注册到WebDataBinder。
如果需要新的PropertyEditor,最好通过扩展PropertyEditorSupport类并自定义重写所需的方法来创建。
七. 配置一个自定义的类型格式化类
PropertyEditor因为它的状态和非线程安全,从版本3起,Spring添加了一个Formatter接口作为PropertyEditor的替代。 格式化类旨在提供类似的功能,但是以完全线程安全的方式,并专注于解析对象类型中的String并将对象转换为其字符串表示形式的非常具体的任务。
对于我们的应用程序,希望有一个格式化程序可以使用一个字符串形式的书籍的ISBN号码并将其转换为一个Book实体对象。 这样,当请求URL签名仅包含ISBN号码或数据库ID时,就可以使用Book类型的参数定义控制器请求的方法。
首先,在src/main/java/org/test/bookpub目录下创建一个新的包formatters,在此包下,创建BookFormatter
类并实现Formatter
接口,代码示例如下:
public class BookFormatter implements Formatter<Book> {
private BookRepository repository;
public BookFormatter(BookRepository repository) {
this.repository = repository;
}
@Override
public Book parse(String bookIdentifier, Locale locale) throws ParseException {
Book book = repository.findBookByIsbn(bookIdentifier);
return book != null ? book : repository.findOne(Long.valueOf(bookIdentifier));
}
@Override
public String print(Book book, Locale locale) {
return book.getIsbn();
}
}
然后,在WebConfiguration
类中,重写addFormatters(FormatterRegistry registry)
方法,并把BookFormatter
类注册进去。
@RequestMapping(value = "/{isbn}/reviewers", method = RequestMethod.GET)
public List<Reviewer> getReviewers(@PathVariable("isbn") Book book) {
return book.getReviewers();
}
接下来,在BookController
类中,新增一个请求方法,用来根据给定的图书的 isbn来显示评论者,
@RequestMapping(value = "/{isbn}/reviewers", method = RequestMethod.GET)
public List<Reviewer> getReviewers(@PathVariable("isbn") Book book) {
return book.getReviewers();
}
为了一些数据,现在手动添加一些测试数据填充数据库,通过向StartupRunner类添加两个自动装配的资源库:
@Autowired private AuthorRepository authorRepository;
@Autowired private PublisherRepository publisherRepository;
下面这些代码添加到StartupRunner
类的run(...)
方法中:
Author author = new Author("Alex", "Antonov");
author = authorRepository.save(author);
Publisher publisher = new Publisher("Packt");
publisher = publisherRepository.save(publisher);
Book book = new Book("978-1-78528-415-1", "Spring Boot Recipes", author, publisher);
bookRepository.save(book);
输入./gradlew clean bootRun
,在控制台,启动应用程序。
访问http://localhost:8080/books/978-1-78528-415-1/reviewers,在浏览器中可以看到如下结果:
格式化功能旨在提供与PropertyEditors类似的功能。 通过将FormatterRegistry注册在重写的addFormatter
方法中,告诉Spring使用Formatter将Book的文本表示转换为实体对象并返回。 由于格式化是无状态的,因此我们无需在控制器中每次都要注册; 我们只做一次就好,这确保Spring为每个Web请求使用它。
Tips
如果要定义一个常用类型的转换(例如String或Boolean),就像我们在IsbnEditor示例中所做的那样,最好是通过Controller的InitBinder
方法中的PropertyEditors初始化来做,因为这样的改变可能不是全局所期望的,只是针对特定的控制器的功能。
你可能已经注意到,我们还将BookRepository自动装配到WebConfiguration类,因为这是创建BookFormatter所需的。 这是Spring的一个很酷的东西,它让我们可以组合配置类,并使它们同时依赖于其他bean。 正如我们指出,为了创建一个WebConfiguration类,我们需要一个BookRepository,Spring确保在创建WebConfiguration类时首先创建BookRepository,然后自动注入作为依赖。 实例化WebConfiguration之后,将对其进行处理以进行配置说明。
Spring Boot 学习(2)的更多相关文章
- Spring Boot学习大全(入门)
Spring Boot学习(入门) 1.了解Spring boot Spring boot的官网(https://spring.io),我们需要的一些jar包,配置文件都可以在下载.添置书签后,我自己 ...
- Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客
==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...
- Spring boot学习1 构建微服务:Spring boot 入门篇
Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...
- spring boot 学习资料
spring boot 学习资料: 学习资料 网址 Spring Boot Cookbook-极客学院 http://wiki.jikexueyuan.com/project/spring-boot- ...
- Spring Boot学习笔记2——基本使用之最佳实践[z]
前言 在上一篇文章Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用已经对Spring Boot的基本体系与基本使用进行了学习,本文主要目的是更加进一步的来说明对于Spring B ...
- spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战
SpringBoot + Redis +SpringSession 缓存之实战 前言 前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需 ...
- 转载:spring boot学习
Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...
- Spring Boot学习路线
Spring Boot 学习路线,本文计划根据作者近几年的工作.学习经验,来分析和制定一个学习使用 Spring Boot技术的步骤路线图. SpringBoot是伴随着Spring4.0诞生的: S ...
- 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题
Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...
- 15 个优秀开源的 Spring Boot 学习项目,一网打尽!
Spring Boot 算是目前 Java 领域最火的技术栈了,松哥年初出版的 <Spring Boot + Vue 全栈开发实战>迄今为止已经加印了 8 次,Spring Boot 的受 ...
随机推荐
- windows下修改eclipse的默认编码 转
windows下一般系统编码为 GB2312(中文版的windows), 由于我比较喜欢utf8格式的编码,现将修改方式和大家分享 如果要使新建立工程.java文件直接使UTF-8则需要做以下工作: ...
- grep的用法笔记
1.grep搜索不保护字符串的命令格式如下: #带-v参数 jevan@df ~ grep "agc" -vRn ./
- html/css/javascript的含义、作用及理解
HTML(HyperText Markup Language/超文本标记语言) 含义:HTML是一种用于创建网页的标准标记语言. 作用:页面内可以包含图片.链接,甚至音乐.程序等非文字元素. 理解:主 ...
- iOS开发 - 啰嗦讲解 Runloop
写在前面的 为什么要了解 RunLoop?如果你想成为一个高级iOS开发工程师,那这是你必须了解的东西,他能帮助你更好的理解底层实现的原理,可以利用它的特性做出一些高效又神奇的功能.RunLoop这个 ...
- 深入理解css中vertical-align属性
一.为什么要写这篇文章 今天看到一个问题: 两个div 都设置 display:inline-block,正常显示:但是在第二个div中加一个块级元素或者内联元素,显示就变了个样,为什么? <m ...
- 类似智能购票的demo--进入页面后默认焦点在第一个输入框,输入内容、回车、right时焦点自动跳到下一个,当跳到select时,下拉选项自动弹出,并且可以按上下键选择,选择完成后再跳到下一个。
要实现的效果:进入页面后默认焦点在第一个输入框,输入内容.回车.right时焦点自动跳到下一个,当跳到select时,下拉选项自动弹出,并且可以按上下键选择,选择完成后再跳到下一个. PS:自己模拟的 ...
- Maven(二)之Maven项目构建演练
从上一篇的讲解中我们知道了什么是Maven,然后它的安装配置,到修改本地仓库,这篇我们用一个实际的例子,带领大家走进我们的Maven之旅.让我们一起来体验一下Maven的高度自动化构建项目的过程. 一 ...
- ajax发送异步请求
一:得到XMLHttpRequest对象 ajax其实只需要学习XMLHttpRequest一个对象 大多数浏览器都支持: var xmlHttp = new XMLHttprequest(); IE ...
- css3常用方法以及css3选择器
最重要的 CSS3 模块包括: 选择器 框模型 背景和边框 文本效果 2D/3D 转换 动画 多列布局 用户界面 CSS3 边框 CSS3 边框 通过 CSS3,您能够创建圆角边框,向矩形添加 ...
- (知识点)JavaScript闭包
下面是我对闭包的理解:(把他们整理出来,整理的过程也是在梳理) 1.首先,在理解闭包之前: 我们首先应该清楚下作用域和作用域链 作用域:每个函数定义时创建时自己的环境即作用域 作用域链:函数内可访问自 ...