第1章:微服务架构的演进
1.1 单体架构
任何一个网站在发布初期几乎都不可能立马就拥有庞大的用户流量和海量数据,都是在不停的试错过程中一步一步演变其自身架构,满足其自身业务。比如现在能够抗住双十一这么大流量的淘宝,它的技术最早用的是 LAMP(Linux+Apache+Mysql+Php)。
实际上,架构越复杂,意味着业务的体量越庞大。
对于一个刚刚起步的项目,我们会选择最简单最快速的方式来实现。而单体架构是最好的选择,目前很多的传统软件行业仍然采用这类的架构。
一般的实施方案是,把所有的功能模块都打包在一个(jar、war),并且部署在一个 web 容器下,比如 tomcat、weblogic、jboss 中运行
1.2 集群架构
一旦用户量以及流量开始增加,服务器的性能就会遇到瓶颈,这个时候必须要对系统架构做调整以及优化。而在这个阶段主要需要解决的问题是提升业务系统的并行处理能力,降低单机系统负载,以便支撑更多的用户访问操作。
集群就是一种很好的方式,它可以把多台独立的服务器通过网络连接进行组合,对外形成一个整体提供服务。当一台服务器的处理能力接近或已超出其容量上限时,我们不会去尝试换一个更高性能的服务器,因为投入产出比不高,一般的做法就是采用集群技术,通过增加新的服务器来分散并发访问流量,只要业务系统能够随意支持服务器的横向扩容,那么从理论上来说就应该无惧任何挑战,从而实现可伸缩性和高可用性架构。
1.3 业务垂直化拆分
虽然通过集群可以提升并行处理能力以及对于高可用的实现,但是同时还需要考虑到业务的复杂度,如果仍然把所有的业务逻辑全部耦合在一起放在一个 war 包中来管理,那对于代码的维护和扩展来说是非常困难的。而且如果某个业务功能出现故障,会导致整个系统不可用。所以这个阶段要做的就是降低业务的耦合度,提升系统的容错性。
所以这个时候可以对业务进行垂直化拆分,简单来说,就是可以按照系统的业务功能拆分出多个业务模块,比如电商网站,会拆分出:首页、用户、搜索、订单、支付、商品等子系统。每个子系统由不同的业务团队负责。
1.4 服务化改造
随着对业务系统进行垂直化改造之后,以业务功能纬度拆分出来多个子系统,而在各个子系统中,会存在比较多的共享业务,比如用户信息查询,在支付业务中会涉及到、在首页中也会涉及到。那么势必会造成重复开发产生非常多的冗余代码。那么这个时候就引入了服务化改造的思想,也就是 SOA把一些通用的、会被多个上层服务调用的模块独立拆分出来,形成一些共享的基础服务。这些被拆分出来的共享服务相对来说是比较独立,并且可重用。 比如用户管理服务,包含用户注册、用户查询等功能。比如单点登录服务;
SOA 的核心目标就是通过服务的流程化来实现业务的灵活性,而这个流程化其实就是一系列相关联的任务组成,这一系列相关联的任务可以通过一系列的服务组合来实现具体的业务功能SOA 面向服务架构,从语义上说,它与面向过程、面向对象、面向组件一样,是一种软件组建及开发的方式。所以在 SOA 中,服务是最核心的抽象手段,业务被划分为一些列粗粒度的业务服务和业务流程
SOA 中更强调 ESB 企业服务总线,企业服务总线可以使得服务之间的交互是动态的,以及服务位置是透明的。这样的好处是服务的调用者和服务的提供者之间是高度解耦的。从而使得服务有更高的灵活性以及隔离性。
ESB: 是从面相服务架构(SOA)发展过来的,主要是对多个系统中的服务调用者和服务提供者的解耦。ESB 本身提供了服务暴露、接入、协议转化、数据格式转化、路由等功能。
SOA 主要解决的问题:
-
信息孤岛
-
互联互通
-
业务重用
1.5 微服务架构
业务系统实施服务化改造后,原本共享的业务被拆分,形成可复用的服务,可以在最大程度上避免共享业务的重复建设、资源连接瓶颈等问题出现。那么那些被拆分出来的服务,是否也需要以业务功能为维度来进行拆分,使之能够独立进行部署,以降低业务藕合和提升容错性呢?
微服务并不是一种新思想的方法。它更像是一种思想的精炼,是一种服务化思想的最佳实践方向而已,所以我认为微服务其实是在 SOA 思路下,随着各个企业对于服务化治理上不断的完善,以及对软件的交付链路以及基础设施逐步成熟之下的一种自然的产物。 微服务也是一种面向服务的架构模型,只是它更强调服务的粒度。也就是服务的职责更加单一更加精炼我们也可以把 SOA 看成是微服务的超集。 也就是多个微服务可以组成一个 soa 服务。
1.6 微服务和 SOA 架构的区别
经常会有同学问,微服务和 SOA 架构有什么区别。这个区别一定要从架构的发展过程来了解。这两种架构模式,其实本质上应该是在分布式架构这条时间线上,基于服务化思想的不断完善,以及基础设施的逐步成熟之下的一种升级。既然存在于时间线的先后,那也就意味着,这两种架构模式所关注的点不一样
-
SOA 关注的是服务的重用性、以及解决企业内部的信息孤岛问题
-
微服务关注的是解耦,解耦和可重用性在特定的角度来看是一样,但本质上是不同的。解耦是降低业务之间的耦合度(也就是微服务关注的服务粒度),而可重用性关注的是服务的复用
-
微服务会使用更轻量级的通信协议,使用 Restful 风格的 API。轻量级协议可以很好的支持跨语言,是的语言生态更加丰富
-
微服务会更多的关注 Devops 的持续交付,因为服务粒度更细使得开发运维变得更加重要。所以微服务对于容器化技术的结合更加紧密
-
SOA 应该是微服务的超集
随着架构的不断演进,底层框架为了满足需求也在不断的努力,spring为了简化开发,从最开始xml配置到后面的注解配置,其实都在简化开发这条路上不断努力,但是spring依然做的不够,而且也无法满足微服务架构的各种组件引入带来的各种配置,这个时候springboot产生了,那么接下来,我们先来看看spring做出了哪些努力,又有什么不足之处。
第2章:Spring的演进
spring的核心思想实际上就是IoC、DI、AOP三大块,它的核心目的就是为了简化开发,容器化管理我们的bean对象。基于这个目的,spring做了很多努力,在一定程度上,spring确实简化了开发,但是随着业务复杂度越来越深,功能需求越来越大,各种组件的出现,spring的使用也开始变的吃力,这个吃力实际上就体现在两个方便:bean对象注入到IoC容器的过程越来越麻烦;配置文件越来越多,无法统一管理。事实上,spring也做过很多的努力,我们现在看看它的发展史吧。
先创建spring的maven项目,然后通过集成springMVC和Mybatis举例
-
项目创建
-
添加依赖包
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-vip-jt-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>spring-vip-jt-demo Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <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> <!--spring 版本号--> <spring.version>5.2.8.RELEASE</spring.version> <!--mybatis 版本号--> <mybatis.version>3.5.6</mybatis.version> </properties> <dependencies> <!--spring 核心包--> <!-- spring start --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- spring end --> <!--mybatis核心包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--日志--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.8.0-alpha0</version> <scope>test</scope> </dependency> <!--j2ee相关包 servlet、jsp、jstl--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--mybatis/spring 包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.6</version> </dependency> <!--MySQL 驱动包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-model</artifactId> <version>3.0</version> </dependency> </dependencies> </project>
-
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Archetype Created Web Application</display-name> <!--welcome pages--> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 解决post乱码解决在url中传递中文参数时的乱码 --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <!-- 配置所有请求都经过该拦截器,即所有资源都统一使用 utf-8 防止乱码 --> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置springmvc DispatcherServlet--> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!--配置dispatcher.xml作为mvc的配置文件--> <param-name>contextConfigLocation</param-name> <param-value>classpath:springMVC.xml</param-value> </init-param> <!-- 1、load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法); 2、当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet; 3、当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载; 4、正数的值越小,该servlet的优先级越高,应用启动时就越先加载; 5、当值相同时,容器就会自己选择顺序来加载。 --> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <!-- /* 可以匹配所有的请求--> <!-- 会匹配到所有像 /login 这样的路径型url,但不会匹配到 后缀型的url(即 *.html等) --> <url-pattern>/</url-pattern> </servlet-mapping> <!--把applicationContext.xml加入到配置文件中--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
-
配置springMCV.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--此文件负责整个mvc中的配置--> <!-- 自动扫描装配 --> <context:component-scan base-package="com.example"/> <!--启用spring的一些annotation --> <context:annotation-config/> <!-- 配置注解驱动 可以将request参数与绑定到controller参数上 --> <mvc:annotation-driven/> <!--静态资源映射--> <!--本项目把静态资源放在了webapp的statics目录下,资源映射如下--> <mvc:resources mapping="/css/**" location="/css/"/> <mvc:resources mapping="/js/**" location="/js/"/> <mvc:resources mapping="/image/**" location="/images/"/> <mvc:default-servlet-handler /> <!--这句要加上,要不然可能会访问不到静态资源,具体作用自行百度--> <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP--> <!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- --> <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/views/"/><!--设置JSP文件的目录位置--> <property name="suffix" value=".jsp"/> <property name="exposeContextBeansAsAttributes" value="true"/> </bean> </beans>
-
配置applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- demo02包通过注解自动扫描 --> <context:component-scan base-package="com.example.demo02"/> </beans>
-
创建a.jsp
<html> <body> <h2>${version}</h2> <h2>${name}:${msg}</h2> </body> </html>
2.1 Spring1.x时代
在此时因为jdk1.5刚刚出来,注解开发并未盛行,因此一切Spring配置都是xml格式,想象一下所有的bean都用xml配置,细思极恐啊,心疼那个时候的程序员2秒
-
在applicationContext.xml中配置
<!-- demo01包通过xml配置 --> <bean id="helloService01" class="com.example.demo01.HelloService01"/>
-
controller
package com.example.demo01; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Eclipse_2019 * @create 2021/7/31 17:52 */ @Controller public class HelloController01 { @Autowired private HelloService01 helloService01; @RequestMapping("/hello01") public ModelAndView hello01(@RequestParam String name){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("version","1.X版本"); modelAndView.addObject("name",name); modelAndView.addObject("msg",helloService01.sayHello(name)); modelAndView.setViewName("a"); return modelAndView; } }
-
service
public class HelloService01 { public String sayHello(String name){ return "你真棒!"+name; } }
-
测试
-
public class DemoMain { public static void main(String[] args) { // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml"); System.out.println(context.getBean(HelloService01.class)); } }
-
Tomcat启动
-
2.2 Spring2.x时代
Spring引入了注解开发,但是因为并不完善,因此并未完全替代xml,此时的程序员往往是把xml与注解进行结合,貌似我们之前都是这种方式。
-
@Required/@Repository/@Aspect
spring 2.5
-
@Component
-
@Service
-
@Controller
-
@RequestMapping
-
在applicationContext.xml增加配置
<context:component-scan base-package="com.example.demo02"/>
-
controller
@Controller public class HelloController02 { @Autowired private HelloService02 helloService02; @RequestMapping("/hello02") public ModelAndView hello(@RequestParam String name){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("version","2.X版本"); modelAndView.addObject("name",name); modelAndView.addObject("msg",helloService02.sayHello(name)); modelAndView.setViewName("a"); return modelAndView; } }
-
service
@Service public class HelloService02 { public String sayHello(String name){ return "你好帅啊!"; } }
-
测试
-
public class Demo02Main { public static void main(String[] args) { ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml"); System.out.println(context.getBean(HelloController02.class)); } }
-
Tomcat
-
2.3 Spring3.x时代
2.3.1 Configuration
3.0以后Spring的注解已经非常完善了,因此Spring推荐大家使用完全的java配置来代替以前的xml,不过似乎在国内并未推广盛行。然后当SpringBoot来临,人们才慢慢认识到java配置的优雅。
-
@Configuration 去XML化
-
configuration
package com.example.demo03; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author Eclipse_2019 * @create 2021/8/3 17:16 */ @Configuration public class SpringConfiguration { @Bean public HelloService03 helloService03(){ return new HelloService03(); } @Bean public HelloController03 helloController03(){ return new HelloController03(); } }
-
controller同2.x版本
-
service
public class HelloService03 { public String sayHello(String name){ return "你好帅啊!"; } }
-
测试同上
2.4 Spring4.x时代
-
@Conditional
springboot条件注解
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean) @ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean) @ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean) @ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean) @ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean) @ConditionalOnNotWebApplication(不是web应用)
2.5 集成Mybatis
集成Redis或者mybatis要怎么做:
1.导包
2.创建配置文件
mybatis配置举例:
-
配置spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--1 引入属性文件,在配置中占位使用 --> <context:property-placeholder location="classpath*:db.properties" /> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--配置数据库信息--> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--声明MyBatis中提供的SqlSessionFactoryBean,用于创建SqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--引用注入,将数据库连接池赋值给dataSource--> <property name="dataSource" ref="dataSource"/> <!--MyBatis主配置文件位置,configLocation为Resource类型,读取配置文件--> <property name="configLocation" value="classpath:mybatis.xml"></property> <!--用于指定mapper.xml文件的位置 如果Mapper.xml与Dao接口文件在同一个包下且同名,spring中MapperScannerConfigurer扫描Dao接口文件的同时会自动扫描同名的Mapper.xml并装配到Dao接口文件 如果Mapper.xml与Dao接口文件不在同一个包下或者不同名,就必须使用配置mapperLocations指定mapper.xml的位置 此时spring是通过识别mapper.xml中的<mapper namespace=""> namespace的值来确定对应的Mapper.class--> <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/> </bean> <!--创建Dao对象,使用SqlSession的getMapper(dao.class) MapperScannerConfigurer:在内部调用getMapper()生成每个Dao接口的代理对象--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--指定sqlSessionFactory的ID--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!--指定包名,包名为Dao接口所在包名,MapperScannerConfigurer扫描该包,为每个接口执行getMapper()方法, 得到每个接口的Dao对象,创建好的Dao对象放入Spring容器--> <property name="basePackage" value="com.example.demo07"/> </bean> </beans>
-
配置mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- settings --> <settings> <!-- 打开延迟加载的开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 将积极加载改为消极加载(即按需加载) --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 打开全局缓存开关(二级缓存)默认值就是 true --> <setting name="cacheEnabled" value="true"/> </settings> <!-- 别名定义 --> <typeAliases> <package name="com.example.demo07"/> </typeAliases> <!-- 加载映射文件 --> <mappers> <mapper class="com.example.demo07.UserDao"/> </mappers> </configuration>
通过上面这种方式才能把mybatis注入到我们springIOC容器中,但是这种方式太麻烦了。怎么做更简便呢?
第3章:SpringBoot应运而生
3.1 简介
3.1.1 是什么
Springboot是Spring项目中的一个子工程,与我们所熟知的Spring-framework 同属于spring的产品:
官网地址
:Spring | Projectsactuator:Production-ready Features
我们可以看到下面的一段介绍:
Takes an opinionated view of building production-ready Spring applications. Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.
翻译一下:
用一些固定的方式来构建生产级别的spring应用。Spring Boot 推崇约定大于配置的方式以便于你能够尽可能快速的启动并运行程序。
其实人们把Spring Boot 称为搭建程序的脚手架
。其最主要作用就是帮我们快速的构建庞大的spring项目,并且尽可能的减少一切xml配置,做到开箱即用,迅速上手,让我们关注与业务而非配置。
3.1.2 为什么
java一直被人诟病的一点就是臃肿、麻烦。当我们还在辛苦的搭建项目时,可能Python程序员已经把功能写好了。为了解决这些问题,然后出现了一个框架叫做Spring,Spring翻译过来就是春天,意味着程序员的春天来了,但是真的是这样吗?其实大佬们创建出Spring这个框架本质上就是为了给程序员们减负,为了使我们构建项目更加便捷,为了让我们开发更加快速,但是呢,早期的Spring框架还是会有很多问题,最主要的两点就是:
-
复杂的配置
项目各种配置其实是开发时的损耗, 因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。
-
一个是混乱的依赖管理
项目的依赖管理也是件吃力不讨好的事情。决定项目里要用哪些库就已经够让人头痛的了,你还要知道这些库的哪个版本和其他库不会有冲突,这难题实在太棘手。并且,依赖管理也是一种损耗,添加依赖不是写应用程序代码。一旦选错了依赖的版本,随之而来的不兼容问题毫无疑问会是生产力杀手。
而SpringBoot让这一切成为过去!
Spring Boot 简化了基于Spring的应用开发,只需要“run”就能创建一个独立的、生产级别的Spring应用。Spring Boot为Spring平台及第三方库提供开箱即用的设置(提供默认设置,存放默认配置的包就是启动器),这样我们就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。
我们可以使用SpringBoot创建java应用,并使用java –jar 启动它,就能得到一个生产级别的web工程。
3.1.3 特性
Spring Boot 主要目标是:
为所有 Spring 的开发者提供一个非常快速的、广泛接受的入门体验
开箱即用(启动器starter-其实就是SpringBoot提供的一个jar包),但通过自己设置参数(.properties),即可快速摆脱这种方式。
提供了一些大型项目中常见的非功能性特性,如内嵌服务器、安全、指标,健康检测、外部化配置等
绝对没有代码生成,也无需 XML 配置。
自动配置、Starter组件、Actuator、命令行界面(CLI) 是 Spring Boot 最重要的 4 大核心特性,其中 CLI 是 Spring Boot 的可选特性,虽然它功能强大,但也引入了一套不太常规的开发模型,因而这里仅关注其它 3 种特性。
3.2 快速入门
接下来,我们就来利用Springboot快速搭建一个web工程
3.2.1 创建工程
3.2.2编写controller
@RestController
public class HelloController {
@GetMapping("hello")
public String hello(){
return "hello, spring boot!";
}
}
3.2.3 启动项目
接下来,我们运行main函数,查看控制台:
监听的端口是8080
打开页面访问:http://localhost:8080/hello
3.3 集成mybatis
引包
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
-
配置文件
spring.datasource.username=root spring.datasource.password=jingtian spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.8.74:3306/test server.port=8080 mybatis.mapper-locations=classpath:*Mapper.xml
-
controller
package com.example.springbootvipjtdemo.demo01.controller; import com.example.springbootvipjtdemo.demo01.dao.entity.User; import com.example.springbootvipjtdemo.demo01.services.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** * @author Eclipse_2019 * @create 2021/8/2 16:33 */ @RestController public class HelloController { @Autowired IUserService userService; @PostMapping("addUser") public String addUser(@RequestBody User user){ int a = userService.insert(user); if(a!=0){ return "插入成功"; }else{ return "失败"; } } }
-
service
package com.example.springbootvipjtdemo.demo01.services; import com.example.springbootvipjtdemo.demo01.dao.entity.User; public interface IUserService { int insert(User user); } package com.example.springbootvipjtdemo.demo01.services.impl; import com.example.springbootvipjtdemo.demo01.dao.entity.User; import com.example.springbootvipjtdemo.demo01.dao.mappers.UserMapper; import com.example.springbootvipjtdemo.demo01.services.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author Eclipse_2019 * @create 2021/8/2 16:47 */ @Service public class UserServiceImpl implements IUserService { @Autowired UserMapper userMapper; @Override public int insert(User user) { return userMapper.insert(user); } }
-
dao
package com.example.springbootvipjtdemo.demo01.dao.mappers; import com.example.springbootvipjtdemo.demo01.dao.entity.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper { int insert(User user); }
-
mapper
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.springbootvipjtdemo.demo01.dao.mappers.UserMapper"> <resultMap id="BaseResultMap" type="com.example.springbootvipjtdemo.demo01.dao.entity.User"> <id column="userid" property="userID"/> <result column="username" property="userName"/> </resultMap> <insert id="insert" parameterType="com.example.springbootvipjtdemo.demo01.dao.entity.User" keyProperty="userId" useGeneratedKeys="true"> insert into user(username,age) values(#{userName,jdbcType=VARCHAR},#{age,jdbcType=BIGINT}) </insert> </mapper>
-
启动类
package com.example.springbootvipjtdemo.demo01; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("com.example.springbootvipjtdemo.demo01.dao.mappers") @SpringBootApplication(scanBasePackages = {"com.example.springbootvipjtdemo.demo01"}) public class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/76729.html