spring boot微服务项目搭建
第一章 SpringBoot介绍
1 简介
Spring Boot是一个便捷搭建基于spring工程的脚手架;作用是帮助开发人员快速搭建大型的spring 项目。简化工程的配置和依赖管理;开发人员把时间都集中在业务开发上。
首页Spring Boot简介可以看到下面的一段介绍:
Spring Boot is designed to get you up and running as quickly as possible, with minimal upfront
confifiguration of Spring. Spring Boot takes an opinionated view of building production-ready
applications.
翻译一下:
Spring Boot的设计目的是让您尽可能快地启动和运行,而无需预先配置Spring。Spring Boot以一种固定的方
式来构建可用于生产级别的应用程序。
一般把Spring Boot称为搭建程序的脚手架或者说是便捷搭建基于Spring的工程脚手架。其最主要作用就是帮助开
发人员快速的构建庞大的spring项目,并且尽可能的减少一切xml配置,做到开箱即用,迅速上手,让开发人员关
注业务而非配置。
2 Spring boot特点
- 为基于Spring的开发提供更快的入门体验
- 开箱即用,没有代码生成,也无需XML配置。同时也可以修改默认值来满足特定的需求。
- 提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
- Spring Boot并不是不对Spring功能上的增强,而是提供了一种快速使用Spring的方式。
3 为什么要学习Spring Boot
java一直被人诟病的一点就是臃肿、麻烦。当我们还在辛苦的搭建项目时,可能Python程序员已经把功能写好了,究其原因注意是两点:
复杂的配置
项目各种配置其实是开发时的损耗, 因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。混乱的依赖管理
项目的依赖管理也是件吃力不讨好的事情。决定项目里要用哪些库就已经够让人头痛的了,你还要知道这些库
的哪个版本和其他库不会有冲突,这难题实在太棘手。并且,依赖管理也是一种损耗,添加依赖不是写应用程
序代码。一旦选错了依赖的版本,随之而来的不兼容问题毫无疑问会是生产力杀手。
而Spring Boot让这一切成为过去!Spring Boot 简化了基于Spring的应用开发,只需要“run”就能创建一个独立的、生产级别的Spring应用。
Spring Boot为Spring平台及第三方库提供开箱即用的设置(提供默认设置,存放默认配置的包就是启动器
starter),这样我们就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。
我们可以使用Spring Boot创建java应用,并使用java –jar 启动它,就能得到一个生产级别的web工程。
第二章 入门案例
1 创建SpringBoot项目
idea->file->new->project 选中 Srping Initializr,然后一直下一步就可以了
默认生成的Spring Boot项目;
java文件夹
resources文件夹中目录结构
static:保存所有的静态资源,例如: js,css ,images;
templates:保存所有的模板页面(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面),可以使用模板引擎(freemarker、thymeleaf);
application.properties:Spring Boot应用的配置文件,可以修改一些默认设置;
2 添加依赖
SpringBoot提供了许多“启动器”,启动器在类路径中添加依赖的jar包。
spring-boot-starter-parent是一个特别的启动器,里面已经对各种常用依赖的版本进行了管理,我们的项目需要以这个项目为父工程,这样我们就不用操心依赖的版本问题了。
pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.2</version><relativePath/></parent><groupId>com.xxx</groupId><artifactId>springboot01</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot01</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!-- 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> <!-- 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version><scope>test</scope></dependency><!-- 增加web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
添加web依赖后(spring-boot-starter-web),会发现tomcat、springboot、springmvc等依赖已经加进来了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3a2ZzNkZ-1656551199494)(image/1.png)]
所以启动SpringBoot项目不需要再像ssm一样需要额外的tomcat了。
3 创建代码
创建启动类Springboot01Application
在com/xxx包中创建启动类,这个类要和controller同级
springboot启动原理: 采用springmvc注解方式启动,内置http服务器(默认tomcat),所以不需要额外配置Tomcat
package com.xxx;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用*/
@SpringBootApplication
public class Springboot01Application {//启动应用public static void main(String[] args) {SpringApplication.run(Springboot01Application.class, args);}}
说明:
1 @SpringBootApplication注解
@SpringBootApplication源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@SpringBootApplication:Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
@SpringBootApplication组合注解,兼备了@EnableAutoConfiguration、@Configuration和@ComponentScan 注解的功能。
@EnableAutoConfiguration: 启动自动配置机制
@ComponentScan: 启动组件扫描。
@Configuration: 注册额外的bean或者导入其他配置类。
4 测试
直接运行启动类Springboot01Application即可,控制台出现如下提示,说明启动成功
com.xxx.Springboot01Application: Started Springboot01Application in 1.909 seconds (JVM running for 3.553)
测试完毕!
增加Controller,然后继续测试
写法一:
@RestController
public class HelloController {@RequestMapping("/")public String home() {return "第一个SpringBoot!!!";}}
写法二:
@Controller
public class HelloController {@RequestMapping("/")@ResponseBodypublic String home() {return "第一个SpringBoot!!!";}}
由此可见:@RestController = @Controller+@ResponseBody
通过浏览器访问下面地址:http://127.0.0.1:8080/
浏览器页面出现 “第一个SpringBoot!!!” ,说明搭建成功!
注意:默认端口就是8080。
5 配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的,因为SpringBoot遵从约定大于配置规则。
配置文件位于resources文件夹下,配置文件支持2种风格:
- application.properties
- application.yml
application.properties
SpringBoot会默认扫描这个配置文件,这里的命名只能是application,因为SpringBoot遵从约定大于配置规则。
application.properties示例:
server.port=8080
server.servlet.context-path=/
YAML语法
基本语法:
- k:(空格)v:表示一对键值对(空格必须有)
- 以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
- 属性和值也是大小写敏感
- 值中的字符串默认不用加上单引号或者双引号
application.yml示例:
server:port: 8080servlet-path: /
备注:其实SpringBoot底层会把application.yml文件解析为application.properties
6 @Value读取配置文件
使用@Value可以把配置文件的值直接注入到成员变量中。
案例:
@Controller
//默认获取的是application.properties中的值
//如果不是,则需要加上@PropertySource注解,且指定配置文件名称
//@PropertySource(value = "classpath:application.properties") //可以不配置
//@PropertySource(value = "classpath:user.properties") //必须配置
public class TestController {//方式一@Autowiredprivate Environment environment;//方式二@Value("${server.port}")private String port;@GetMapping("test")@ResponseBodypublic void test() {System.out.println("获取配置文件中的值:" + environment.getProperty("server.port"));System.out.println("获取配置文件中的值port:" + port);}}
7 stater起步器
Starters是一系列很好用的依赖描述符,可以包含在应用程序中。您可以为您需要的所有Spring和相关技术提供一站式服务,而无需搜索示例代码和复制粘贴大量的依赖描述符。例如,如果您想开始使用Spring和JPA进行数据库访问,只需将spring-boot-starter-data-jpa
项目中的依赖项即可。
starter包含了一系列依赖,且支持传递依赖。
下面的starter由SpringBoot提供,放在org.springframework.boot
包下面。
名称 | 描述 |
---|---|
spring-boot-starter
|
核心starter,包括自动配置支持、日志记录和YAML。 |
spring-boot-starter-activemq
|
Starter for JMS messaging using Apache ActiveMQ |
spring-boot-starter-amqp
|
Starter for using Spring AMQP and Rabbit MQ |
spring-boot-starter-aop
|
Starter for aspect-oriented programming with Spring AOP and AspectJ |
spring-boot-starter-artemis
|
Starter for JMS messaging using Apache Artemis |
spring-boot-starter-batch
|
Starter for using Spring Batch |
spring-boot-starter-cache
|
Starter for using Spring Framework’s caching support |
spring-boot-starter-data-cassandra
|
Starter for using Cassandra distributed database and Spring Data Cassandra |
spring-boot-starter-data-cassandra-reactive
|
Starter for using Cassandra distributed database and Spring Data Cassandra Reactive |
spring-boot-starter-data-couchbase
|
Starter for using Couchbase document-oriented database and Spring Data Couchbase |
spring-boot-starter-data-couchbase-reactive
|
Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive |
spring-boot-starter-data-elasticsearch
|
Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch |
spring-boot-starter-data-jdbc
|
Starter for using Spring Data JDBC |
spring-boot-starter-data-jpa
|
Starter for using Spring Data JPA with Hibernate |
spring-boot-starter-data-ldap
|
Starter for using Spring Data LDAP |
spring-boot-starter-data-mongodb
|
Starter for using MongoDB document-oriented database and Spring Data MongoDB |
spring-boot-starter-data-mongodb-reactive
|
Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive |
spring-boot-starter-data-neo4j
|
Starter for using Neo4j graph database and Spring Data Neo4j |
spring-boot-starter-data-r2dbc
|
Starter for using Spring Data R2DBC |
spring-boot-starter-data-redis
|
Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client |
spring-boot-starter-data-redis-reactive
|
Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client |
spring-boot-starter-data-rest
|
Starter for exposing Spring Data repositories over REST using Spring Data REST |
spring-boot-starter-data-solr
|
Starter for using the Apache Solr search platform with Spring Data Solr |
spring-boot-starter-freemarker
|
Starter for building MVC web applications using FreeMarker views |
spring-boot-starter-groovy-templates
|
Starter for building MVC web applications using Groovy Templates views |
spring-boot-starter-hateoas
|
Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS |
spring-boot-starter-integration
|
Starter for using Spring Integration |
spring-boot-starter-jdbc
|
Starter for using JDBC with the HikariCP connection pool |
spring-boot-starter-jersey
|
Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web
|
spring-boot-starter-jooq
|
Starter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc
|
spring-boot-starter-json
|
Starter for reading and writing json |
spring-boot-starter-jta-atomikos
|
Starter for JTA transactions using Atomikos |
spring-boot-starter-jta-bitronix
|
Starter for JTA transactions using Bitronix. Deprecated since 2.3.0 |
spring-boot-starter-mail
|
Starter for using Java Mail and Spring Framework’s email sending support |
spring-boot-starter-mustache
|
Starter for building web applications using Mustache views |
spring-boot-starter-oauth2-client
|
Starter for using Spring Security’s OAuth2/OpenID Connect client features |
spring-boot-starter-oauth2-resource-server
|
Starter for using Spring Security’s OAuth2 resource server features |
spring-boot-starter-quartz
|
Starter for using the Quartz scheduler |
spring-boot-starter-rsocket
|
Starter for building RSocket clients and servers |
spring-boot-starter-security
|
Starter for using Spring Security |
spring-boot-starter-test
|
Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito |
spring-boot-starter-thymeleaf
|
Starter for building MVC web applications using Thymeleaf views |
spring-boot-starter-validation
|
Starter for using Java Bean Validation with Hibernate Validator |
spring-boot-starter-web
|
Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container |
spring-boot-starter-web-services
|
Starter for using Spring Web Services |
spring-boot-starter-webflux
|
Starter for building WebFlux applications using Spring Framework’s Reactive Web support |
spring-boot-starter-websocket
|
Starter for building WebSocket applications using Spring Framework’s WebSocket support |
后面会继续讲解这些起步器的使用。
8 热部署
在pom.xml中添加依赖
<!-- 热部署 --><!-- devtools可以实现页面热部署(即页面修改后会立即生效,这个可以直接在application.properties文件中配置spring.thymeleaf.cache=false来实现) --><!-- 实现类文件热部署(类文件修改后不会立即生效),实现对属性文件的热部署。 --><!-- 即devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),注意:因为其采用的虚拟机机制,该项重启是很快的 --><!-- (1)base classloader (Base类加载器):加载不改变的Class,例如:第三方提供的jar包。 --><!-- (2)restart classloader(Restart类加载器):加载正在开发的Class。 --><!-- 为什么重启很快,因为重启的时候只是加载了在开发的Class,没有重新加载第三方的jar包。 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><!-- optional=true, 依赖不会传递, 该项目依赖devtools;之后依赖boot项目的项目如果想要使用devtools, 需要重新引入 --><optional>true</optional></dependency>
在application.properties中添加配置信息
#热部署生效
spring.devtools.restart.enabled=true
#设置重启的目录,添加那个目录的文件需要restart
spring.devtools.restart.additional-paths=src/main/java
#如使用 thymeleaf 模板,记得在配置文件中关掉 thymeleaf 缓存
#spring.thymeleaf.cache=false
idea的设置
File->Settings->Build ,Exception,Deployment->Compiler-> 勾上Build Project automatically
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P7zA03Ua-1656551199502)(image/Springboot基础/image-20210723071801569.png)]
ctrl + shift + alt + / 然后选择Registry,勾上 Compiler.autoMake.allow.when.app.running
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HBblvEGn-1656551199503)(image/Springboot基础/image-20210723071815906.png)]
勾上 Compiler.autoMake.allow.when.app.running
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6T7xWhVu-1656551199503)(image/Springboot基础/image-20210723071936776.png)]
测试
每次修改完代码,要ctrl+s保存,然后热部署才会生效
9 返回json格式数据
springboot返回json格式数据
1 返回对象数据
增加POJO:
public class Student {private String name;private int age;
}
UserController
@RestController
public class UserController {@RequestMapping("/getStudent")public Student getStudent() {return new Student("张三5",44);}
}
在浏览器访问:http://127.0.0.1:8080/getStudent,即可以看到返回的json数据
2 返回数组数据
在TestController增加方法getStudents():
@RequestMapping("/getStudents")
public List<Student> getStudents() {List students=new ArrayList();students.add(new Student("张三",12));students.add(new Student("张三2",13));students.add(new Student("张三3",22));students.add(new Student("张三4",33));students.add(new Student("张三5",44));return students;
}
在浏览器访问:http://127.0.0.1:8080/getStudents,即可以看到返回的数组数据
3 返回HashMap数据
增加方法:
@RequestMapping("/getStudentMap")
public Map getStudentMap() {Map map = new HashMap();List students=new ArrayList();students.add(new Student("张三",12));students.add(new Student("张三2",13));students.add(new Student("张三3",22));students.add(new Student("张三4",33));students.add(new Student("张三5",44));map.put("retcode",1);map.put("students",students);return map;
}
10、springboot使用静态资源
在 Spring Boot 中,默认情况下,一共有5个位置可以放静态资源,五个路径分别是如下5个:
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
/:当前项目的根路径
优先级别是从上往下,即如果在以上5个目录出现相同的文件,会按照这个优先级别来显示。
在资源文件resources目录下建立如下四个目录:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VkAixILm-1656551199504)(image/Springboot/image-20210223144841813.png)]
我们项目的静态资源存放在 static下面。
第三章 集成数据库
1、springboot集成jdbcTemplate
1)增加依赖
在原有的springboot的基础上,增加下面的依赖:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version> <scope>runtime</scope>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.6</version>
</dependency>
<!-- jdbcTemplate -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
2)增加数据库配置
修改application.yml
其中如果是mysql8的版本,驱动和url要做相应的修改
spring:datasource:url: jdbc:mysql://localhost:3306/db_userusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource
mysql8的配置:
驱动:com.mysql.cj.jdbc.Driver
url : jdbc:mysql://localhost:3306/db_user?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
3)创建表和增加数据
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',`username` varchar(50) NOT NULL COMMENT '用户名',`age` int(11) NOT NULL COMMENT '年龄',`ctm` datetime NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;INSERT INTO `tb_user` VALUES ('1', '张三', '18', '2019-01-24 09:07:41');
INSERT INTO `tb_user` VALUES ('2', '李四', '20', '2019-01-24 09:07:41');
INSERT INTO `tb_user` VALUES ('3', '王五', '19', '2019-01-24 09:07:41');
4)增加实体类
public class User {private int id;private String username;private int age;private Date ctm;public User() {}public User(String username, int age) {this.username = username;this.age = age;this.ctm = new Date();}// Getter、Setter
}
5)增加dao接口
public interface UserDao {User getUserById(Integer id);public List<User> getUserList();public int add(User user);public int update(Integer id, User user);public int delete(Integer id);
}
5)增加dao实现类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import java.util.Date;
import java.util.List;@Repository
public class UserDaoImpl implements UserDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic User getUserById(Integer id) {List<User> list = jdbcTemplate.query("select * from tb_user where id = ?", new Object[]{id}, new BeanPropertyRowMapper(User.class));if(list!=null && list.size()>0){return list.get(0);}else{return null;}}@Overridepublic List<User> getUserList() {List<User> list = jdbcTemplate.query("select * from tb_user", new Object[]{}, new BeanPropertyRowMapper(User.class));if(list!=null && list.size()>0){return list;}else{return null;}}@Overridepublic int add(User user) {return jdbcTemplate.update("insert into tb_user(username, age, ctm) values(?, ?, ?)",user.getUsername(),user.getAge(), new Date());}@Overridepublic int update(Integer id, User user) {return jdbcTemplate.update("UPDATE tb_user SET username = ? , age = ? WHERE id=?",user.getUsername(),user.getAge(), id);}@Overridepublic int delete(Integer id) {return jdbcTemplate.update("DELETE from tb_user where id = ? ",id);}}
7)测试
a、修改controller,增加getUserById()方法和成员变量userDao
public class UserController {@AutowiredUserDao userDao;//由springboot自动注入dao对象给contrroller//测试访问数据获取对象@RequestMapping("/getUserById")public User getUserById(int id){return userDao.getUserById(id);}
b、访问url获取用户信息
http://127.0.0.1:8080/user/getUserById?id=3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Neh9O6ms-1656551199506)(…/…/…/…/work/03-课件/MD版本/04-核心框架课件/09-springboot v2/image/springboot/image-20210225180238184.png)]
8)解决pojo属性和数据库字段名不一致问题
方法1:使用别名
public Project getProjectById2(Integer id) {String sql = "select id,name,engineer,start_time startDate,cost_months costMonths," +"project_desc projectDesc, complete_rate completeRate,working_rate workingRate," +"waiting_rate waitingRate " +"from tb_project where id=?";System.out.println(sql);List<Project> list = jdbcTemplate.query(sql,new Object[]{id},new BeanPropertyRowMapper(Project.class));if(list != null && list.size()>0)return list.get(0);elsereturn null;}
方法2:自定义mapper
public Project getProjectById(Integer id) {String sql = "select * from tb_project where id=?";System.out.println(sql);List<Project> list = jdbcTemplate.query(sql,new Object[]{id}, new ProjectRomapper());if(list != null && list.size()>0)return list.get(0);elsereturn null;}
ProjectRomapper 代码
public class ProjectRomapper implements RowMapper<Project> {@Overridepublic Project mapRow(ResultSet resultSet, int i) throws SQLException {Project project = new Project();project.setId(resultSet.getInt("id"));project.setName(resultSet.getString("name"));project.setEngineer(resultSet.getString("engineer"));project.setStartDate(resultSet.getDate("start_time"));project.setCostMonths(resultSet.getInt("cost_months"));project.setCompleteRate(resultSet.getDouble("complete_rate"));project.setWaitingRate(resultSet.getDouble("working_rate"));project.setWorkingRate(resultSet.getDouble("waiting_rate"));return project;}
}
2 集成Mybatis
1 依赖
pom.xml
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--spring-mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.37</version></dependency><!--druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.16</version></dependency><!-- jpa依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
2 配置文件
在resources目录下建立mybatis-config.xml
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--需要内容自己添加,可以什么都不写--><settings><!--开启驼峰命名匹配规则--><setting name="mapUnderscoreToCamelCase" value="true"/></settings></configuration>
application.properties
server.port=8080
server.servlet.context-path=/
#
#数据源
spring.datasource.url=jdbc:mysql://localhost:3306/travel?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.jdbc.Driver
#
#mybatis
mybatis.config-location=classpath:mybatis-config.xml
mybatis.checkConfigLocation=true
# mybatis 别名扫描
mybatis.type-aliases-package=edu.ln.travel.pojo
# mapper.xml文件全部放在resources/mappers目录中
mybatis.mapper-locations=classpath:mappers/*.xml
注意:如果是mysql8,
driver-class-name= com.mysql.cj.jdbc.Driver
url=
jdbc:mysql://localhost:3306/travel?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
3 model层
UserDao需要加入@Mapper注解
如果UserDao不加@Mapper注解 ,也可以在springboot的启动类上加上@MapperScan(“com.dao”)注解
@Mapper
public interface UserDao {public List<User> findAll();}
pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private Integer uid;private String name;private Integer telephone;
}
resources/mappers/UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" ><mapper namespace="edu.ln.travel.dao.UserDao"><select id="findAll" resultType="User">select * from tab_user</select></mapper>
4、测试集成mybatis
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybatisApplication.class)
class MybatisApplicationTest {@AutowiredUserDao userDao;@Testpublic void test1(){List<User> users = userDao.findAll();System.out.println(users);}@Testpublic void test2(){User user = userDao.findById(4);System.out.println(user);}
}
3、集成通用mapper
1)引入依赖
通用Mapper的作者也为自己的插件编写了启动器,我们直接引入即可:
<!-- 通用mapper -->
<dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>4.2.1</version>
</dependency>
不需要做任何配置就可以使用了。
@Mapper
public interface UserMapper extends tk.mybatis.mapper.common.Mapper<User>{
}
2)修改pojo增加jpa的设置
pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name="tab_user")
public class User {@Idprivate Integer uid;private String name;private Integer telephone;
}
3)测试集成通用mapper
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybatisApplication.class)
class MybatisApplicationTest {@AutowiredUserDao userDao;@AutowiredUserMapper userMapper;@Testpublic void test1(){List<User> users = userDao.findAll();System.out.println(users);}@Testpublic void test2(){User user = userDao.findById(4);System.out.println(user);}///============user mapper的测试@Testpublic void testMapper1(){User user = new User(null,"杰伦-布朗",28);int ret = userMapper.insert(user);System.out.println("usrmapper 插入用户: " + ret);}
}
3、集成PageHelper
1 增加依赖
注意,springboot2.6.0和springboot2.6.1以上只能使用pagehelper-spring-boot-starter1.4.1及以上版本,如果用低版本的pagehelper-spring-boot-starter,springboot需要降版本。
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.3</version></dependency>
2、application配置文件中配置
pagehelper分页插件配置,这些属性不加也可以实现分页功能
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
3、PageHelper的使用
在userService增加分页功能。
@Override
public Page<User> listByPage(int pageNo, int pageSize) {PageHelper.startPage(pageNo, pageSize);Page<User> pageUsers =(Page<User> ) userDao.findAll();System.out.println("总条数:"+pageUsers.getTotal());return pageUsers;
}
第四章 使用springboot
1 模板引擎
1)介绍
常见的模板引擎有JSP、Velocity、Freemarker、Thymeleaf, 使用springboot整合jsp并不是很好,因为springboot默认没有对jsp有很大的支持,SpringBoot推荐使用Thymeleaf
2)Thymeleaf的特点
- 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
- 开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
- 多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
- 与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。
3)Thymeleaf的使用
首先引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
框架自动给我们默认分配了模版的前缀和后缀,我们只需要按部就班的将模版丢进去即可
具体见:ThymeLeafProperties类默认ed配置。
修改配置文件
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
Thymeleaf语法规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wjjN4B7D-1656551199507)(image/2.png)]
案例1:基本使用
在resources/templates目录下创建index.html文件,只要我们把HTML页面放在classpath:/templates/下,thymeleaf就能自动渲染;
IndexController
@Controller
@RequestMapping("index")
public class IndexController {@RequestMapping("index")public String hello(Model model) {//跳转到index.html页面model.addAttribute("hello","你好");return "index";}
}
index.html
<!DOCTYPE html>
<!-- 导入thymeleaf的名称空间 -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1> SpringBoot集成Thymeleaf成功!</h1><!--th:text 将div里面的文本内容设置为 --><div th:text="${hello}">这是显示欢迎信息</div>
</body>
</html>
说明:
导入thymeleaf的名称空间,不导入则无法渲染
<html lang="en" xmlns:th="http://www.thymeleaf.org">
案例2:循环
html代码:
<tr th:each="user : ${users}"><td th:text="${user.name}">Onions</td><td th:text="${user.age}">2.41</td>
</tr>
${users} 是要遍历的集合,可以是以下类型:
- Iterable,实现了Iterable接口的类
- Enumeration,枚举
- Interator,迭代器
- Map,遍历得到的是Map.Entry
- Array,数组及其它一切符合数组结果的对象
在迭代的同时,我们也可以获取迭代的状态对象:
<tr th:each="user,stat : ${users}"><td th:text="${user.name}">Onions</td><td th:text="${user.age}">2.41</td>
</tr>
stat对象包含以下属性:
- index,从0开始的角标
- count,元素的个数,从1开始
- size,总元素个数
- current,当前遍历到的元素
- even/odd,返回是否为奇偶,boolean值
- first/last,返回是否为第一或最后,boolean值
案例3:逻辑判断
逻辑判断Thymeleaf中使用th:if
或者 th:unless
,两者的意思恰好相反。
<span th:if="${user.age} > 24">老油条</span>
如果表达式的值为true,则标签会渲染到页面,否则不进行渲染。
以下情况被认定为true:
- 表达式值为true
- 表达式值为非0数值
- 表达式值为非0字符
- 表达式值为字符串,但不是
"false"
,"no"
,"off"
- 表达式不是布尔、字符串、数字、字符中的任何一种
其它情况包括null都被认定为false。
案例4:JS模板
模板引擎不仅可以渲染html,也可以对JS中的进行预处理。而且为了在纯静态环境下可以运行,其Thymeleaf代码可以被注释起来:
<script th:inline="javascript">const user = /*[[${user}]]*/ {};const age = /*[[${user.age}]]*/ 20;console.log(user);console.log(age)
</script>
在script标签中通过th:inline="javascript"
来声明这是要特殊处理的js脚本
语法结构:
const user = /*[[Thymeleaf表达式]]*/ "静态环境下的默认值";
因为Thymeleaf被注释起来,因此即便是静态环境下, js代码也不会报错,而是采用表达式后面跟着的默认值。且User对象会被直接处理为json格式。
2 全局异常捕获
如果每个方法都可能会发生异常,每个方法都加上try不好,因此使用全局捕获异常处理
全局捕获异常: 整个web请求项目全局捕获异常。
/*** @auth admin* @date* @Description 全局异常捕获类*/
@ControllerAdvice
public class GlobalException {private static final Logger log = LoggerFactory.getLogger(GlobalException.class);@ResponseBody@ExceptionHandler(NullPointerException.class)public Map<String, Object> nullPointerException() {//实际开发中,会将错误记录在日志中,每天检测有哪些错误报告,通过邮件发送给你Map<String, Object> errorResultMap = new HashMap<String, Object>();errorResultMap.put("code", "500");errorResultMap.put("msg", "全局捕获异常-NullPointerException");return errorResultMap;}@ResponseBody@ExceptionHandler(RuntimeException.class)public Map<String, Object> runtimeException() {Map<String, Object> errorResultMap = new HashMap<String, Object>();errorResultMap.put("code", "500");errorResultMap.put("msg", "全局捕获异常-runtimeException");return errorResultMap;}@ResponseBody@ExceptionHandler(Exception.class)public Map<String, Object> exception() {Map<String, Object> errorResultMap = new HashMap<String, Object>();errorResultMap.put("code", "500");errorResultMap.put("msg", "全局捕获异常-exception");return errorResultMap;}}
测试:
在任何一个类中手动写一个异常,例如 int a=1/0,发现会被全局异常类捕获到。
说明:
1 发生异常会首先被子类捕获,如果子类捕获不到,由父类捕获,直至根类Exception捕获
2 可以自定义异常类
3 AOP统一处理日志
pom依赖
<!-- springboot aop技术 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
aop类
package com.aop;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** @auth admin* @date* @Description aop类*/
@Aspect
@Component
public class WebLogAspect {private static final Logger log = LoggerFactory.getLogger(WebLogAspect.class);@Pointcut("execution(* com.controller.*.*(..))")public void webLog() {}@Before("webLog()")public void doBefore(JoinPoint joinPoint) throws Throwable {//接收到请求,记录请求内容,可以保存到nosql中ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//记录下请求内容log.info("URL:" + request.getRequestURL().toString());log.info("HTTP_METHOD:" + request.getMethod());log.info("IP:" + request.getRemoteAddr());Enumeration<String> enu = request.getParameterNames();while (enu.hasMoreElements()) {String name = (String) enu.nextElement();log.info("name:{},value:{}", name, request.getParameter(name));}}@AfterReturning(returning = "ret", pointcut = "webLog()")public void doAfterReturning(Object ret) throws Throwable {//处理完请求,返回内容log.info("返回内容 :" + ret);}}
4 集成Swagger3
Swagger是一个可以根据你的代码,自动生成接口文档的一个工具,并且可以用作接口测试工具,Swagger 3.0版本是在Swagger2的基础上进行了部分升级, 使用和Swagger2没有多少区别
一个重要的优化是依赖的引入,由之前的多个依赖变更为一个依赖,跟随springboot-starter风格,同时引入了新的开关注解 @EnableOpenApi 以代替@EnableSwagger2 。
必要工作只有两个:添加swagger3的starter依赖包,在springboot主程序类添加@EnableOpenApi开关注解。
第1步:增加依赖,修改pom.xml
<!-- swagger -->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version>
</dependency>
第2步:添加开关注解@EnableOpenApi
@SpringBootApplication@EnableOpenApi //启动swagger3
public class DTourApp {public static void main(String[] args) {SpringApplication.run(DemoSwagger3Application.class, args);}}
第3步:添加Swagger配置类(可选步骤)
自定义首页属性 Docket配置
package edu.ln.tour.config;
@Configuration
public class Swagger3 {@Beanpublic Docket docket() {return new Docket(DocumentationType.OAS_30).apiInfo(new ApiInfoBuilder().contact(new Contact("黄豆", "", "88779900@qq.com")).title("岭南旅游网").build());}
}
第4步:配置路径匹配策略,解决空指针问题
springboot2.6.x版本以上配置swagger3.0会提示[空指针异常]
错误如下
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
原因: 这是因为Springfox使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher。
解决:在application.properties里配置:spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
则需要在applocation.properties增加如下配置:
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
第5步
为了增加文档的可读性,我们还需要在接口中增加一些说明
UserController可以添加@Api和 @ApiOperation注解
@Api(description = "用户管理api")
@Controller
public class UserController {Logger logger = LoggerFactory.getLogger(getClass());@Resourceprivate UserService userService;@ApiOperation("查询所有用户信息")@GetMapping("getAll")@ResponseBodypublic List<User> getAll() {return userService.findAll();}@ApiOperation("添加用户")@GetMapping("save")@ResponseBodypublic void save(User user) {}}
@ApiModel("用户实体类")
public class User {@ApiModelProperty("id")private Long id;@ApiModelProperty(value = "用户姓名", required = true)private String name;@ApiModelProperty("用户年龄")private Integer age;
第6步:测试
启动springboot
swagger-ui访问地址:http://127.0.0.1:8080/swagger-ui/index.html
常用注解如下:
注解 | 使用的地方 | 用途 |
---|---|---|
@Api | 类/接口 | 描述类/接口主要用途 |
@ApiOperation | 方法 | 描述方法的用途 |
@ApiImplicitParam | 方法 | 用于描述接口的非对象参数 |
@ApiImplicitParams | 方法 | 用于描述接口的非对象参数集 |
@ApiIgnore | 类/方法/参数 | Swagger 文档不会显示拥有该注解的接口 |
@ApiModel | 参数实体类 | 可设置接口相关实体的描述 |
@ApiModelProperty | 参数实体类属性 | 可设置实体属性的相关描述 |
第五章 日志
1 日志框架
在项目的开发中,日志是必不可少的一个记录事件的组件,所以也会相应的在项目中实现和构建日志框架。
市面上的日志框架:
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…
通常情况下,日志是由一个抽象层+实现层的组合来搭建的。
日志门面 (日志的抽象层) | 日志实现 |
---|---|
JCL(Jakarta Commons Logging) 、SLF4j(Simple Logging Facade for Java) 、jboss-logging | Log4j、JUL(java.util.logging) 、Log4j2 、 Logback |
而SpringBoot选择了SLF4J+Logback的组合,这个组合是当下比较合适的一组。
2 SLF4j使用
application.properties加入日志配置信息
#
#日志的级别:由低到高trace<debug<info<warn<error
#SpringBoot默认是设置info级别
logging.level.edu.ln.tour=trace #包的日志级别
#logging.level.root=trace #root日志级别
日志的级别:优先级依次升高
测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TourApp.class)
public class TestLogger {
//记录器Logger logger = LoggerFactory.getLogger(getClass());@Testpublic void contextLoads() {//日志的级别;//由低到高 trace<debug<info<warn<error//可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效logger.trace("这是trace日志...");logger.debug("这是debug日志...");//SpringBoot默认使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别logger.info("这是info日志...");logger.warn("这是warn日志...");logger.error("这是error日志...");}
}
这些日志信息默认都会在控制台进行输出打印。
通过修改logging.level.com.xxx=日志级别,可以看到打印的信息也不同。
3 配置日志生成路径和名称
在项目的运行中,我们不可能一直看着控制台,而且日志数量会很大,那么我们需要指定我们需要的日志名称以及
日志生成的路径,用到两个配置都是在application.properties/yml中写,如下:(都不设置的话,不生成日志)
#
#日志的级别:由低到高trace<debug<info<warn<error
#SpringBoot默认是设置info级别
logging.level.edu.ln.tour=info
#
#在当前磁盘的根路径下创建spring文件夹和里面的log文件夹,并使用spring.log作为默认文件
logging.file.path=/spring/log
#
#在当前项目的根目录中生成a.log文件(生成完刷新一下项目)
#logging.file.name=a.log
#注意:logging.file.path和logging.file.name如果同时配置,则只有logging.file.name有效
#
# 设置控制台输出的日志的格式
#logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 设置指定文件中日志输出的格式
#logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
logging.file.name | logging.file.path | Example | Description |
---|---|---|---|
(none) | (none) | 只在控制台输出 | |
指定文件名 | (none) | my.log | 输出日志到当前项目的根目录中my.log文件 |
(none) | 指定目录 | /var/log | 输出到当前磁盘/var/log的spring.log 文件中 |
指定文件名 | 指定目录 | my.log | 输出日志到当前项目的根目录中my.log文件 |
4 在service中使用logger
在service使用logger如下。然后观察spring.log的输出。
@Service
public class UserServiceImpl implements UserService {Logger logger = LoggerFactory.getLogger(getClass());@AutowiredUserDao userDao;@Overridepublic Page<User> listByPage(int pageNo, int pageSize) {logger.debug("分页:"+pageNo+"---"+pageSize);PageHelper.startPage(pageNo, pageSize);Page<User> pageUsers =(Page<User> ) userDao.findAll();System.out.println("总条数:"+pageUsers.getTotal());return pageUsers;}
}
spring.log的输出:
...
e.ln.tour.service.impl.UserServiceImpl : 分页:2---3
....
第六章、springboot文件上传
1、文件上传
增加依赖
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.3</version></dependency>
html代码
<form>单选:<input type="file" id="uploadFile" name="uploadFile"><br><button type="button" id="btn1">保存单选</button><br>
</form>
js代码
$(function(){$('#btn1').click(function(){var files = $('#uploadFile').prop('files');var data = new FormData();//注意uploadFile和controller中的参数名要一致data.append('uploadFile', files[0]);data.append('username',"zhangsan");$.ajax({url: '/fileupload',type: 'POST',data: data,cache: false,processData: false,contentType: false,success: function(msg){console.log( "Data Saved: " + msg );}});});
})
Controller代码
@RequestMapping(value="/fileupload")@ResponseBodypublic void save22(String username, MultipartFile uploadFile) throws IOException {System.out.println(username);System.out.println(uploadFile);String originalFilename = uploadFile.getOriginalFilename();uploadFile.transferTo(new File("C:\\upload\\"+originalFilename));}
2、多个文件上传
html
<form id="uploadForm" action="Upload" method="post" enctype="multipart/form-data"><input id="File1" name="uploadFile" accept="image/gif, image/jpeg" multiple="multiple" type="file" value="" /><input type="text" name="username" id="username" value="zhansan"><input id="btn" type="button" value="上传" />
</form>
js
$(function(){$('#btn').click(function(){var formData = new FormData($("#uploadForm")[0]);$.ajax({url: '/fileuploadMul',type: 'POST',data: formData,cache: false,processData: false,contentType: false,success: function(msg){console.log( "Data Saved: " + msg );}});});
})
controller
@RequestMapping(value="/fileuploadMul")
@ResponseBody
public void save23(String username, MultipartFile[] uploadFile) throws IOException {System.out.println(username);for (MultipartFile multipartFile : uploadFile) {String originalFilename = multipartFile.getOriginalFilename();multipartFile.transferTo(new File("C:\\upload\\"+originalFilename));}
}
3、文件下载
通过封装ResponseEntity,将文件流写入body中。这里注意一点,就是文件的格式需要根据具体文件的类型来设置,一般默认为application/octet-stream。文件头中设置缓存,以及文件的名字。
@RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> downloadFile( String fileName) throws IOException { String filePath = "E:/test/"+fileName; FileSystemResource file = new FileSystemResource(filePath); HttpHeaders headers = new HttpHeaders(); headers.add("Cache-Control", "no-cache, no-store, must-revalidate"); headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getFilename())); headers.add("Pragma", "no-cache"); headers.add("Expires", "0"); return ResponseEntity .ok() .headers(headers) .contentLength(file.contentLength()) .contentType(MediaType.parseMediaType("application/octet-stream")) .body(new InputStreamResource(file.getInputStream())); }
spring boot微服务项目搭建相关推荐
- 高级版的 jvisualvm :Spring Boot Admin 监控 Spring Boot 微服务项目
前奏:先说一下 Java VisualVM Java VisualVM 是一个能够监控 JVM 的 jdk 自带的图形化工具: 在 $JAVA_HOME/bin 目录下,可直接运行它. 要想监控远程服 ...
- Spring/Spring Boot微服务项目 集成Druid 实现监控功能
为什么80%的码农都做不了架构师?>>> 步骤如下: 1.首先新建2个model(LogInfo,MonitorInfo) public class LogInfo imple ...
- Spring Boot微服务项目启动错误: 找不到或无法加载主类解决方案
这个问题其实不考察技术含量,只是看思路和细心程度.简单记录下,希望能帮助一个是一个. 解决方法一:maven clean install方式 可以找到具体服务模块的maven工具如下操作,或者直接执行 ...
- Spring Cloud Hoxton 版本微服务项目搭建 admin 监控客户端
Spring Cloud Hoxton 版本微服务项目搭建 admin 监控客户端 前言 在上一篇文章博主已经讲解了admin 管理中心服务项目如何创建,不会的话可以前往学习,传送门:Spring C ...
- Docker容器及Spring Boot微服务应用
2019独角兽企业重金招聘Python工程师标准>>> Docker容器及Spring Boot微服务应用 1 什么是Docker 1.1 Docker的出现 问题一:项目实施环境复 ...
- Spring Cloud 微服务项目实战 -
文章目录 微服务"三大功能,两大特性" Spring Boot & Spring Cloud Spring Cloud 组件库一览 Spring Cloud 版本 毕业版本 ...
- Docker基础篇 - (六)Docker 网络Spring Boot微服务打包Docker镜像
⑦ Docker 网络 7.1 理解Docker0 清空下前面的docker 镜像.容器 # 删除全部容器 [root@cVzhanshi tomcat-diy]# docker rm -f $(do ...
- spring boot 微服务集群 + 注册中心
spring boot 微服务框架下载地址: https://start.spring.io/ 注册中心 Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进 ...
- Spring Boot微服务的黑匣子测试是如此简单
当我需要进行原型设计,概念验证或在空闲时间使用一些新技术时,开始新项目对于Maven来说总是有点烦人. 不得不说,设置Maven项目并不难,您可以使用Maven原型. 但是原型通常是过时的. 谁想玩旧 ...
最新文章
- R语言使用yardstick包的conf_mat函数计算多分类(Multiclass)模型的混淆矩阵、并使用summary函数基于混淆矩阵输出分类模型评估的其它详细指标(kappa、npv等13个)
- 搬运机器人举杯贺所需的条件_机器人调试工程师的工作是怎样的
- NYOJ 598 旋转圆柱矩阵
- 3000字详解Pandas数据查询,建议收藏
- (day 52 - 递归 and 短路逻辑运算符的用法 ) 剑指 Offer 64. 求1+2+…+n
- gns3虚拟机服务器集群,GNS3中如何实现与Vmware Workstation连接
- PHP与JS互相加密解密方法2.0
- python工资条教程_批量发工资怎么操作_利用python轻松解决用邮箱批量发工资条...
- java链式编程/级联式编程
- 数学的意义与数学教育的价值
- 大数据平台以及一些核心组件介绍
- 三线一单”大气环境质量底线体系与划分技术方法
- 企业为什么要开通微信公众号?
- C++ Primer 读书笔记及知识点延伸 chapter2
- 站长付个人微信支付宝收款系统如何对接?
- 【杂谈】win10耳机与外放分别设置
- 《Android群英传》读书笔记
- Thumbnail 图片压缩
- CSDN博客新手使用方案
- 供应链计划的五个步骤,你知道吗?
热门文章
- 罗永浩 AR 创业公司估值 10 亿;​苹果宣布加大 AppStore 广告推送量;​Node.js 19 发布|极客头条...
- 转载:Android (争取做到)最全的底部导航栏实现方法
- 牵手中关村,这里脱胎换骨引凤来
- SAP 详细分析BOM物料清单
- 【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
- 学生党必备好物神器:科大讯飞智能录音笔
- 好用不贵的职场礼物——讯飞智能录音笔SR302
- ROG魔霸7Plus的CPU温度与 Armoury Crate 设置问题
- 活动通知html代码大全,促销活动通知范文
- 微信小程序图片裁剪工具we-cropper