文章目录
Java
人人开源代码生成器:https://gitee.com/renrenio/renren-generator.git
所有idea快捷键: 博客csdn @ 绿茵场上的程序猿
spring平台各组件版本对应:https://spring.p2hp.com/projects/spring-cloud.html
aliyun的mvn仓库:https://developer.aliyun.com/mvn/search
spring security用法:Spring Security使用详解(基本用法 ) - 邓维-java - 博客园
spring security视频:https://www.bilibili.com/video/BV1kj41167rK?t=518.7&p=4
java开发框架需要实现这些功能:面向对象和自动GC(java语言特性)、面向切面、控制反转(ioc和di)、包管理工具、orm、mvc、web、事务、微服务。
spring的主要模块:spring本身的基础特性、springboot自动配置、springmvc。
# 面向对象和自动GC
java语言特性实现
# 面向切面
spring框架实现。
# 控制反转(ioc和di)
spring框架实现。
# 包管理工具
maven
# orm
mybatisplus实体映射模型
# mvc
# web
spring web框架,还提供restful api组件、rpc组件,ribbon工具可以提供基于负载均衡算法的rest调用,cloud提供openfeign远程调用
# 事务。
spring框架的transaction组件
java语法
基本数据类型:https://www.php.cn/faq/500617.html
命名规范、基本数据类型、常用数据结构封装类、代码语法(类定义变量定义函数定义控制结构语法注解语法异常语法并发语法)、常用基础库(os、文件、path、http、并发、异常)、面向对象支持、aop支持、ioc和di支持、jdk版本。
# 命名规范
包名。全部小写不要下划线。
类名。驼峰命名法不要下划线首字母大写,抽象类以Abstract或者Base为前缀,接口实现类以Impl为后缀,异常类以Exception为后缀,测试类以Test为后缀。
方法变量。驼峰命名法不用下划线首字母小写,有返回值加get前缀,设置方法加动词前缀修饰如set、insert、update、delete,查询方法加select、find、query前缀,带有条件的方法用By或者With连接,判断方法加is前缀,测试方法加test前缀。
常量。全部大写用下划线分割。
枚举类。类名遵循类名命名,值遵循常量命名法。
泛型。E表示元素element通常用在集合中,T表示类型type通常指类,K/V表示键值对key/value通常成对用于Map中,N表示数值类型Number,?表示不确定的java类型,X表示异常,U/S表示任意类型。
# 基本数据类型
java中有7种基本数据类型byte,short,int,long,float,double,boolean,char
byte。8位,-128~127。
short。16位,-32768~32767。
int。32位,-2.1e9~2.1e9。
long。64位,-9.2e18~9.2e18。
float。32位,3.4e-45~1.4e38,直接赋值必须加f/F。
double。64位,4.9e-324~1.8e308,直接赋值可加可不加d/D,因为小数常量默认类型是double。
boolean。1位,true/false。
char。16位存储unicode码,用单引号赋值。
基本类型的位数和取值范围可以使用包装类.SIZE/.MIN_VALUE/.MAX_VALUE获取,其中float和double的.MIN_VALUE不是最小的负数而是最小的正小数,即0+-Float.MIN_VALUE之间的数float无法表示因为超出了float的精度范围。
# 常用数据结构封装类
list, map, set, linklist, hashmap, hashset,
# 代码语法
类定义。
变量定义。
函数定义。
控制结构语法。
注解语法。
异常语法。
并发语法。
# 常用基础库
os。
文件。
path。
http。
并发。
异常。
# 面向对象支持
# aop支持
# ioc和di支持
# jdk版本
jdk5.0(1.5)开始实现了自动装包和拆包
springboot经验
springboot的使用:http://t.csdnimg.cn/gLKw4
springboot面试题:https://www.bilibili.com/video/BV1Fh4y1D7Aq?t=7.9&p=4
概念。springboot是spring的一个模块,旨在简化spring应用程序的创建和部署,提供了一些额外特性来简化配置和开发过程。
使用方法。举一个例子,比如说在项目中使用了MySQL数据库,那么就引入MySQL依赖包,然后在application配置文件中配置数据源信息,springboot会根据项目依赖中的MySQL依赖自动读取配置文件中的数据源信息,然后将配置信息应用到对应的数据容器中,springboot内嵌了web服务器,因此springboot打包之后可以直接通过jar -jar命令运行。springboot的使用方式就引入springboot依赖,然后在启动类中设置@sprongbootapplication注解,在配置yaml文件中配置数据连接字符串,使用spring的依赖注入功能,在业务类和控制器中使用@service和@restcontroller可以完成自动注入,引入mybatis依赖,使用@mappingscan注解映射mapper的位置,之后完成相关的业务代码和控制器就可以启动应用了。
问题1-在项目中是怎么使用springboot的?
首先是引入一个spring-boot-starter依赖作为父依赖,然后根据项目场景引入springweb或者springmvc之类的依赖和mysql、mybatis等依赖,在properties配置文件中配置数据源和端口等信息,为启动类添加@springbootApplication注解,之后编写业务代码就可以启动应用了。
问题1-springboot的启动原理。
7步。
运行main方法。
运行run方法。在run方法中会读取配置信息、创建上下文、初始化上下文、加载ioc容器。在这个过程中调用很多监听器用于扩展。
问题2-springboot自动配置的原理,讲一下常用的注解和类?
6步。
通过@SpringBootApplication引入@SpringBootConfiguration和@EnableAutoConfiguration
通过@EnableAutoConfiguration引入@Import
通过@Import导入DeferredImportSelector组件
DeferredImportSelector会读取所有/META-INF/spring.factories文件
过滤出所有AutoConfigurationClass的类
通过@ConditionOnXXX排除无效的自动配置类。
事务
spring transaction。事务的使用就是使用@transactional注解。
# 实现方式
4种。编程式,transactionProxyFactoryBean的声明式事务,AspectJ的XML声明式事务,基于注解的声明式事务。
# 功能
一系列动作要么全完成,要么全不完成。
https://blog.csdn.net/2301_78145678/article/details/130753716
mysql经验
问题1-mysql的索引
ssm经验
目标:使用ssm开发一个后台管理系统。
涉及的技术:ssm、thymeleaf、mysql
主要内容:
ssm是指使用spring、springmvc、mybatis开发的项目。
1)spring是一个开源的应用程序框架,提供了一种全面的编程和配置模型,spring的核心特性包括依赖注入、面向切面、控制反转等。spring支持各种开发层次,包括web应用开发、数据访问、消息传递等,它提供了一系列的模块,如spring mvc、spring data、spring security等。spring框架提供了一个容器ApplicationContext,用于管理和组织应用程序中的对象,主要有5个方面的作用:bean的管理、依赖注入、AOP支持、国际化支持、事件机制。
2)springmvc是spring框架中的一个模块,用于构建web应用程序。springmvc提供了一种分离关注点的方式,使得开发人员可以专注于业务逻辑/模型、用户界面/视图、处理用户请求/控制器 3个部分。
面向切面
spring框架实现。
控制反转(ioc和di)
spring框架实现。
orm框架
# mybatisplus
mybatisplus是操作mysql的orm框架,使用jdbc作为mysql数据库驱动,支持mysql sqlserver oracle sqlite mariadb db2 h2 hsql postgresql
达梦数据库 虚谷数据库 人大金仓数据库等这些数据库软件。
# RedisTemplate
访问redis的组件,jdk11可以使用redisom官方组件,jdk8使用redistemplate。
# rabbitmq
session消息中间件,其他消息中间件还有kafka
pojo
pojo类英文全称是plain ordinary java object,中文叫做普通java对象,pojo包括实体类entity、视图对象vo、业务传输对象dto等一众java对象。
高并发
高并发商城项目需要使用spring提供基本的ioc和aop功能,需要使用springboot提供默认配置,简化开发,需要使用springcloud提供网关和负载均衡,需要使用elastic search提供对商品的全文检索,需要使用redis对商品信息进行缓存,对用户session进行缓存,需要使用rabbitmq进行流量消峰。
基础服务需要使用mysql进行数据存储。
明天讲一下MySQL的分库分表。
高并发主要是使用3个工具:缓存、异步、队列。
缓存就是使用redis作为缓存数据库,掌握redis数据库的使用。异步就是使用消息中间件进行异步解耦,进行流量的缓存。队列就是让高并发的请求排队逐一处理。主要工具:redis、kafka和rabbitmq。
java小厂技术
ssm+mysql已经可以解决大部分小厂的问题了,就我实习过的一家帮助医院录入老年人就诊信息的小公司,就是使用ssm+mysql做一个简单的信息管理系统,只要学过软件的人基本都能做。下面说一下需要学习的技术。
面试提问:spring提供基本的ioc和aop功能,说一下实现原理。
springcloud
# springcloud
提供微服务和云原生功能组件.
# springcloud gateway
网关
# nacos
注册发现配置中心
常用命令
# 运行
java -jar ./target/spring-petclinic-3.1.0-SNAPSHOT.jar
版本管理github经常连不上使用码云配置.gitignore排除不进行版本控制的文件。
**/mvnw
**/mvnw.cmd
**/.mvn
**/target/
.idea
**/.gitignore
组件版本
版本适配:jdk1.8, springboot-2.2.6.RELEASE, springcloud-Hoxton.SR1, springcloudalibaba-2.2.6.RELEASE, mybatis-plus-3.3.0, mysqlconnectorjava-8.0.33, Spring Cloud Gateway-2.2.1.RELEASE, nacos2.2.6
组件 | 依赖 | 版本 |
---|---|---|
JDK | 1.8 | |
Spring | 包含于spring-boot-starter-parent | |
SpringBoot | spring-boot-starter-parent | 1.5.10.RELEASE |
SpringWeb | spring-boot-starter-web | 依赖于spring-boot-starter-parent |
SpringMVC | 包含于spring-boot-starter-web | |
Mybatis | mybatis-spring | 2.0.6 |
Mybatis-Plus | mybatis-plus-boot-starter | 3.0-RELEASE |
Lombok | 1.16.20 | |
Thymeleaf | spring-boot-starter-thymeleaf | 依赖于spring-boot-starter-parent |
快捷键
# 快捷键
自动缩进行:ctrl+alt+l
跳转到implementation类:ctrl+alt+B
跳转到方法实现处:ctrl+B
根据类名查找类:ctrl+N
查看接口的所有实现类:ctrl+H
重命名:shift+f6
# 服务启动参数设置
设置服务启动端口:Program arguments :--server.port=9011
代码生成器
代码生成器有人人开源和MybatisPlus-generator,人人开源的用法是通过git下载源码修改application.yml更新MySQL账号和密码数据库名称修改generator.properties更新包名表前缀修改模板运行RenrenApplication.java启动项目访问http://localhost即可。
generator.properties
mainPath=com.zhou
#包名
package=com.zhou
moduleName=seckill
#作者
author=zhoujk
#Email
email=zhoujkmail@163.com
#表前缀
tablePrefix=
controller
// 删除 @RequiresPermissions一共有4个
import org.springframework.beans.factory.annotation.Autowired;
@RequiresPermissions("${moduleName}:${pathName}:list")
// 修改
import ${package}.${moduleName}.utils.PageUtils;
import ${package}.${moduleName}.utils.R;
@RequestMapping("${pathName}")
service
// 修改
import ${package}.${moduleName}.utils.PageUtils;
// 注释掉
// PageUtils queryPage(Map<String, Object> params);
impl
// 修改
import ${package}.${moduleName}.utils.PageUtils;
import ${package}.${moduleName}.utils.Query;
// 注释掉
/**
@Override
public PageUtils queryPage(Map<String, Object> params) {
IPage<${className}Entity> page = this.page(
new Query<${className}Entity>().getPage(params),
new QueryWrapper<${className}Entity>()
);
return new PageUtils(page);
}
*/
Mybatis-Plus
- 添加依赖
MyBatis-Plus依赖、MySQL驱动、httpcomponents依赖、servlet依赖
<!--业务需求-->
<!--集成spring-web-mvc-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.15</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>5.1.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--生成业务代码 MyBatisPlus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- 集成mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
<scope>compile</scope>
</dependency>
- 注册mapper
为XxxApplication.java
添加注解
@MapperScan(“com.zhou.seckill.dao”)
- 配置application.yml
## 数据源、映射文件位置
spring:
datasource:
username: root
password: zhoujkAAAAA
url: jdbc:mysql://192.168.137.2:3306/seckill
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
## 应用服务 WEB 访问端口
server:
port: 8082
thymeleaf
1)添加依赖
<!-- 整合thymeleaf,前端引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- thymeleaf热部署,修改html之后立即生效 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
## 关闭 thymeleaf 缓存,实现热部署
spring.thymeleaf.cache=false
2)编写html页面
所有html页面默认放在resources/template
下面,默认访问index.html
页面。
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Index Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="${message}">Welcome to BeiJing!</p>
</body>
</html>
3)编写Controller
// 只有@Controller的时候返回“login”才会生效,使用@RestController需要返回new ModelAndView("login")才会路由到页面。
@Controller
@RequestMapping("page")
public class PageController {
/**
* 进入登录页
*/
@RequestMapping("/login")
public String loginPage(){
return "login";
}
}
Cookie\Session
演示:登录模块
1)写接口
@RequestMapping("login")
public Result<User> doLogin(HttpServletResponse response, HttpSession session,
@Valid LoginParam loginParam){
Result<User> login = userService.login(loginParam);
return login;
}
2)生成 Cookie 和Session
生成Cookie ,写入到HttpServletResponse
中。
private final static String COOKIE_DOMAIN = "localhost";
private final static String COOKIE_NAME = "seckill_login_token";
/**
* token = httpSession.getId();
*/
public static void writeLoginToken(HttpServletResponse response, String token){
Cookie cookie = new Cookie(COOKIE_NAME,token);
cookie.setDomain(COOKIE_DOMAIN);
cookie.setPath("/");//代表设置在根目录
cookie.setHttpOnly(true);
//单位是秒。
//如果这个MaxAge不设置的话,cookie就不会写入硬盘,而是写在内存。只在当前页面有效。
cookie.setMaxAge(60 * 60 * 24 * 365);//如果是-1,代表永久
log.info("write cookieName:{},cookieValue:{}",cookie.getName(),cookie.getValue());
response.addCookie(cookie);
}
生成 Session ,保存到 Redis 中。
redisService.set(UserKey.getByName, httpSession.getId(), login.getData(),
Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
3)读取 Cookie 和 Session
读取Cookie
private final static String COOKIE_DOMAIN = "localhost";
private final static String COOKIE_NAME = "seckill_login_token";
public static String readLoginToken(HttpServletRequest request){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck : cks){
log.info("read cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
log.info("return cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
return ck.getValue();
}
}
}
return null;
}
读取Session
User user = redisService.get(UserKey.getByName, loginToken, User.class);
3)删除 Cookie 和 Session
删除Cookie
public static void delLoginToken(HttpServletRequest request, HttpServletResponse response){
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if(StringUtils.equals(cookie.getName(),COOKIE_NAME)){
cookie.setDomain(COOKIE_DOMAIN);
cookie.setPath("/");
cookie.setMaxAge(0);//设置成0,代表删除此cookie。
// log.info("del cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
response.addCookie(cookie);
return;
}
}
}
}
删除Session
redisService.del(UserKey.getByName , token);
Transaction
在需要执行事务的方法上方添加@Transactional
注解
@Transactional
public OrderInfo insert(User user, GoodsBo goods) {
//秒杀商品库存减一
//插入秒杀表
}
Lombok
直接添加Lombok依赖即可,可用于在entity类添加@Data注解。
Logging
配置
logging:
level:
com.netflix: WARN
org.springframework.web: WARN
com.zhou: INFO
OSS
使用谷粒商城写好的Singleupload.Vue和MultiUpload.Vue两个组件之后报错:The OSS Access Key Id you provided does not exist in our records。原因:封装上传参数的时候参数名称没有写对,改过来就好了。
dataObj: {
OSSAccessKeyId: '',
policy: '',
Signature: '',
key: '',
host: '',
dir: '',
uuid: ""
},
在阿里云OSS对象存储控制台创建bucket,并设置为 公共读 和 允许跨域。
在阿里云RAM控制台创建子用户,保存用户ID和KEY(只在创建时显示,之后无法再查看):
access-key: LTAI5tMLTWzrybw6qw6RwhYd
secret-key: wfgKv6jkJXQbyyZcp75NWE2wgPMPHE
为该子用户添加权限:
{AliyunOSSFullAccess 管理对象存储服务(OSS)权限(已添加)}(添加这1个就可以了)
third-party的pom添加依赖:aliyun-oss-spring-boot-starter
添加bootstrap.properties文件:
spring.application.name=zhoumall-third-party
spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=bf88dd25-311b-42b4-9729-9facaa8cad40
spring.cloud.nacos.config.extension-configs[0].data-id=oss.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
添加配置项oss.xml:
spring:
cloud:
alicloud:
access-key: LTAI5tDEftneVL9Gua3XHMd5
secret-key: ITlo1G4uThQCbg8m2aZLXHfz4AykZo
oss:
endpoint: oss-cn-qingdao.aliyuncs.com
枚举请求状态
constant
文件夹:创建一个CodeMsg
类枚举常用状态码和状态信息
public class CodeMsg {
private int code;
private String msg;
......
public static CodeMsg SUCCESS = new CodeMsg(0, "success");
public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务端异常");
......
}
全局统一返回
utils
文件夹:创建一个Result
类统一所有api
返回的数据格式。
public class Result<T> {
private int code;
private String msg;
private T data;
......
}
MD5密文存储
前后端都要实现MD5加密,后端原理不懂,前端代码不懂。
1)添加MD5
依赖
<!-- MD5加密 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- 使用StringUtils类需要添加依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
2)实现MD5
加密
创建一个工具类MD5Util
。
import org.apache.commons.codec.digest.DigestUtils;
public class MD5Util {
// 加密算法
public static String md5(String src) {
return DigestUtils.md5Hex(src);
}
// 盐
private static final String salt = "9d5b364d";
// 明文+盐➡加密➡密文
public static String inputPassToFormPass(String inputPass) {
String str = ""+salt.charAt(0)+salt.charAt(2) + inputPass +salt.charAt(5) + salt.charAt(4);
return md5(str);
}
// 密文+盐➡加密➡数据库密文
public static String formPassToDBPass(String formPass, String salt) {
String str = ""+salt.charAt(0)+salt.charAt(2) + formPass +salt.charAt(5) + salt.charAt(4);
return md5(str);
}
// 明文+盐➡加密➡密文,密文+盐➡加密➡数据库密文
public static String inputPassToDbPass(String inputPass, String saltDB) {
String formPass = inputPassToFormPass(inputPass);
String dbPass = formPassToDBPass(formPass, saltDB);
return dbPass;
}
// test
public static void main(String[] args) {
System.out.println(inputPassToDbPass("12345678", "9d5b364d")); // cd235d8b395725d4c3352e9689f346b6
}
}
3)用法
String dbPwd= user.getPassword();
String dbSalt = user.getSalt();
String calcPass = MD5Util.formPassToDBPass(loginParam.getPassword(), dbSalt);
实体类别划分
实体类别 | 备注 | |
---|---|---|
entity | 数据库实体类 | |
param | 接口参数封装类 | |
bo | 业务中间数据实体类,封装了业务中间状态的数据格式,可以包含业务方法 | |
constant | 各种枚举常量 |
参数校验
见文档JSR303.md
使用参数校验
1)引入依赖
<!--参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
1)校验规则注解
为实体类添加注解
@NotBlank(message = "name不能为空")
@NotEmpty
@URL(message = "logo必须是一个合法的url")
@NotEmpty // 作用于列表数组等
@Pattern(regexp = "^[a-zA-Z]$", message = "检索首字母必须是一个字母")
@NotNull // 作用于对象上
@Min(value = 0, message = "排序必须大于等于0")
2)校验标识注解
为参数添加注解@Valid
@RequestMapping("/login")
public String login(HttpRequest request, HttpResponse response, @Valid LoginParam loginParam){
return "login";
}
4)校验配置
配置文件中添加配置,自动返回错误信息
include-binding-errors: always
自定义参数校验
1)定义校验规则注解
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class})
public @interface IsMobile {
boolean required() default true;
String message() default "手机号码格式错误";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
2)定义校验器
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {
private boolean required = false;
public void initialize(IsMobile constraintAnnotation) {
required = constraintAnnotation.required();
}
public boolean isValid(String value, ConstraintValidatorContext context) {
if(required) {
return ValidatorUtil.isMobile(value);
}else {
if(StringUtils.isEmpty(value)) {
return true;
}else {
return ValidatorUtil.isMobile(value);
}
}
}
}
3)实现校验逻辑
定义校验工具类
public class ValidatorUtil {
private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");
public static boolean isMobile(String src) {
if(StringUtils.isEmpty(src)) {
return false;
}
Matcher m = mobile_pattern.matcher(src);
return m.matches();
}
}
统一异常处理
编码步骤:
- zhoumall-product中创建异常目录:com.zhou.mall.product.exception
- 创建异常处理文件:ZhoumallExceptionControllerAdvice.java
- 编写异常处理逻辑:针对不同的异常类型编写不同的异常处理方法
// 处理数据校验异常
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleValidException(MethodArgumentNotValidException e) {
log.error("数据校验出现问题:{},异常类型:{}", e.getMessage(), e.getClass());
BindingResult bindingResult = e.getBindingResult();
Map<String, String> map = new HashMap<>();
bindingResult.getFieldErrors().forEach((fieldError -> {
map.put(fieldError.getField(), fieldError.getDefaultMessage());
}));
return R.error(400, "数据校验异常").put("data", map);
}
// 处理其他异常
@ExceptionHandler
public R handleException(Exception e){
return R.error();
}
定义错误状态码和错误信息
- zhoumall-common中创建异常处理目录:com.zhou.common.exception
- 编写枚举类BizCodeEnume
package com.zhou.common.exception;
/**
* 错误码和错误信息校验类:
* 1. 错误码定义规则为5位数字
* 2. 前两位表示业务场景,最后三位表示错误码。例如:10001。10:通用,001系统未知异常
* 3. 维护错误码后需要维护错误描述,将他们定义为枚举类型
*
* 错误码列表
* 10:通用
* 001:参数格式校验
* 11:商品
* 12:订单
* 13:购物车
* 14:物流
*/
public enum BizCodeEnume {
UNKNOW_EXCEPTION(10000,"系统未知异常"),
VALID_EXCEPTION(10001, "参数校验失败");
private int code;
private String message;
BizCodeEnume(int code, String message){
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
- 返回的状态码和错误消息直接从枚举类中获取
return R.error(BizCodeEnume.VALID_EXCEPTION.getCode(), BizCodeEnume.VALID_EXCEPTION.getMessage()).put("data", map);
分组校验
- 在zhoumall-common中添加分组校验目录和2个分组校验组别接口
- 添加分组校验组别groups={AddGroup.class, UpdateGroup.class}
@NotEmpty(message = "logo地址不能为空", groups = {AddGroup.class})
@URL(message = "logo必须是一个合法的url", groups = {AddGroup.class, UpdateGroup.class})
private String logo;
- Controller中方法参数换成@Validated({AddGroup.class})
public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand /*, BindingResult result*/)
注意:使用@Validate注解之后,bean属性中注解没有添加groups的校验默认不生效,这点和@Valid注解不同。
编码到P69 00:00 自定义校验规则
自定义校验注解
1)定义校验规则注解
编写一个自定义的校验注解&自定义该注解的配置信息
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
String message() default "{com.zhou.common.valid.ListValue.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int[] vals() default {};
}
2)配置注解信息
ValidationMessages.properties
com.zhou.common.valid.ListValue.message=必须提交指定的值
3)定义的校验器
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {
private Set<Integer> set = new HashSet<>();
// 初始化方法
@Override
public void initialize(ListValue constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
}
/**
* 判断是否校验成功
* @param integer 需要校验的值
*/
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
return set.contains(integer);
}
}
- 关联自定义的校验注解和自定义的校验器
@Constraint(validatedBy = {ListValueConstraintValidator.class})
MySQL
数据源配置
## 数据源
spring:
datasource:
username: root
password: zjk123456
url: jdbc:mysql://192.168.137.32:3306/gulimall_sms
driver-class-name: com.mysql.cj.jdbc.Driver
Redis
redis缓存的使用
1)添加依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
2)定义配置类
配置项实体类 RedisConfig.java
@Setter
@Getter
@Component
@ConfigurationProperties(prefix="redis")
public class RedisConfig {
private String host;
private int port;
private int timeout;//秒
private String password;
private int poolMaxTotal;
private int poolMaxIdle;
private int poolMaxWait;//秒
}
增加配置项数据
application.yaml
redis:
host: 192.168.137.2
password: 123456
poolMaxIdle: 500
poolMaxTotal: 1000
poolMaxWait: 500
port: 6379
timeout: 10
3)创建redis客户端
操作Redis的客户端有2种可选:Jedis
和 RedisTemplate
,这里选择的是Jedis
。
RedisPoolFactory.java
@Service
public class RedisPoolFactory {
@Autowired
RedisConfig redisConfig;
@Bean
public JedisPool JedisPoolFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000);
JedisPool jp = new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(),
redisConfig.getTimeout()*1000, redisConfig.getPassword(), 0);
return jp;
}
}
4)创建redis服务类
RedisService.java
@Service
public class RedisService {
@Autowired
JedisPool jedisPool;
/**
* 增(存入对象)
* */
public <T> boolean set(KeyPrefix prefix, String key, T value ,int exTime) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String str = beanToString(value);
if(str == null || str.length() <= 0) {
return false;
}
//生成真正的key
String realKey = prefix.getPrefix() + key;
if(exTime == 0) {
//直接保存
jedis.set(realKey, str);
}else {
//设置过期时间
jedis.setex(realKey, exTime, str);
}
return true;
}finally {
returnToPool(jedis);
}
}
/**
* 删
*/
public Long del(KeyPrefix prefix,String key){
Jedis jedis = null;
Long result = null;
try {
jedis = jedisPool.getResource();
result = jedis.del(prefix.getPrefix()+key);
return result;
} finally {
returnToPool(jedis);
}
}
/**
* 改(修改过期时间)
*/
public Long expire(KeyPrefix prefix,String key,int exTime){
Jedis jedis = null;
Long result = null;
try {
jedis = jedisPool.getResource();
result = jedis.expire(prefix.getPrefix()+key,exTime);
return result;
} finally {
returnToPool(jedis);
}
}
/**
* 改(将值自增1,不存在就先置0)
* */
public <T> Long incr(KeyPrefix prefix, String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey = prefix.getPrefix() + key;
return jedis.incr(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 改(将值自减1,如果值不存在就先置0再自减1)
* */
public <T> Long decr(KeyPrefix prefix, String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey = prefix.getPrefix() + key;
return jedis.decr(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 查(返回对象)
* */
public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey = prefix.getPrefix() + key;
String str = jedis.get(realKey);
T t = stringToBean(str, clazz);
return t;
}finally {
returnToPool(jedis);
}
}
/**
* 查(判断是否存在)
* */
public <T> boolean exists(KeyPrefix prefix, String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey = prefix.getPrefix() + key;
return jedis.exists(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 工具:将 bean 转 String
*/
public static <T> String beanToString(T value) {
if(value == null) {
return null;
}
Class<?> clazz = value.getClass();
if(clazz == int.class || clazz == Integer.class) {
return ""+value;
}else if(clazz == String.class) {
return (String)value;
}else if(clazz == long.class || clazz == Long.class) {
return ""+value;
}else {
return JSON.toJSONString(value);
}
}
/**
* 工具:string 转 bean
*/
public static <T> T stringToBean(String str, Class<T> clazz) {
if(str == null || str.length() <= 0 || clazz == null) {
return null;
}
if(clazz == int.class || clazz == Integer.class) {
return (T)Integer.valueOf(str);
}else if(clazz == String.class) {
return (T)str;
}else if(clazz == long.class || clazz == Long.class) {
return (T)Long.valueOf(str);
}else {
return JSON.toJavaObject(JSON.parseObject(str), clazz);
}
}
/**
* 关闭与 redis 的连接
*/
private void returnToPool(Jedis jedis) {
if(jedis != null) {
jedis.close();
}
}
}
RabbitMQ
RabbitMQ消息队列的使用
1)添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2)定义配置类
配置信息
#rabbitmq
spring.rabbitmq.host=192.168.137.2
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.listener.simple.concurrency= 10
spring.rabbitmq.listener.simple.max-concurrency= 10
spring.rabbitmq.listener.simple.prefetch= 1
spring.rabbitmq.listener.simple.auto-startup=true
spring.rabbitmq.listener.simple.default-requeue-rejected= true
spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=1000
spring.rabbitmq.template.retry.max-attempts=3
spring.rabbitmq.template.retry.max-interval=10000
spring.rabbitmq.template.retry.multiplier=1.0
配置类
@Configuration
public class MQConfig {
public static final String SECKILL_QUEUE = "seckill.queue";
public static final String QUEUE = "queue";
@Bean
public MessageConverter getMessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public Queue queue() {
return new Queue(QUEUE, true);
}
3)定义消息
@Setter
@Getter
public class SeckillMessage {
private User user;
private long goodsId;
}
4)定义生产者
@Service
public class MQSender {
private static Logger log = LoggerFactory.getLogger(MQSender.class);
@Autowired
AmqpTemplate amqpTemplate;
public void sendSeckillMessage(SeckillMessage mm) {
String msg = RedisService.beanToString(mm);
log.info("send message:"+msg);
amqpTemplate.convertAndSend(MQConfig.SECKILL_QUEUE, msg);
}
}
5)定义消费者
@Service
public class MQReceiver {
private static Logger log = LoggerFactory.getLogger(MQReceiver.class);
@Autowired
RedisService redisService;
@Autowired
SeckillGoodsService goodsService;
@Autowired
OrderService orderService;
@Autowired
SeckillOrderService seckillOrderService;
@RabbitListener(queues=MQConfig.SECKILL_QUEUE)
public void receive(String message) {
log.info("receive message:"+message);
SeckillMessage sm = RedisService.stringToBean(message, SeckillMessage.class);
User user = sm.getUser();
long goodsId = sm.getGoodsId();
GoodsBo goods = goodsService.getSeckillGoodsBoByGoodsId(goodsId);
int stock = goods.getStockCount();
if(stock <= 0) {
return;
}
//判断是否已经秒杀到了
SeckillOrder order = seckillOrderService.getSeckillOrderByUserIdGoodsId(user.getId(), goodsId);
if(order != null) {
return;
}
//减库存 下订单 写入秒杀订单
seckillOrderService.insert(user, goods);
}
}
分布式技术:
微服务架构图:
微服务组件:
SpringCloud
阿里巴巴nacos注册中心: 文档链接
- 依赖管理
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Spring Boot 和Spring Cloud 版本适配
spring-boot-starter-parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
spring-cloud-dependencies
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 注册中心
nacos.discovery
引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置 Nacos Server 地址
spring:
cloud:
nacos:
discovery:
server-addr: 101.43.245.198:8848
使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
@EnableDiscoveryClient
为每个服务增加添加基本配置信息(服务有名字才能注册上去)
spring:
application:
name: upcmall-product
server:
port: 11000
- 远程调用
所使用的组件是:springcloud.openfeign
引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
开启feign功能
@EnableFeignClients(basePackages=“com.upc.upcmall.product.feign”)
声明远程接口
@FeignClient(“upcmall-ware”)
public interface WareFeignService{
@PostMapping(“ware/waresku/skus”)
Public Resp<List<SkuStockVo>> skuWareInfos(@RequestBody List<Long> skuIds);
}
编写一个接口,告诉SpringCloud这个接口需要调用远程服务
- 配置中心
所使用的组件是 nacos.config
引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
创建配置文件bootstrap.properties
spring.application.name=upcmall-coupon
spring.cloud.nacos.config.server-addr=101.43.245.198:8848
在配置中心添加一个数据集(Data Id)upcmall-coupon.properties(应用名.properties)
coupon.user.name=”李四”
coupon.user.age=”18”
配置配置文件application.properties
coupon.user.name=”张三”
coupon.user.age=”20”
添加测试接口
@Value("${coupon.user.name}")
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R test(){
return R.ok().put("name",name).put("age",age);
}
添加注解
@RefreshScope //动态获取并刷新配置
@Value(“${配置项的名}”) //获取配置项
在配置中心统一所有配置bootstrap.properties
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true
spring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true
- 网关
使用的组件是:spring.cloud.gateway
引入依赖,引入common依赖并剔除springboot.web依赖,解决依赖冲突
<dependency>
<groupId>com.upc.upcmall</groupId>
<artifactId>upcmall-common</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
添加注解,取消数据源自动配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
配置文件application.properties
spring.application.name=upcmall-gateway
spring.cloud.nacos.discovery.server-addr=101.43.245.198:8848
server.port=88
配置文件bootstrap.properties
spring.application.name=upcmall-gateway
spring.cloud.nacos.config.server-addr=101.43.245.198:8848
spring.cloud.nacos.config.namespace=65ef2335-6de9-46c1-9807-e688c87d09e6
spring.cloud.nacos.config.group=dev
配置predicate factory application.yml
spring:
cloud:
gateway:
routes:
- id: baidu_route
uri: https://baidu.com
predicates:
- Query=url,baidu
- id: qq_route
uri: https://qq.com
predicates:
- Query=url,qq
浏览器中测试:http://localhost:88/?url=qq
- 事件驱动
依赖
<!--集成消息中间件:spring-cloud-stream、kafka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
spring cloud stream 配合kafka的使用见git仓库
centos7中安装kafka
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>
配置
spring:
cloud:
stream:
kafka:
binder:
brokers: 192.168.137.41:9092
bindings:
input:
destination: accountChangeTopic
contentType: application/json
output:
destination: accountChangeTopic
contentType: application/json
Maven
v3.8.2常用命令
# 删除target
mvn clean
# 编译
mvn compile
# 打包
mvn package -DskipTests=ture
# 安装到本地仓库
mvn install
# 安装到远程仓库
mvn deploy
# 打包并运行springboot
mvn spring-boot:run
# 检验资源是否可用
mvn validate
# 测试
mvn test
Docker
教程:https://docs.docker.com/language/java/develop/
Docker仓库:https://hub.docker.com/repository/docker/zhoujiakai/cicdtest/general
Github仓库:https://github.com/zhoujiakai/cicdtest
使用最新版本 v24.0.6,分为3步:定义Dockerfile、docker build、docker run。分为8个步骤:
- 打包镜像
定义Dockerfile
环境准备:jdk8_202,mvn3,git
## syntax=docker/dockerfile:1
FROM eclipse/ubuntu_jdk8:latest
WORKDIR /app
COPY pom.xml ./
COPY src ./src
RUN mvn clean install
CMD ["java", "-jar", "./target/cicdtest-1.0.0-SNAPSHOT.jar"]
构建
cd cicdtest
docker build --tag zhoujiakai/cicdtest .
docker images
2)运行容器
docker run \
--name mypro \
-d -p 8080:8080 \
zhoujiakai/cicdtest:latest
docker run \
–name mypro \
-d -p 8080:8080 \
zhoujiakai/cicdtest:latest
3)组合服务
持久化存储:创建2个卷
docker volume create mysql_data
docker volume create mysql_config
创建一个网络:mysqlnet
docker network create mysqlnet
运行mysql容器:
docker run -it --rm -d -v mysql_data:/var/lib/mysql \
-v mysql_config:/etc/mysql/conf.d \
--network mysqlnet \
--name mysqlserver \
-e MYSQL_USER=petclinic -e MYSQL_PASSWORD=petclinic \
-e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=petclinic \
-p 3306:3306 mysql:8.0
更新Dockerfile文件:
## syntax=docker/dockerfile:1
FROM eclipse/ubuntu_jdk8:latest
WORKDIR /app
COPY pom.xml ./
COPY src ./src
RUN mvn clean install
CMD ["java", "-jar", "./target/cicdtest-1.0.0-SNAPSHOT.jar"]
创建docker-compose.dev.yml
version: '3.8'
services:
cicdtest:
build:
context: .
ports:
- "8080:8080"
volumes:
- ./:/app
depends_on:
- mysqlserver
mysqlserver:
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_ALLOW_EMPTY_PASSWORD=true
- MYSQL_USER=cicdtest
- MYSQL_PASSWORD=cicdtest
- MYSQL_DATABASE=cicdtest
volumes:
- mysql_data:/var/lib/mysql
- mysql_config:/etc/mysql/conf.d
volumes:
mysql_data:
mysql_config:
构建服务:
docker compose -f docker-compose.dev.yml up --build -d
4)CICD
1) Create a new repository on GitHub.
https://github.com/zhoujiakai/cicdtest
2) Define the GitHub Actions workflow.
DOCKERHUB_USERNAME:zhoujiakai
(dockerhub中)clockboxci:dckr_pat_sSv53yr3x1Vtk269DqsHYg3-U20
DOCKERHUB_TOKEN:dckr_pat_sSv53yr3x1Vtk269DqsHYg3-U20
3) Run the workflow.
name: ci
on:
push:
branches:
- "main"
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/cicdtest:latest
测试运行
docker run \
--name mypro \
-d -p 8080:8080 \
zhoujiakai/cicdtest:latest
成功
使用docker运行打包好的java文件
- 将jar文件放到:服务器
位置:“/tmp/dockertmp”
- 创建Dockerfile
教程:docker官方文档,博客csdn @ 小刘不想敲代码
创建“Dockerfile”并添加以下内容
## 基础镜像使用java
FROM zhoujiakai/openjdk:jdk18
## 作者
MAINTAINER zhoujk
## VOLUME 指定临时文件目录 /tmp 在主机 /var/lib/docker 目录下创建一个临时文件并连接到容器的 /tmp
VOLUME /tmp
## 将jar包添加到容器中并更名为 callback_docker.jar(这个最重要!!!)
ADD oss-callback-server-demo.jar callback_docker.jar
## 运行jar包
RUN bash -c 'touch /callback_docker.jar'
ENTRYPOINT ["java","-jar","/callback_docker.jar"]
## 暴露端口
EXPOSE 9000
- 创建docker镜像
docker build -t callback_docker:1.6 .
- 运行docker容器
docker run --rm -d -p 9000:9000 callback_docker:1.6 --name callback1
docker run --rm -it -p 9000:9000 callback_docker:1.6 --name callback1
- 有个类没有找到
org/eclipse/jetty/server/Handler
Kubesphere
使用版本v4.0.0,Kubesphere结构如下:
admin:默认管理员用户,在 KubeSphere平台具有所有权限,并可以根据需要创建其他用户。
角色和用户:将不同的权限组合抽象成角色。角色分为:平台角色、集群角色、企业空间角色、项目角色
用户: 每一个用户都只属于一种角色,拥有角色所定义的操作系统资源的权限。
集群
企业空间
项目
多集群项目
DevOps项目
k8s-v1.28.0
学习的思路:基本概念 → \rightarrow →最佳实践 → \rightarrow →应用到项目中
k8s基本组件
master节点:
etcd(2379/2380):分布式存储机制,保存整个集群的状态
API server(6443):对外提供操作和访问etcd的API
Scheduler(10251):调度Pod资源到相应的机器上
Controller Manager(10252):自动观察和维护集群状态
worker节点:
Controller Runtime:下载镜像和运行容器
Pod:k8s的基本调度单位
kubelet(10250):与master节点上的API server进行交互,接收指令执行操作
kube-proxy(10256):负责对Pod进行寻址和负载均衡
网络通讯:
dashboard(8443):用户操作k8s集群是通过kubectl命令行工具或者dashboard;
Pod之间进行通讯时通过集群内部覆盖网络Overlay Network;
外部流量进行集群访问Pod则是通过负载均衡Load Balander设备进行。
k8s数据字典
如何使用k8s:
Cluster:整个kubernetes集群,使用kubernetes统一管理整个集群的资源。
Deployment:部署应用程序
使用 kubectl create deployment 命令在 Kubernetes 上部署应用,例如:
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
kubectl get deployments列出所有部署
Service:使用service整合多个pod以及向外部暴露service服务,在运行deployment时使用–expose参数创建一个service
Replicas:在运行kubectl run命令时使用–replicas参数来设置副本数。
外部化应用配置:使用 Kubernetes ConfigMaps 和 Secrets 设置环境变量, 然后在 MicroProfile config 中使用它们。
k8s常用命令
删除资源:kubectl delete pod/redis configmap/example-redis-config
删除services:kubectl delete services my-service
删除deployment:kubectl delete deployment hello-world
Jenkins
官网教程:https://www.jenkins.io/doc/book/installing/linux/#debianubuntu