Spring新手教程

基于《Spring实战》第五版进行学习

让我们来一起学习Java Spring吧!

Spring基础

介绍

Spring 的核心是一个容器,通常称为 Spring 应用程序上下文,用于创建和管理应用程序组件。**这些组件(或 bean)**在 Spring 应用程序上下文中连接在一起以构成一个完整的应用程序。

将 bean 连接在一起的行为是基于一种称为 依赖注入(DI)的模式。依赖项注入的应用程序不是由组件自身创建和维护它们依赖的其他 bean 的生命周期,而是依赖于单独的实体(容器)来创建和维护所有组件,并将这些组件注入需要它们的 bean。通常通过构造函数参数或属性访问器方法完成此操作

如product service依赖(即内部需要一个)inventory service,在Spring中其框架如下:

Spring新手教程_第1张图片

传统方式是使用XML进行配置:



    

但是上面的方式不太放便,现在常用的是利用Java注解的方式:

@Configuration:向spring表明其是一个配置类
public class ServiceConfiguration {
    @Bean:指示其返回的是一个Bean组件
    public InventoryService inventoryService() {
        return new InventoryService();
    }
    
    @Bean:同上,同时还依赖了上一个bean
    public ProductService productService() {
        return new ProductService(inventoryService());
    }
}

使用注解的方式是基于自动配置和自动扫描。

现在可以利用https://start.spring.io/实现快速的Spring项目框架搭建。

有关Spring的注解详情,可参看:Spring注解与测试。

Spring MVC

Spring MVC是Spring附带的web框架,核心是控制器的概念,其是一个处理请求并使用某种信息进行响应的类。

MVC即是:model-view-controller。

其中,controller主要负责处理相应的网络请求,并使用JSP或Themleaf等模板来设计视图(可视化对应的模型)。模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器

如何利用Spring MVC进行Web应用的开发,可见开发Web应用。

Spring与数据库

Spring框架下提供来JDBC和JPA来简化和规范与数据库的交互,大大简化了编写持久化层操作的时间——Spring处理数据库。

Spring Security

应用程序安全性一直是一个重要的主题,而且似乎一天比一天重要。幸运的是,Spring 在 Spring security 中有一个健壮的安全框架。

Spring Security 解决了广泛的应用程序安全性需求,包括身份验证、授权和 API 安全性。

https://potoyang.gitbook.io/spring-in-action-v5/di-4-zhang-spring-an-quan

Spring配置属性

前面已经说到,spring有两种配置:

  • Bean wiring:声明该组件在spring中作为组件,以及应该如何相互注入;
  • Property injection:如何在spring上下文设置bean;

值得一提的是,Spring的环境是所有可配置属性的汇总,包括:

  • JVM系统属性
  • 操作系统环境变量
  • 命令行参数
  • 应用程序属性配置文件

它将上述四种属性汇总到一个环境中,以至于其内的Bean都可以互相调用或注入。

Spring新手教程_第2张图片

Spring配置属性包括服务器、web页面、数据库等等,建议需要配置相关属性的时候再去查询,但是需要提前看看能够配置什么东西,以便在工作时更好地去查找。

Spring集成

Spring框架自己已经功能强大,但还可以通过与其他应用程序集成而变得更强!

REST服务

什么是REST服务?

REST不是”rest”这个单词,而是几个单词的缩写 REpresentation State Transfer,直接翻译:表现层状态转移。比较通俗的说法是:URL定位资源,用HTTP动词(GET,POST,DELETE,PUSH等)描述操作

什么是RESTful?

基于REST构建的API就是Restful风格。

为什么使用Restful?

传统的开发方式是用JSP来作为表现层,这有一个缺点:需要将前端的静态HTML页面转换为JSP页面,降低了开发效率,并且让后端人员还需要关注前端的页面。为了应对这个问题,采用前后端分离。并且Restful可以统一给PC、微信(H5)、IOS或Android提供服务,服务器至提供数据,不提供前端样式前端样式就由前端来关注!

restful详情请见:restful。

restful实例详见:实例。

如何使用Rest API?

Spring 应用程序可以通过以下方式使用 REST API:

  • RestTemplate —— 一个由 Spring 核心框架提供的简单、同步 REST 客户端。

  • Traverson —— 可感知超链接的同步 REST 客户端,由 Spring HATEOAS 提供,灵感来自同名的 JavaScript 库。

  • WebClient —— 一个在 Spring 5 中引入的响应式、异步 REST 客户端。

发送异步消息

Spring可以使用JMS来发送洗哦阿西,也可以使用RabbitMQ以及AMQP、Kafka等消息中间件来实现消息的发送。

  • JMS 是一个 Java 标准,它定义了一个用于使用消息代理的公共 API。

Spring 通过称为 JmsTemplate 的基于模板的抽象来支持 JMS。使用 JmsTemplate,很容易从生产者端跨队列和主题发送消息,并在消费者端接收这些消息。Spring 还支持消息驱动 POJO 的概念:简单的 Java 对象以异步方式对队列或主题上到达的消息做出响应

  • 想要使用RabbitMQ(AMQP协议的具体实现)或Kafka消息中间件,需要先在Spring中进行配置,暂略;

集成Spring

使用 Spring 配置,可以将多个组件组装到数据流经的管道中。从而实现不同组件之间的消息通过传输管道来互相传递。

那么如何配置集成流(即定义数据流向)呢?

  • 使用XML,一个示例如下:


    
    
    
    
    

上述代码的重点在倒数几行:定义了两个channel,并设定了两者之间的数据传输方式,最后的fileWriterChannel通道利用int-file命名空间配置了一个外部通道适配器,将消息写入文件中。

  • 使用XML方式在大型项目中不方便开发和后期更改,依旧是Java注解更好,将上述的XML实现用java注解的方式代码如下:
@Configuration
public class FileWriterIntegrationConfig {
    
    @Bean
    @Transformer(inputChannel="textInChannel", outputChannel="fileWriterChannel")
    public GenericTransformer upperCaseTransformer() {
        return text -> text.toUpperCase();
    }
    
    @Bean
    @ServiceActivator(inputChannel="fileWriterChannel")
    public FileWritingMessageHandler fileWriter() {
        FileWritingMessageHandler handler = 
            new FileWritingMessageHandler(new File("/tmp/sia5/files"));
        handler.setExpectReply(false);
        handler.setFileExistsMode(FileExistsMode.APPEND);
        handler.setAppendNewLine(true);
        return handler;
    }
}
  • 还可以使用DSL配置,与使用Java注解方式不同,它不是通过多个bean,而后设置两者之间的数据传输方式,而是直接定义一个数据流向的bean,直接看代码:
@Configuration
public class FileWriterIntegrationConfig {
    
    @Bean
    public IntegrationFlow fileWriterFlow() {
        return IntegrationFlows
            .from(MessageChannels.direct("textInChannel"))
            .transform(t -> t.toUpperCase())
            .handle(Files.outboundAdapter(new File("/tmp/sia5/files"))
                    .fileExistsMode(FileExistsMode.APPEND)
                    .appendNewLine(true))
            .get();
    }
}

**注:**IntergrationFlow是Spring中的集成类。

使用Spring Integration的DSL可以实现怎样的功能?

集成流由以下一个或多个组件组成:

  • channel:信息从一个组件到另一个组件;
  • Filters:只允许一些满足条件的数据通过集成流;
  • Transformers:对消息进行一些数据处理,一般是数据类型的转换;
  • Routers:通常是基于消息头将信息发送到几个渠道之一;
  • Splitters:将消息分为多条,传送到不同的渠道;
  • Aggregators:将多条消息聚合为一条,分类器的冤家;
  • Service activators:将消息传送给java方法,而后传输返回值到输出;
  • Channel adapters:将通道连接到某些外部系统或传输;
  • Gateways:通过相应的接口将数据传递到集成流;

**注:**所谓Spring集成就是实现多个组件之间的数据交互;

响应式Spring

Reactor就是一个常用的事件反应模型。

什么是Reactor?

当我们开发应用程序时,有两种风格的代码我们可以写——命令式和响应式

  • 命令式(同步式) 的代码是一套串行任务,每次运行一个,完成前一个任务后再完成后一个。数据是批量进行处理的,在前面的任务没有完成批量数据处理前,不能将工作移交到下一个任务

  • 响应式 定义一组任务去处理数据,但这些任务可并行运行。每个任务处理这些数据的一个子集,当它处理另外一个子集的时候,把处理完成的数据交给下一个任务。

应用于一个真实世界的类比就是,**将命令式编程看做一个装水的气球,响应式编程看做花园里面的水管。**两者都是在炎热的夏天让你的朋友惊喜并沉浸其中的方式。但是它们的执行风格是不同的:

  • 命令式 一个水气球一次能携带的它的有效载荷,在撞击的那一刻浸湿了它预定的目标。然而,水球的容量是有限的,如果你想用水泡更多的人(或把同一个人淋得更湿),你唯一的选择就是增加水球的数量

  • 一根花园水龙带将其有效载荷作为一股水流从水龙头流向喷嘴。花园水龙头接的水带的容量可能是有限的,但在打水仗的过程中水是源源不断的。只要水从水龙头进入软管,就会一直通过软管然后从喷嘴喷出。同一个花园软管是很容易扩展的,你和朋友们可以玩得更尽兴

命令式编程就类似打水仗中的水球,本质上没有什么问题,但是拿着类似响应式编程的水管的人在可扩展性和性能方面是有优势的

Reactor就是上面所说的响应式编程。

响应式流

Reactive Stream(响应式流)旨在为无阻塞异步流处理提供标准。它通过四个接口来概括:Publisher、Subscriber、Processor、Subscription。

  • Publisher为每一个Subscription的Subscriber提供数据,Subscriber通过Publisher的接口来订阅:
public interface Publisher {
    void subscribe(Subscriber subscriber);
}
  • Subscriber一旦进行了订阅subsribe,就可以接受Publisher的消息。
  • Subscription式一个消息对象,通过实现这个接口可以获取对象中的消息数据;
  • Processor连接发布者与订阅者,并且两者之间的身份会因为Processor而改变(谁说发布者不能当订阅者了?)

**注:**响应式编程的核心类型为Mono(不多于一个数据项)、Flux(可表示多个数据项)。

实战操作

如何实现一个Spring WebFlux实例可以参考。

如何实现一个响应式数据存储实例可以参考。

Spring Cloud

微服务

在介绍什么式微服务之前,先看看之前几十年的开发方式

你创建一个Web服务的单体应用程序,它构建到一个可部署的 JAR 或 WAR 文件中。开发成单体应用是很正常,几十年来大多数应用程序都是这样构建的。即使将应用程序分解为多模块构建,您最终也仍然会得到一个 JAR 或 WAR 文件,然后再将其推送到生产环境中。

这无疑是构建小型、简单应用程序的最适宜的方法。**但有趣的是,小型应用程序往往会增长。**当需要一个新的特性时,很容易在项目中添加更多的代码。在你意识到大事不妙之前,您的应用就已经变成复杂的单体的应用了

单体应用看似简单,但存在以下问题:

  • 单体应用复杂度高:复杂度越高,越难搞清楚每个组件在整体中的作用;
  • 测试太难:系统越复杂,集成测试就越麻烦;
  • 依赖可能会冲突:两个功能的依赖可能互相冲突;
  • 不易扩展:即便只是修改了一小部分的功能,也需要部署整体;
  • 技术选型比较困难:因为你是在给整体框架选择语言、平台、库等;
  • 上线工作更复杂:一个功能除了问题,可能整个系统都上不了线。

为了解决单体应用的缺点,微服务出现了:简单来说,微服务架构是将应用程序分解成小规模应用的办法,这些小应用独立开发和部署。这些小应用(微服务)相互协调,以提供更完整和强大的应用程序。

它的优点就是上面单体应用的缺点相对面。

**注:微服务现在还没搞清楚不要紧,**因为它是一个出现没几年的概念,很难用之前的概念来解释、区分它,多看看资料慢慢就理解了。

Eureka

由于Spring Cloud太多了,只拿出其中Spring Cloud Netflix的Eureka来简单讲讲。

Eureka 这个词表达的含义,是当一个人找到或发现某事时的一种喜悦的感叹。这个含义,使其成为服务注册中心的最合适的命名。微服务正是通过 Eureka 服务发现彼此。

传说 Eureka 是希腊物理学家阿基米德最先表达出来的。当年他坐在浴缸里洗澡时,发现了浮力的原理,便跳了出来,光着身子跑回家,大喊着“Eureka !”

**注:**传说毕竟是传说。

Eureka 充当微服务应用程序中,**所有服务的中心注册表。**Eureka 本身可以被认为是一个微型的服务,其目的是在更大的范围内帮助其他服务发现彼此。

Spring新手教程_第3张图片

当一个服务实例启动时,它将用自己名称向Eureka注册。如果某个服务有多个实例,他们都以相同的名字在Eureka中注册(相同的名字?)

当另一个服务需要使用某些服务时,它不是通过硬编码(即像函数中写好了参数)的方式去调用服务,而是从Eureka中通过名称去查找服务,而后另一个组件Ribbon会利用负载均衡算法来选择一个合适的服务主机发送给另一个服务

其他

有关Spring Cloud如何进行配置管理,请跳转配置管理。

有关Spring Cloud如何处理失败和时延,请跳转失败解决。

Spring部署

上面所讲的都是Spring的相关理论和组件,是开发时考虑的东西。

那么如何将一个开发好的项目线上部署呢?比如一个Web项目?

主体流程如下:

  • 创建并完成Spring项目
  • 打包成jar格式(如果想部署到web容器,也可以打包成war格式)
  • 部署并启动

详细的操作过程请看:

https://www.jianshu.com/p/3f3c0f5b13f6

致谢

https://potoyang.gitbook.io/spring-in-action-v5/

你可能感兴趣的:(后台开发,互联网,spring,java,大数据,spring,boot,数据库)