Spring Boot实战

Spring在java EE开发中是实际意义上的标准,但我们在开发Spring的时候可能会遇到以下令人头疼的问题:

1.大量配置文件的定义。
2.与第三方软件整合的技术问题。

Spring每个版本的退出都以减少配置作为自己的主要目标,例如:

1.推出@Component,@Service,@Repository,@Controller注解在类上声明Bean
2.推出@Configuration,@Bean的java配置来替代xml配置。

Spring Boot具有以下特征:

1.遵循“习惯优于配置”的原则,使用Spring Boot只需要很少的配置。大部分可以使用默认配置。
2.项目快速搭建,可无配置整合第三方框架。
3.可完全不使用xml配置,只使用自动配置java config
4.内嵌servlet容器,应用可用jar包运行。
5.运行中应用状态的监控。

虽然Spring Boot给我们带来了类似于脚本语言开发的效率,但Spring Boot里没有使用如何让你意外的技术,完全是一个单纯的基于Spring的应用如,Spring Boot的自动配置是通过Spring 4.x 的@Conditional注解来实现的

第一部分.点睛Spring 4.x

Chapter1.Spring基础

Spring的简史:

1.xml配置

在Spring 1.x时代,使用Spring开发满眼都是xml配置的Bean,随着项目的扩大,我们需要xml配置文件分放到不同的配置文件里,那时候需要频繁地在开发的类和配置文件中切换。

2.注解配置

在Spring 2.x时代,随着JDK 1.5带来的注解支持,Spring提供了声明Bean的注解(如@Component,@Service),大大减少了配置量。这时Spring圈子里存在着一种争论:注解配置和xml配置究竟哪个好?我们最终的选择是应用的基本配置(如数据库配置)用xml,业务配置用注解

3.java配置

Spring3.x到现在,Spring提供了java配置的能力,使用java配置可以让你更理解你配置的Bean。我们目前刚好处于这个时代,Spring 4.x和Spring Boot都推荐使用java配置,所以我们在本书通篇将使用java配置。

Spring使用简单的POJO(plain old java object,即无任何限制的普通java对象)来进行企业化开发,每一个被Spring管理的java对象都称之为Bean。而Spring提供了一个IoC容器用来初始化对象,解决对象间的依赖管理和对象的使用。

Spring的生态:

1.Spring Boot:使用默认开发配置来实现快速开发
2.Spring Data:对主流的关系型和NoSQL数据库的支持
3.Spring Security:通过认证和授权保护应用
4.Spring Web Flow:基于Spring MVC提供基于向导流程式的Web应用开发
5.Spring Web Services:提供了基于协议有限的SOAP/Web服务
6.Spring Session:提供一个API及实现来管理用户会话信息
等等,还有很多。

Spring框架本身有四大原则

1.使用POJO进行轻量级和最小侵入式开发
2.通过依赖注入和基于接口编程实现松耦合
3.通过AOP和默认习惯进行声明式编程
4.通过AOP和模板(template)减少模块化代码

我们经常说的控制翻转(inversion of control-IOC)和依赖注入(dependency injection-DI)在Spring环境下是等同的概念,控制翻转是通过依赖注入实现的。所谓的依赖注入指的是容器负责创建对象和维护对象间的依赖关系,而不是通过对象本身自己的创建和解决自己的依赖。比如典型的:

?
1
2
@Autowired
MyBean bean;

而不是自己new出一个对象

声明Bean的注解:

1.@Component组件,没有明确的角色
2.Service在业务逻辑层(service层)使用
3.@Repository在数据访问层(dao层)使用
4.@Controller在展现层(MVC->Spring MVC)使用

注入Bean的注解:

1.@Autowired,Spring提供的注解(推荐使用)
2.@Inject,JSR-330提供
3.@Resource,JSR-250提供

注入Bean的注解可以注解在set方法上或者属性上,不过最好是在属性上,优点是代码更少,层次更清晰。

@Configuration声明当前类是一个配置类。

使用@ComponentScan,自动扫描包名下所有使用@Service,@Component,@Compository,@Controller的类,并注册为Bean。

java配置是通过@Configuation和@Bean来实现的。

@Configuration声明当前类时一个配置类,相当于一个Spring配置的xml文件。
@Bean注解在方法上,声明当前方法的返回值为一个Bean。

何时使用java配置或者注解配置呢?
我们的原则是:全局配置使用java配置(如数据库相关配置,MVC相关配置),业务Bean的配置使用注解配置

AOP:面向切面编程,相对于OOP面向对象编程

Spring的AOP的存在的目的是为了解耦。AOP可以让一组类共享相同的行为。在OOP中只能通过继承类和实现接口,来使代码的耦合度增强,且类继承只能为单继承,阻碍更多行为添加到一组类上,AOP弥补了OOP的不足。

注解注解本身是没有功能的,就和xml一样。注解和xml都是一种元数据,元数据即解释数据的数据,这就是所谓的配置。

Chapter2.Spring常用配置

Scope描述的是Spring容器如何新建Bean的实例的。有以下几种,通过@Scope注解来实现:

1.Singleton:一个Spring容器中只有一个Bean的实例,此为Spring的默认配置,全容器共享一个实例
2.Prototype:每次调用新建一个Bean的实例。
3.Request:Web项目中,给每一个http request新建一个Bean实例。
4.Session:Web项目中,给每一个http session新建一个Bean实例。

Spring EL-Spring表达式语言,支持在xml和注解中使用表达式,类似于JSP的EL表达式语言。

示例:

?
1
2
3
4
5
6
7
8
9
//注入普通字符串
@Value ( "I Love You!" ) //1
private String normal;
//注入操作系统属性
@Value ( "#{systemProperties['os.name']}" ) //2
private String osName;
//注入表达式结果
@Value ( "#{ T(java.lang.Math).random() * 100.0 }" ) //3
private double randomNumber;

在实际开发的时候,经常会遇到Bean在使用使用之前或者之后做些必要的操作。在使用java配置和注解配置下提供了如下两种方式:

1.java配置方式:使用@Bean的initMethoddestroyMethod
2.注解方式:利用JSR-250的@PostConstruct@PreDestroy

Spring的事件(Application Event)为Bean与Bean之间的消息通信提供了支持。当一个Bean处理完一个任务之后,希望另外一个Bean知道并能做相应的处理,这时我们就需要让另一个Bean监听当前Bean说发送的事件。

Spring的事件需要遵循如下流程:

1.自定义事件,继承ApplicationEvent
2.定义事件监听器,实现ApplicationListener
3.使用容器发布事件

具体例子看书源码即可。

Chapter3.Spring高级话题

Spring的依赖注入的最大亮点就是你所有的Bean对容器Spring容器的存在是没有意识的。即你可以将你的容器替换成别的容器。

但在实际项目中,不可避免要用到Spring容器本身的功能资源,这时你的Bean必须要意识到Spring容器的存在,才能调用Spring说提供的资源,这就是所谓的Spring Aware。其实,Spring Aware本来就是Spring设计用来框架内部使用的,若使用了Spring Aware,你的Bean将会和Spring框架耦合。

Spring Aware的目的是为了让Bean获得Spring容器的服务

多线程

Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。而实际开发中任务一般是非阻碍的,即异步的,所以我们要在配置类中通过@EnableAsync开启对异步任务的支持。并通过在实际执行的Bean方法中使用@Async注解来声明其是一个异步任务。

计划任务

计划任务在Spring中的实现变得异常的简单。首先通过在配置类注解@EnableScheduling来开启对计划任务的支持,然后在要执行任务的方法上注解@Scheduled,声明这是一个计划任务。

Spring通过@Scheduled支持多种类型的计划任务,包含cron,fixDeley,fixedRate等。例如:

?
1
2
3
4
//每个5秒执行一次
@Scheduled (fixedRate= 5000 )
//UNIX或LINUX系统下的定时任务
@Scheduled (cron= "0 28 11 ? * *" )

组合注解和元注解

注解的大量使用,尤其相同的多个注解用到各个类或方法中,会相当繁琐。这就是所谓的样板代码,是Spring设计原则中要消除的代码。

所谓元注解其实就是可以注解到别的注解上的注解,被注解的注解称之为组合注解

@Enable*注解

通过观察@Enable*注解的源码,我们发现所有的注解都有一个@Import注解,@Import是用来导入配置类的,这也就意味着这些自动开启的实现其实是导入了一些自动配置的Bean。这些导入的配置主要分为三种类型:

1.直接导入配置类
2.依据调价选择配置类
3.动态注册Bean

分清MVC和三层架构的不同:

MVC:Model+View+Controller(数据模型+视图+控制器)

三层架构:Presentation tier+Application tier+Data tier(展现层+应用层+数据访问层)

实际的MVC只存在三层架构中的展现层,M实际上是数据模型,是包含数据的对象。在Spring MVC中,有一个专门的类叫Model,用来和V之间的数据交互、传值;V指的是视图页面,包含JSP,Thymeleaf等。C当然就是控制器(Spring MVC的注解@Controller类)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Spring MVC配置
@Configuration
@EnableWebMvc
@EnableScheduling
@ComponentScan ( "com.wisely.highlight_springmvc4" )
public class MyMvcConfig extends WebMvcConfigurerAdapter {
 
     @Bean
     public InternalResourceViewResolver viewResolver() {
         InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
         viewResolver.setPrefix( "/WEB-INF/classes/views/" );
         viewResolver.setSuffix( ".jsp" );
         viewResolver.setViewClass(JstlView. class );
         return viewResolver;
     }
}

注意这里对路径前缀的配置为/WEB-INF/classes/views/,不是和我们的开发的目录一样。因为看到的页面效果是运行时而不是开发时的代码,运行时代码会将我们的页面自动编写到/WEB-INF/classes/views/(因为我把JSP文件放在了/resources/views目录下)下。

?
1
2
3
4
5
6
7
8
9
10
@Controller
public class HelloController {
 
     @RequestMapping ( "/index" )
     public  String hello(){
 
         return "index" ;
     }
 
}

通过上面的ViewResolver的Bean配置,返回值为index,说明我们的页面放置的路径为/WEB-INF/classes/views/index.jsp。

Spring MVC的常用注解

1.@Controller
2.@RequestMapping
3.@RequestBody
@RequestBody允许request的参数在request体中,而不是在直接链接在地址后面。
4.@ResponseBody
@ResponseBody支持将返回值放在response体内,而不是返回一个页面。
5.@PathVariable
6.@RestController
是一个组合注解,组合了@Controller和@ReponseBody。

示例:
添加jackson即相关依赖,获得对象和json或xml之间的转化。

特别指出:在实际项目中,我们主要支持json数据,没必要同时支持json和xml,因为json比xml更简洁,而且也更推荐。

?
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
public class DemoObj {
     private Long id;
     private String name;
 
     //jackson对对象和json做转换时一定需要此空构造
     public DemoObj() {
         super ();
     }
     public DemoObj(Long id, String name) {
         super ();
         this .id = id;
         this .name = name;
     }
     public Long getId() {
         return id;
     }
     public void setId(Long id) {
         this .id = id;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this .name = name;
     }
 
 
 
}

演示@Controller控制器:

?
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
@Controller // 1
@RequestMapping ( "/anno" ) //2
public class DemoAnnoController {
 
     @RequestMapping (produces = "text/plain;charset=UTF-8" // 3
     public @ResponseBody String index(HttpServletRequest request) { // 4
         return "url:" + request.getRequestURL() + " can access" ;
     }
 
     @RequestMapping (value = "/pathvar/{str}" , produces = "text/plain;charset=UTF-8" ) // 5
     public @ResponseBody String demoPathVar( @PathVariable String str, //3
             HttpServletRequest request) {
         return "url:" + request.getRequestURL() + " can access,str: " + str;
     }
 
     @RequestMapping (value = "/requestParam" , produces = "text/plain;charset=UTF-8" )
     //6演示常规的request参数获取,访问路径
     //为/anno/requestParam?id=1
     public @ResponseBody String passRequestParam(Long id,
             HttpServletRequest request) {
 
         return "url:" + request.getRequestURL() + " can access,id: " + id;
 
     }
 
     @RequestMapping (value = "/obj" , produces = "application/json;charset=UTF-8" )
     //演示解释参数到对象,访问路径为/anno/obj?id=1&name=xx
     @ResponseBody //8
     public String passObj(DemoObj obj, HttpServletRequest request) {
 
          return "url:" + request.getRequestURL()
                     + " can access, obj id: " + obj.getId()+ " obj name:" + obj.getName();
 
     }
 
     @RequestMapping (value = { "/name1" , "/name2" }, produces = "text/plain;charset=UTF-8" ) //9
     public @ResponseBody String remove(HttpServletRequest request) {
 
         return "url:" + request.getRequestURL() + " can access" ;
     }
 
}

演示@RestController控制器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController //1
@RequestMapping ( "/rest" )
public class DemoRestController {
 
     @RequestMapping (value = "/getjson" ,
             produces={ "application/json;charset=UTF-8" }) //2
     public DemoObj getjson (DemoObj obj){
     //直接返回对象,对象会自动转换称json
         return new DemoObj(obj.getId()+ 1 , obj.getName()+ "yy" );
     }
     @RequestMapping (value = "/getxml" ,
             produces={ "application/xml;charset=UTF-8" }) //4返回数据的媒体类型为xml
     public DemoObj getxml(DemoObj obj){
         return new DemoObj(obj.getId()+ 1 , obj.getName()+ "yy" );
     }
 
}

Spring MVC的基本配置

Spring MVC的定制配置需要我们的配置类继承一个WebMvcConfigureAdapter类,并在此类使用@EnableWebMvc注解,来开启对Spring MVC的配置支持,这样我们就可以重写这个类的方法,完成我们的常用配置。

静态资源映射

?
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
@Configuration
//1开启Spring MVC支持,若无此句,重写
//WebMvcConfigurerAdapter方法无效
@EnableWebMvc
@EnableScheduling
@ComponentScan ( "com.wisely.highlight_springmvc4" )
public class MyMvcConfig extends WebMvcConfigurerAdapter { // 2重写方法进行配置
 
     @Bean
     public InternalResourceViewResolver viewResolver() {
         InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
         viewResolver.setPrefix( "/WEB-INF/classes/views/" );
         viewResolver.setSuffix( ".jsp" );
         viewResolver.setViewClass(JstlView. class );
         return viewResolver;
     }
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
 
 
//addResourceLocations指的是文件放置的目录,
//addResourceHandler指的是对外暴露的访问路径
registry.addResourceHandler( "/assets/**" ).addResourceLocations(
                 "classpath:/assets/" );
 
     }
}

快捷的ViewController
我们在配置页面转向的时候使用下面的代码:

?
1
2
3
4
@RequestMapping ( "/index" )
public Stirng hello(){
return "hello" ;
}

如果只是单纯的转向,没有其他的业务逻辑的话,这样写很麻烦,我们可以通过重写addViewControllers来简化配置:

?
1
2
3
4
@override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController( "/index" ).setViewName( "index" )
}

文件上传配置:

在Spring的控制器中,通过MultipartFile file来接收文件,通过MultipartFile[] files接收多个文件上传。

服务器端推送技术

服务器推送技术在日常生活中较为常用,很多人早期的方案是使用Ajax向服务器轮询消息,这种方式的轮询频率不好控制,所以大大增加了服务器的压力。

本节的服务器端推送方案都是基于:当客户端向服务端发送请求,服务端会抓住这个请求不放,等有数据更新的时候才返回给客户端,当客户端接收到消息后,再向服务端发送请求,周而复始。这种方式的好处是大大减少了服务器的请求数量,大大减少了服务器的压力

Spring MVC的测试

为了测试Web项目通常不需要启动项目,我们需要一些Servlet相关的模拟对象。比如:MockMVC,MockHttpServletRequest,MockHttpServletResponse,MockHttpSession等。

测试驱动开发(TDD)

我们按照需求先写一个自己预期结果的测试用例,这个测试用例刚开始肯定是失败的测试,随着不断的编码和重构,最终让测试用例通过测试。这样才能保证软件的质量和可控性。

我们主要借助的是JUnit来进行测试。
演示测试:

?
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
@RunWith (SpringJUnit4ClassRunner. class )
@ContextConfiguration (classes = {MyMvcConfig. class })
@WebAppConfiguration ( "src/main/resources" ) //1
public class TestControllerIntegrationTests {
     private MockMvc mockMvc; //2
 
     @Autowired
     private DemoService demoService; //3
 
     @Autowired
     WebApplicationContext wac; //4
 
     @Autowired
     MockHttpSession session; //5
 
     @Autowired
     MockHttpServletRequest request; //6
 
     @Before //7在测试开始前进行的初始化工作
     public void setup() {
         mockMvc =
                 MockMvcBuilders.webAppContextSetup( this .wac).build(); //2
         }
 
     @Test
     public void testNormalController() throws Exception{
         mockMvc.perform(get( "/normal" )) //8
                 .andExpect(status().isOk()) //9
                 .andExpect(view().name( "page" )) //10
                 .andExpect(forwardedUrl( "/WEB-INF/classes/views/page.jsp" )) //11
                 .andExpect(model().attribute( "msg" , demoService.saySomething())); //12
 
     }
 
     @Test
     public void testRestController() throws Exception{
         mockMvc.perform(get( "/testRest" )) //13
         .andExpect(status().isOk())
          .andExpect(content().contentType( "text/plain;charset=UTF-8" )) //14
         .andExpect(content().string(demoService.saySomething())); //15
     }
 
}

第三部分.实战Spring Boot

Chapter5.Spring基础

Spring Boot:
它使用”习惯优于配置”(项目中存在大量的配置,此外还内置一个习惯性的配置,让你无须手动进行配置)的理念让你的项目快速运行起来。使用Spring Boot很容易创建一个独立运行(运行jar,内嵌servlet容器),准生产级别的给予Spring框架的项目,使用Spring Boot你可以不用或者只需很少的Spring配置。

Spring Boot核心功能:

1.独立运行的Spring项目

2.内嵌Servlet容器

3.提供starter简化Maven配置
这个确实很方便,不用自己手动添加很多依赖

4.自动配置Spring
Spring Boot会根据在类路径中的jar包,类,为jar包里的类自动配置bean,这样会极大地减少我们要使用的配置。当然,Sping Boot只是考虑了大多数的开发场景,并不是所有的场景,若在实际中需要自动配置Bean,而Spring Boot没有提供支持,那么可以自定义自动配置。(见Spring运行原理)

5.准生产的应用监控
Spring提供基于http,ssh,telnet对运行时的项目进行监控

6.无代码生成和xml配置
Spring 4.x提倡使用java配置和注解配置组合,而Spring Boot不需要任何xml配置即可实现Spring的所有配置。

一个小技巧
在InteliJ IDEA中创建Spring项目时,选择新建Spring Initializer项目,可以添加各种starter,然后会在maven中自动添加依赖,很方便。

@SpringBootApplication是Spring Boot项目的核心注解,主要目的是开启自动配置

Chapter6.Spring Boot核心

@SpringBootApplication是个组合注解,源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
@Target ({ElementType.TYPE})
@Retention (RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan (
     excludeFilters = { @Filter (
     type = FilterType.CUSTOM,
     classes = {TypeExcludeFilter. class }
)}
)

Spring Boot的配置文件

Spring Boot使用一个全局的配置文件application.properties或application.yml,放置在/src/main/resources目录或者类路径下的/config下。这里面的配置非常多,参见官方给出的附录。例如:

?
1
2
3
4
//将tomcat默认端口号8080改为9090,并将默认的访问路径"/"
//修改为"//hellohost"
server.port= 9090
server.context-path=/hellohost

常规属性配置

我们之前讲过在常规Spring环境下,注入properites文件里的值的方式,通过@PropertySource指明properties文件的位置,然后通过@Value注入值。在Spring Boot里,我们只需在application.properties中定义属性,然后使用@Value注入即可。

类型安全的配置(基于properties)

上例中使用@Value注入每个配置在实际项目中会显得很麻烦,因为要写@Value注入很多次啊。

下面是一个进化版,能够通过@ConfigurationProperties将properties属性和一个Bean及其属性关联,从而实现类型安全的配置。例如:在application.properties上添加:

?
1
2
author.name =zeng
author.age = 24

当然也可以新建一个properties文件,这就需要我们在@ConfigurationProperties的属性locations里面指定properties的位置,且需要在入口类上配置。

类型安全的Bean:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component
@ConfigurationProperties (prefix = "author" ) //1
public class AuthorSettings {
     private String name;
     private Long age;
 
     public String getName() {
         return name;
     }
 
     public void setName(String name) {
         this .name = name;
     }
 
     public Long getAge() {
         return age;
     }
 
     public void setAge(Long age) {
         this .age = age;
     }
}

通过prefix指定配置的前缀,通过locations制定文件的位置。比如:

?
1
@ConfigurationProperties (prefix = "author" ,locations={ "classpath:config/author.properties" })

日志配置

默认情况下,Spring Boot使用Logback作为日志框架。

?
1
2
3
4
5
6
7
8
9
10
# LOGGING
logging.config= # Location of the logging configuration file. For instance `classpath:logback.xml` for Logback
logging.exception-conversion-word=%wEx # Conversion word used when logging exceptions.
logging.file= # Log file name. For instance `myapp.log`
logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG`
logging.path= # Location of the log file. For instance `/var/log`
logging.pattern.console= # Appender pattern for output to the console. Only supported with the default logback setup.
logging.pattern.file= # Appender pattern for output to the file. Only supported with the default logback setup.
logging.pattern.level= # Appender pattern for log level ( default %5p). Only supported with the default logback setup.
logging.register-shutdown-hook= false # Register a shutdown hook for the logging system when it is initialized.

Spring Boot运行原理

在前面我们了解到Spring 4.x提供了基于条件来配置Bean的能力,其实Spring Boot的神奇的实现也是基于这一原理的。

关于Spring Boot的运作原理,还是要回归到@SpringBootApplication注解上来,这个注解是一个组合注解,前面已经演示过了,它的核心功能是由@EnableAutoConfiguration注解来提供的。

Chapter7.Spring Boot的Web开发

Spring Boot提供了spring-boot-starter-web为Web开发予以支持,spring-boot-starter-web为我们提供了嵌入的Tomcat以及Spring MVC的依赖。而Web相关的自动配置存储在org.springframework.web下。从这些文件名可以看出:

1.ServerPropertiesAutoConfiguration和ServerPropertes自动配置内嵌的Servlet容器

2.HttpEncodingAutoConfiguration和HttpEncodingProperties用来自动配置http的编码

3.MultipartAutoConfiguration和MultipartProperties用来自自动配置上传文件的属性

4.JacksonHttpMessageConvertersConfiguration用来自动配置mappingJackson2HttpMessageConverter和mappingJackson2XmlHttpMessageConverter。

5.WebMvcAutoConfiguration和WebMvcProperties配置Spring MVC。

Thymeleaf与Spring MVC的集成

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Bean
public TemplateResolver templateResovler(){
     TemplateResovler templateResovler = new ServletContextTemplateResovler();
     templateResovler.setPrefix( "/WEB-INF/templates" );
     templateResovler.setSuffix( ".html" );
     templateResovler.setTemplateMode( "HTML5" );
     return templateResovler;
}
 
@Bean
public SpringTemplateEngine templateEngine(){
     SpringTemplateEngine templateEngine = new SpringTemplateEngine();
     templateEngine.setTemplateResovler(templateResovler());
     return templateEngine;
}
 
@Bean
public ThymeleafViewResovler thymeleafVewResolver(){
     ThymeleafViewResolver thymeleafVewResolver = new ThymeleafViewResovler();
     ThymeleafViewResovler.setTemplateEngine(templateEngine());
     return ThymeleafViewResovler;
}

在Spring MVC中虽然有引擎,让配置变得不那么麻烦,但还是太繁琐了啊。看看Spring Boot吧。

Thymeleaf与Spring Boot的集成

上一部分的一切配置在Spring Boot中一切都是不需要的。Spring Boot通过org.springframework.boot.autoconfigure.thymeleaf包对Thymeleaf进行了自动配置。我们只需要在application.properties中进行适当的配置即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
# THYMELEAF (ThymeleafAutoConfiguration)
spring.thymeleaf.cache= true # Enable template caching.
spring.thymeleaf.check-template= true # Check that the template exists before rendering it.
spring.thymeleaf.check-template-location= true # Check that the templates location exists.
spring.thymeleaf.content-type=text/html # Content-Type value.
spring.thymeleaf.enabled= true # Enable MVC Thymeleaf view resolution.
spring.thymeleaf.encoding=UTF- 8 # Template encoding.
spring.thymeleaf.excluded-view-names= # Comma-separated list of view names that should be excluded from resolution.
spring.thymeleaf.mode=HTML5 # Template mode to be applied to templates. See also StandardTemplateModeHandlers.
spring.thymeleaf.prefix=classpath:/templates/ # Prefix that gets prepended to view names when building a URL.
spring.thymeleaf.suffix=.html # Suffix that gets appended to view names when building a URL.
spring.thymeleaf.template-resolver-order= # Order of the template resolver in the chain.
spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved.

接管Spring Boot的Web配置

好好读读下面两段话

如果Spring Boot提供的Spring MVC默认配置不符合你的需求,则可以通过一个配置类(注解有@Configuration)加上@EnableWebMvc注解来实现完全自己控制的MVC配置。这种情况,这种方法不推荐

当然,在通常情况下,Spring Boot的自动配置是符合我们大多数需求的。在你既需要保留Spring Boot提供的便利,又需要增加自己的额外的配置的时候,可以定义一个配置类并继承WebMvcConfigurerAdapter,无须使用@EnableWebMvc注解。然后按照第4章讲的Spring MVC的配置方法来添加Spring Boot为我们所做的其他配置

关键点是:可以通过Spring MVC的配置方法来配置Spring Boot。

?
1
2
3
4
5
6
7
8
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
 
@override
public void addViewControllers(ViewControllerRegistry registry){
     registry.addViewController( "/xx" ).addViewName( "xx" );
}
}

值得指出的是:在这里重写的addViewController方法,并不会覆盖WebMvcAutoConfiguration中的addViewControllers(在源码中,默认的有一个配置,Spring Boot将”/”映射到index.html),这也就意味着我们的配置和Spring Boot的自动配置同时有效,这也是我们推荐添加自己的MVC配置的方式

WebSocket

WebSocket为浏览器和服务端提供了双工异步通信的功能,即浏览器可以向服务端发送消息,服务端也可以向浏览器发送消息

WebSocket是通过一个socket来实现双工异步通信能力的。但是直接使用WebSocket协议会显得非常繁琐,我们会使用它的子协议STOMP,它是一个更高级别的协议,STOMP协议使用一个基于帧(frame)的格式来定义信息,与HTTP的request和response类似(具有类似于@RequestMapping的@MessageMapping)。

1.广播式
广播式即服务端有消息时,会将消息发送给所有连接了当前endpoint的浏览器。

2.点对点式
广播式有自己的应用场景,但是广播式不能解决我们一个常见的场景,即消息由谁发送,由谁接收的问题。

基于Bootstrap和AngularJS的现代Web应用

现代的B/S系统有下面几个特色:

1.单页面应用

单页面应用(single-page application,简称SPA)值的是一种类似于原生客户端软件的更流畅的用户体验页面。

在单页面的应用中,所有的资源(HTML,JavaScript,CSS)都是按需动态加载到页面上的,且不需要服务端控制页面的转向

2.响应式设计

响应式设计(Responsive web design,简称RWD)指的是不同的设备访问相同的页面的时候,得到不同的页面视图,而得到的视图是适应当前屏幕的。

3.数据导向

数据导向是对于页面导向而言的,页面上的数据获得是通过消费后台的REST服务来实现的,而不是通过服务器渲染的动态界面(如JSP)来实现的,一般数据交换使用的格式是JSON

AngularJS

HTML一般是用来申明静态页面的,但是通常情况下我们希望页面是基于数据动态生成的,这也是我们很多服务器端模板引擎出现的原因,而AngularJS可以只通过前端技术就实现动态的页面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@SpringBootApplication
public class Ch77Application {
 
     @RequestMapping (value= "/search" ,produces={MediaType.APPLICATION_JSON_VALUE})
     public Person search(String personName){
 
         return new Person(personName, 32 , "hefei" );
 
     }
 
     public static void main(String[] args) {
         SpringApplication.run(Ch77Application. class , args);
     }
}

上面的代码我们模拟一个查询,即接收前台传入的personName,然后返回Person类,因为我们使用的是@RestController,且返回值类型是Person,所以Spring MVC会自动将对象输出为JSON。注意代码中的:

?
1
produces={MediaType.APPLICATION_JSON_VALUE}

Chapter8.Spring Boot的数据访问

Spring Data为我们使用统一的API来对很多数据存储技术(比如关系性和非关系型数据库)进行数据访问操作提供了支持。这是Spring通过提供Spring Data Commons项目来实现的,它是上述各种Spring Data项目的依赖。Spring Data Commons让我们在使用关系型或非关系型数据访问技术时都使用基于Spring的统一标准,该标准包含CURD(创建,获取,更新,删除),查询,排序和分页的相关操作。

SpringBoot实战(第4版)清晰文字版,第 1 章 入门 ................................................ 1 1.1 Spring 风云再起 ........................................ 1 1.1.1 重新认识 Spring ............................ 2 1.1.2 Spring Boot 精要 ........................... 3 1.1.3 Spring Boot 不是什么 ................... 6 1.2 Spring Boot 入门 ....................................... 6 1.2.1 安装 Spring Boot CLI .................... 7 1.2.2 使用 Spring Initializr 初始化 Spring Boot 项目 .......................... 10 1.3 小结 ......................................................... 18 第 2 章 开发第一个应用程序 .................... 19 2.1 运用 Spring Boot ..................................... 19 2.1.1 查看初始化的 Spring Boot 新项目 .......................................... 21 2.1.2 Spring Boot 项目构建过程 解析 .............................................. 24 2.2 使用起步依赖 .......................................... 27 2.2.1 指定基于功能的依赖 ................... 28 2.2.2 覆盖起步依赖引入的传递依赖 .... 29 2.3 使用自动配置 .......................................... 30 2.3.1 专注于应用程序功能 ................... 31 2.3.2 运行应用程序 .............................. 36 2.3.3 刚刚发生了什么 ........................... 38 2.4 小结 ......................................................... 41 第 3 章 自定义配置 .................................... 42 3.1 覆盖 Spring Boot 自动配置 ..................... 42 3.1.1 保护应用程序 .............................. 43 3.1.2 创建自定义的安全配置 ............... 44 3.1.3 掀开自动配置的神秘面纱 ........... 48 3.2 通过属性文件外置配置 ........................... 49 3.2.1 自动配置微调 .............................. 50 3.2.2 应用程序 Bean 的配置外置 ......... 55 3.2.3 使用 Profile 进行配置 .................. 59 3.3 定制应用程序错误页面 ........................... 62 3.4 小结 ......................................................... 64 第 4 章 测试 ............................................... 66 4.1 集成测试自动配置 .................................. 66 4.2 测试 Web 应用程序 ................................. 68 4.2.1 模拟 Spring MVC ........................ 69 4.2.2 测试 Web 安全 ............................. 72 4.3 测试运行中的应用程序 ........................... 74 4.3.1 用随机端口启动服务器 ............... 75 4.3.2 使用 Selenium 测试 HTML 页面 ............................................. 76 4.4 小结 ......................................................... 78 第 5 章 Groovy 与 Spring Boot CLI ......... 80 5.1 开发 Spring Boot CLI 应用程序 .............. 80 5.1.1 设置 CLI 项目 .............................. 81 5.1.2 通过 Groovy 消除代码噪声 ......... 81 5.1.3 发生了什么 .................................. 85 5.2 获取依赖 .................................................. 86 5.2.1 覆盖默认依赖版本 ....................... 87 5.2.2 添加依赖仓库 .............................. 88 5.3 用 CLI 运行测试 ...................................... 89 5.4 创建可部署的产物 .................................. 91 5.5 小结 ......................................................... 91 第 6 章 在 Spring Boot 中使用 Grails ...... 93 6.1 使用 GORM 进行数据持久化 ................. 93 2 目 录 6.2 使用 Groovy Server Pages 定义视图 ....... 98 6.3 结合 Spring Boot 与 Grails 3 ................. 100 6.3.1 创建新的 Grails 项目 ................. 100 6.3.2 定义领域模型 ............................ 103 6.3.3 开发 Grails 控制器 ..................... 104 6.3.4 创建视图 .................................... 105 6.4 小结 ....................................................... 107 第 7 章 深入 Actuator .............................. 108 7.1 揭秘 Actuator 的端点 ............................ 108 7.1.1 查看配置明细 ............................ 109 7.1.2 运行时度量 ................................ 115 7.1.3 关闭应用程序 ............................ 121 7.1.4 获取应用信息 ............................ 121 7.2 连接 Actuator 的远程 shell .................... 122 7.2.1 查看 autoconfig 报告 ........... 123 7.2.2 列出应用程序的 Bean ............... 124 7.2.3 查看应用程序的度量信息 ......... 124 7.2.4 调用 Actuator 端点 .................... 125 7.3 通过 JMX 监控应用程序 ....................... 126 7.4 定制 Actuator......................................... 128 7.4.1 修改端点 ID ............................... 128 7.4.2 启用和禁用端点 ........................ 129 7.4.3 添加自定义度量信息 ................. 129 7.4.4 创建自定义跟踪仓库 ................. 132 7.4.5 插入自定义健康指示器 ............. 134 7.5 保护 Actuator 端点 ................................ 136 7.6 小结 ....................................................... 138 第 8 章 部署 Spring Boot 应用程序 ........ 139 8.1 衡量多种部署方式 ................................ 139 8.2 部署到应用服务器 ................................ 140 8.2.1 构建 WAR 文件 ......................... 141 8.2.2 创建生产 Profile ........................ 142 8.2.3 开启数据库迁移 ........................ 145 8.3 推上云端 ............................................... 150 8.3.1 部署到 Cloud Foundry ............... 150 8.3.2 部署到 Heroku ........................... 153 8.4 小结 ....................................................... 155 附录 A Spring Boot 开发者工具.............. 157 附录 B Spring Boot 起步依赖 ................. 163 附录 C 配置属性 ...................................... 169 附录 D Spring Boot 依赖 ......................... 202
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值