参考
B站颜群老师SpringBoot教程,尚硅谷SpringBoot教程,纯洁的微笑
https://www.jianshu.com/p/7293b148028f
微服务
单体应用
在没有提出微服务的概念的“远古”年代,一个软件应用,往往会将应用所有功
能都开发和打包在一起,那时候的一个B/S应用架构往往是这样的
当用户访问量变大导致一台服务器无法支撑时怎么办呢?加服务器加负载均衡
,架构就变成这样了
后面发现把静态文件独立出来,通过CDN等手段进行加速,可以提升应用的整
体相应,单体应用的架构就变成
上面3中架构都还是单体应用,只是在部署方面进行了优化,所以避免不了单体
应用的根本的缺点:
- 代码臃肿,应用启动时间长 (代码超过1G的项目都有!)
- 回归测试周期长,修复一个小小bug可能都需要对所有关键业务进行回归测试
- 应用容错性差,某个小小功能的程序错误可能导致整个系统宕机
- 伸缩困难,单体应用扩展性能时只能整个应用进行扩展,造成计算资源浪费
- 开发协作困难,一个大型应用系统,可能几十个甚至上百个开发人员,大家
都在维护一套代码的话,代码merge复杂度急剧增加
SOA
SOA(Service-Oriented Architecture)-面向服务的体系架构。其中包含
多个服务,而服务之间通过配合最终会提供一系列功能,一个服务通常以独
立的形式存在于操作系统的进程中,服务之间通过网络调用,而非采用进程
内调用的方式进行通信,微服务应该算是SOA的一种演进
微服务概述
微服务需要满足的要求
- 单一职责的。一个微服务应该都是单一职责的,这才是“微”的体现,一个微
服务解决一个业务问题(注意是一个业务问题而不是一个接口)
- 面向服务的。将自己的业务能力封装并对外提供服务,这是继承SOA的核心
思想,一个微服务本身也可能使用到其它微服务的能力
微服务架构
微服务架构,核心是为了解决应用微服务化之后的服务治理问题。应用微服务
化之后,首先遇到的第一个问题就是服务发现问题,一个微服务如何发现其
他微服务呢?最简单的方式就是每个微服务里面配置其他微服务的地址,但
是当微服务数量众多的时候,这样做明显不现实。所以需要使用到微服务架
构中的一个最重要的组件:服务注册中心,所有服务都注册到服务注册中
心,同时也可以从服务注册中心获取当前可用的服务清单
解决服务发现问题后,接着需要解决微服务分布式部署带来的第二个问题:
服务配置管理的问题。当服务数量超过一定程度之后,如果需要在每个服务
里面分别维护每一个服务的配置文件,运维人员估计要哭了。那么,就需要
用到微服务架构里面第二个重要的组件:配置中心,微服务架构就变成下
面这样了
以上应用内部的服务治理,当客户端或外部应用调用服务的时候怎么处理呢
?服务A可能有多个节点,服务A、服务B和服务C的服务地址都不同,服务授
权验证在哪里做?这时,就需要使用到服务网关提供统一的服务入口,最
终形成典型微服务架构
微服务框架
目前国内企业使用的微服务框架主要是Spring Cloud和Dubbo(或DubboX
),但是Dubbo 那两年的停更严重打击了开发人员对它的信心,Spring
Cloud 已经逐渐成为主流。Spring Cloud全家桶提供了各种各样的组件
,基本可以覆盖微服务的服务治理的方方面面,以下列出了Spring
Cloud一些常用组件
SpringBoot入门
SpringBoot概述
Spring Boot 是由Pivotal 团队提供的全新框架,其设计目的是用来简化
新Spring 应用的初始搭建以及开发过程。它默认配置了很多框架的使用方
式,就像Maven 整合了所有的Jar 包,Spring Boot 整合了所有的框架
SpringBoot的好处
其实就是简单、快速、方便!SpringBoot可以快速开发一个微服务。可以简化
j2ee的开发,可以整合各种技术,使用嵌入式servlet 容器不需要打成war
包,去除大量配置,starters自动依赖于版本控制。springboot 最终打成
的jar包是可执行的jar包,不能作为普通的jar包被其他项目依赖,即使依
赖也无法使用其中的类
SpringBoot目录结构
Spring Boot 的基础结构共三个文件
- src/main/java 程序开发以及主程序入口
- src/main/resources 配置文件
- src/test/Java 测试程序
Spring Boot 建议的目录结果如下:root package 结构:
com.example.myproject
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| com +- example +- myproject +- Application.java | +- model | +- Customer.java | +- CustomerRepository.java | +- service | +- CustomerService.java | +- controller | +- CustomerController.java |
|
- Application.java 建议放到根目录下面,主要用于做一些框架配置
- model 目录主要用于实体与数据访问层(Repository)
- service 层主要是业务类代码
- controller 负责页面访问控制
最后启动Application的main 方法,至此一个Java 项目搭建好了!
引入Web模块
- pom.xml中添加支持web的模块
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
|
pom.xml 文件中默认有两个模块
- spring-boot-starter 核心模块,包括自动配置支持、日志和YAML,
如果引入了spring-boot-starter-web web 模块可以去掉此配置,因
为spring-boot-starter-web 自动依赖了spring-boot-starter
- spring-boot-starter-test 测试模块,包括 JUnit、Hamcrest、Mockito
单元测试
打开的src/test/下的测试入口,编写简单的http 请求来测试,使用
mockmvc 进行,利用MockMvcResultHandlers.print()打印出执行
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @RunWith(SpringRunner.class) @SpringBootTest public class HelloTests { private MockMvc mvc; @Before public void setUp() throws Exception { mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()). build(); } @Test public void getHello() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/hello").accept( MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string(equalTo("Hello World"))); } }
|
开发环境调试
springBoot对调试支持很好,修改之后可以实时生效,需要添加以下的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build>
|
部署
不用打成war包,导入maven插件可以将应用打包成可执行的jar包
1 2 3 4 5 6 7 8
| <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
|
场景启动器starter
pom文件中导入的父项目
1 2 3 4 5 6
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.3.RELEASE</version> <relativePath/> </parent>
|
发现父项目还依赖一个父项目
1 2 3 4 5 6
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.3.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
|
进入dependencies中真正管理springboot应用中的所有依赖版本,以后导
入依赖默认不需要写版本,也有没有再dependencies中管理的依赖需要些
版本
1 2 3 4 5 6 7 8 9
| <properties> <activemq.version>5.15.11</activemq.version> <antlr2.version>2.7.7</antlr2.version> <appengine-sdk.version>1.9.77</appengine-sdk.version> <artemis.version>2.10.1</artemis.version> <aspectj.version>1.9.5</aspectj.version> <assertj.version>3.13.2</assertj.version> .... </properties>
|
导入的依赖
spring-boot-starter:springboot场景启动器
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
|
进入spring-boot-starter-web,帮我们导入了web模块正常运行所依赖的
组件,springboot将 所有的功能场景都抽取出来做成一个个的starters
(启动器),只需要引用starter相关场景的依赖都会被导入进来,用什么
功能就导入什么场景的启动器
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 44
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.2.3.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.2.3.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.2.3.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.2.3.RELEASE</version> <scope>compile</scope> <exclusions> <exclusion> <artifactId>tomcat-embed-el</artifactId> <groupId>org.apache.tomcat.embed</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.3.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.3.RELEASE</version> <scope>compile</scope> </dependency> </dependencies>
|
helloworld细节-自动配置
@SpringBootConfiguration
组合注解中@SpringBootConfiguration标注在某个类上表示这是一个springboot配置类,
打开该注解
1 2 3 4 5 6 7 8 9 10
| @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { @AliasFor( annotation = Configuration.class ) boolean proxyBeanMethods() default true; }
|
@Configuration spring定义的注解,标注这是一个配置类,相当于配置
文件,打开该注解
1 2 3 4 5 6 7 8 9 10 11 12
| @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor( annotation = Component.class ) String value() default "";
boolean proxyBeanMethods() default true; }
|
@Component 该配置类也是容器中的一个组件
@MapperScan
这个接口我在秒杀项目中使用过,指定要变成实现类的接口所在的包,然后包下
面的所有接口在编译之后都会生成相应的实现类
@EnableAutoConfiguration
该注解开启自动配置功能,以前需要配置的东西比如spring和springmvc
而springboot自动配置
1 2 3 4 5 6 7 8 9
| @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { ... }
|
@AutoConfigurationPackage 自动配置包,打开该注解
1 2 3 4 5 6 7
| @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({Registrar.class}) public @interface AutoConfigurationPackage { }
|
@Import({Registrar.class}) spring的底层注解,给容器导入一个组
件,打开Registrar
1 2 3 4 5 6
| public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)) .getPackageName()); }
|
将主配置类的所在包以及所有子包里面的所有主键扫描到springioc容器中
选择器
@Import({AutoConfigurationImportSelector.class}) 给容器导入组
件,打开该注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata( this.beanClassLoader); AutoConfigurationImportSelector. AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry( autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray( autoConfigurationEntry.getConfigurations()); } }
|
将所有需要导入的组件以全类名的方式返回添加到容器中
补充
springboot进行单元测试的模块
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
|
springboot配置
application.properties和application.yml
全局的配置文件,名字是固定的。两种格式写法有差别。YAML是以数据为中
心比json/xml更适合做配置文件,spring-boot-starter-parent默认
使用Tomcat作为web容器,如果需要对Tomcat进一步配置可以在配置文
件中配置
properties
1 2
| server.port=8081 server.servlet.context-path=/springboot
|
yaml语法
K: value表示一对键值对(注意空格),只要是左对齐的一列数据都是
同一层级
1 2 3
| server: port: 8001 path: /hello
|
值的写法包括普通的值、对象、map、数组,字符串默认不用加引号。双引号
不会转义字符串特殊字符会作为本身想表示的意思(\n会换行),单引号
会转义特殊字符最终只是一个普通的字符串(\n不会换行)
对象写法有两种
1 2 3 4
| person: name: fd age:12 person: {name: fd,age: 12}
|
数组写法用-表示一个元素
1 2 3 4 5
| pets: - cat - dog - pig pets: [cat,dog,pig]
|
创建一个类Person
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.atguigu.controller.bean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Date; import java.util.HashMap;
@Component @ConfigurationProperties(prefix="person") public class Person { private String lastName; private int age; private boolean boss; private Date birth; private HashMap<String,Object> maps; private ArrayList<Object> list; private Dog dog; public String toString(){ return this.lastName+","+this.age+","+this.birth+ ","+this.boss+","+this.dog+","+this.list+ ","+this.maps; } ... }
|
创建Dog类
1 2 3 4 5 6
| package com.atguigu.controller.bean; public class Dog { private String name; private int age; ... }
|
在yaml文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| person: lastName: zhangsan age: 18 boss: true birth: 2017/12/12 maps: name1: nn name2: mm list: - fsd - fdsv - cv - vvv dog: name: fdf age: 11
|
配置文件属性与组件映射
@ConfigurationProperties(prefix=”person”) 告诉springboot将本
类中的所有属性与配置文件相关的配置进行绑定,prefix获取配置文件中
的属性person,要使用该注解需要导入依赖,只有这个组件是容器中的
组件才可以使用该注解的功能,所以@Component
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
|
测试
springboot单元测试。@SpringBootTest 标明是单元测试。可以在测试期
间很方便的类似编码一样进行自动注入等容器的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.atguigu.spring; import com.atguigu.controller.bean.Person; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class springbootconfigurationtest { @Autowired Person person; @Test public void contextLoads() { System.out.println(person); } }
|
@ConfigurationProperties与@Value的区别
除了使用@ConfigurationProerties之外还可以使用@Value赋值,可以是字
面量、${key}从环境变量、配置文件中获取值、#{SpEL}计算表达式。如果说,
我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接
使用@ConfigurationProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Component @Validated
public class Person { @Email @Value("${person.lastName}") private String lastName; @Value("#{11*2}") private int age; @Value("true") private boolean boss; private Date birth; private HashMap<String,Object> maps; private ArrayList<Object> list; private Dog dog; public String toString(){ return this.lastName+","+this.age+","+this.birth+ ","+this.boss+","+this.dog+","+this.list+ ","+this.maps; } ... }
|
@PropertySource和ImportResource
@PropertySource
加载指定的配置文件。@ConfigurationProperties(prefix=”person”)
默认都是写在全局配置文件中,默认从全局配置文件中获取值。可以创建
一个person.properties文件将与perosn有关的配置写在这个文件中
1 2 3 4 5 6 7 8 9
| person.lastName= lisi person.age= 18 person.boss= true person.birth: 2017/12/12 person.maps.name1= nn person.maps.name2= mm person.list= fsd,fdsv,cv,vvv person.dog.name: fdf perosn.dog.age= 11
|
在person类中加入注解,注意该注解目前只支持properties文件不支持yml
1 2 3 4
| @PropertySource(value={"classpath:person.properties"})
@Component @ConfigurationProperties(prefix="person")
|
@ImportResource
导入spring的配置文件,让配置文件中的内容生效Spring Boot里面没有Spring
的配置文件,我们自己编写的配置文件,也不能自动识别想让Spring的配置文件
生效,加载进来。@ImportResource标注在一个配置类上
Profile
- Profile是spring对不同环境提供不同配置功能的支持,可以通过激活、指定
参数等方式快速切换环境。主配置文件名可以是application-{profile}.
properties/yml,在默认配置文件 application.properties中可以
激活某个环境1
| spring.profiles.active=dev
|
如果使用yaml文件格式可以有多文档块1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| server: port: 8080 spring: profiles: active: dev ---
server: port: 8081 spring: profiles: dev
---
server: port: 8082 spring: profiles: prod
|
- application-dev.yml
- application-prod.yml
- 可以使用命令行模式激活profile
在program arguments中指定 –spring.profiles.active=dev
- 打包之后可以用命令行指定环境运行
jar -jar .. –spring.profiles.active=dev
- 可以配置虚拟机参数
在VM options中 –Dspring.profiles.active=dev
springboot配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者
application.yml文件作为Spring boot的默认配置文件
- –file:./config/ 项目根目录下创建config文件夹
- –file:./ 项目根目录直接创建配置文件
- –classpath:/config/ 在resources文件夹下创建
- –classpath:/
优先级由高到底,高优先级的配置会覆盖低优先级的配置,SpringBoot会从
这四个位置全部加载主配置文件,互补配置我们还可以通过spring.config.
location来改变默认的配置文件位置。项目打包好以后,我们可以使用命令
行参数的形式,启动项目的时候来指定配置文件的新位置,指定配置文件和
默认加载的这些配置文件共同起作用形成互补配置
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar –
spring.config.location=G:/application.properties
外部配置加载顺序
SpringBoot也可以从以下位置加载配置优先级从高到低;高优先级的配置覆
盖低优先级的配置,所有的配置会形成互补配置
- 命令行参数
所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar –server.port
=8087 –server.context-path=/abc多个配置用空格分开 –配置项=值
- 来自java:comp/env的JNDI属性
- Java系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找优先加载带profile
- jar包外部的application-{profile}.properties或application.yml
(带spring.profile)配置文件
- jar包内部的application-{profile}.properties或application.yml
(带spring.profile)配置文件再来加载不带profile
- jar包外部的application.properties或application.yml
(不带spring.profile)配置文件
- jar包内部的application.properties或application.yml
(不带spring.profile)配置文件
- @Configuration注解类上的@PropertySource
- 通过SpringApplication.setDefaultProperties指定的默认属性
自动配置原理
能在application.properties和application.yml文件中配置的属性
添加的组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
SpringFactoriesLoader.loadFactoryNames()
org.springframework.boot.autoconfigure. EnableAutoConfiguration=\ org.springframework.boot.autoconfigure. admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAuto ...
|
配置@Conditional
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配
里面的所有内容才生效
自动配置类必须在一定的条件下才能生效,我们怎么知道哪些自动配置类生效
我们可以通过启用debug=true属性;来让控制台打印自动配置报告,这样我
们就可以很方便 的知道哪些自动配置类生效
springboot与数据访问
整合mybatis
导入相关依赖
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency>
|
创建如下结构的目录结构
entity
在entity中编写实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.atguigu.mybatis.entity; import org.apache.tomcat.jni.Address; public class Pperson { private int id; private String name ; private int age; private boolean sex; private Address address; ... } package com.atguigu.mybatis.entity;
public class Address { private String homeAddress; private String schoolAddress; ... }
|
mapper
在mapper中编写接口并且加上@Mapper注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.atguigu.mybatis.mapper; import com.atguigu.mybatis.entity.Pperson; import org.apache.ibatis.annotations.Mapper; import java.util.HashMap; import java.util.List; @Mapper public interface Ppermapper { Pperson querybyid(int id); List<Pperson> queryall(); void addpperson(Pperson p); void deletebyid(int id); void updatebyid(Pperson p); List<Pperson> queryaddress(Pperson p); List<Pperson> queryhash(HashMap<String,Object> map); }
|
service
添加service类
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
| package com.atguigu.mybatis.service; import com.atguigu.mybatis.entity.Pperson; import com.atguigu.mybatis.mapper.Ppermapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; @Service public class Pperservice { @Autowired private Ppermapper ppermapper; public Pperson querybyid(int id) { return ppermapper.querybyid(id); } public List<Pperson> queryall(){ return ppermapper.queryall(); } public void addpperson(Pperson p){ ppermapper.addpperson(p); } public void deletebyid(int id){ ppermapper.deletebyid(id); } public void updatebyid(Pperson p){ ppermapper.updatebyid(p); } public List<Pperson> queryaddress(Pperson p){ return ppermapper.queryaddress(p); } public List<Pperson> queryhash(HashMap<String,Object> map){ return ppermapper.queryhash(map); } }
|
controller
在控制层添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.atguigu.mybatis.controller;
import com.atguigu.mybatis.entity.Pperson; import com.atguigu.mybatis.service.Pperservice; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class Ppercontroller { @Autowired Pperservice ppservice; @ResponseBody @RequestMapping("/hello/{id}") public Pperson hello(@PathVariable int id) { return ppservice.querybyid(id); } }
|
resources中创建Ppermapper.xml文件
- namespace中需要与使用@Mapper的接口对应
- 文件名称必须与使用@Mapper的接口一致
- 标签中的id必须与@Mapper的接口中的方法名一致,且参数一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?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.atguigu.mybatis.mapper.Ppermapper"> <select id="querybyid" resultMap="ppersonresult" parameterType="int" > select * from pperson where id = #{id} </select> <resultMap id="ppersonresult" type="com.atguigu.mybatis.entity.Pperson"> <id property="id" column="id" /> ... </mapper>
|
入口类中添加@MapperScan注解参数为Mapper接口类所在包
1 2
| @MapperScan("com.atguigu.mybatis.mapper") @SpringBootApplication
|
在application.yml中配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/gaoming?serverTimezone=UTC username: root password: 19991005
mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.atguigu.mybatis.entity configuration: map-underscore-to-camel-case: true
|
运行springboot项目
所有依赖
我先把完整的pom.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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| <?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.atguigu</groupId> <artifactId>spring-boot-01-helloworld</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.3.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.5.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </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>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
</dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <properties> <maven.compiler.source>11</maven.compiler.source> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>11</maven.compiler.target> </properties> </project>
|