1月6
使用场景,多个接口的某个或多个参数都是从登录态中获取的,如下的capCode,这里只设计修改入参。
@Order(1)
@Component
@Aspect
@Slf4j
public class CapCodeAspect {
@Autowired
private TokenService tokenService;
public CapCodeAspect() {
}
@Pointcut("@annotation(com.xx.oo.annotation.CapCode)")
private void parameterPointCut() {
}
@Around("parameterPointCut()")
public Object getCapCode(ProceedingJoinPoint joinPoint) {
try {
Object[] o = joinPoint.getArgs();
if (null != o) {
for (Object ob : o) {
changObjectValue(ob, "capCode", gatCapCode());
}
}
return joinPoint.proceed(o);
} catch (Throwable e) {
log.error("目标方法执行异常,目标类:" + joinPoint.getTarget() + "方法:" + joinPoint.getSignature().getName(), e);
throw new RuntimeException("系统繁忙,请稍后再试!");
}
}
/***
* 修改入参具体字段值
*/
private Object changObjectValue(Object obj, String filedName, Object afterValue) throws Exception {
Class<?> resultClz = obj.getClass();
//获取父类的字段,因为capCode放在在基类里面,这里就直接获取父类的Class了,
//参数只在当前类的可以添加当前类的逻辑
Field[] fieldInfo = resultClz.getSuperclass().getDeclaredFields();
for (Field field : fieldInfo) {
if (filedName.equals(field.getName())) {
field.setAccessible(true); //成员变量为private,故必须进行此操
Object fieldValue = field.get(obj);
field.set(obj, afterValue);
break;
}
}
return obj;
}
private String gatCapCode() {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
String capCode = user.getProviderId();
log.info("资金编码:{}", capCode);
return capCode;
}
}
@Order(1)
@Component
@Aspect
@Slf4j
public class CapCodeAspect {
@Autowired
private TokenService tokenService;
public CapCodeAspect() {
}
@Pointcut("@annotation(com.xx.oo.annotation.CapCode)")
private void parameterPointCut() {
}
@Around("parameterPointCut()")
public Object getCapCode(ProceedingJoinPoint joinPoint) {
try {
Object[] o = joinPoint.getArgs();
if (null != o) {
for (Object ob : o) {
changObjectValue(ob, "capCode", gatCapCode());
}
}
return joinPoint.proceed(o);
} catch (Throwable e) {
log.error("目标方法执行异常,目标类:" + joinPoint.getTarget() + "方法:" + joinPoint.getSignature().getName(), e);
throw new RuntimeException("系统繁忙,请稍后再试!");
}
}
/***
* 修改入参具体字段值
*/
private Object changObjectValue(Object obj, String filedName, Object afterValue) throws Exception {
Class<?> resultClz = obj.getClass();
//获取父类的字段,因为capCode放在在基类里面,这里就直接获取父类的Class了,
//参数只在当前类的可以添加当前类的逻辑
Field[] fieldInfo = resultClz.getSuperclass().getDeclaredFields();
for (Field field : fieldInfo) {
if (filedName.equals(field.getName())) {
field.setAccessible(true); //成员变量为private,故必须进行此操
Object fieldValue = field.get(obj);
field.set(obj, afterValue);
break;
}
}
return obj;
}
private String gatCapCode() {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
String capCode = user.getProviderId();
log.info("资金编码:{}", capCode);
return capCode;
}
}
1月4
工作中发现一个问题。当我用HttpURLConnection去连接读取一个获取每年的节假日接口信息时,老是会发生这个403错误,通过浏览器访问时显示状态码为304,但量使用代码HttpURLConnection去请求会报403的错误,这个引起了IOException,导致获取的直一直为空,但是我使用浏览器请求这个接口时时就没问题。 google后知道了答案。原来如果用java代码HttpURLConnection去连的话 http header 中的User-Agent就为空,解决方法就是在连接之前先设置这个属性。
节假日获取接口:http://timor.tech/api/holiday/year/2022
节假日获取接口:http://timor.tech/api/holiday/year/2022
12月31
公司有个项目运维管理平台中用户管理模块添加用户时填写用户邮箱反馈说不能带点,如heck.jiang@heckjj.com这种,这明显不合理呀,而且这种情况也很常见。如下图:

于是乎拉下前端代码发现,校验邮箱的正则是这样的“{ required: true, message: '请输入正确的邮箱', pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, trigger: 'blur' }”,明显达到期望,自己重新写了一个如下:
^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
用校验工具校验了一下,成功匹配到了heck.jiang@heckjj.com这个邮箱。
于是乎拉下前端代码发现,校验邮箱的正则是这样的“{ required: true, message: '请输入正确的邮箱', pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, trigger: 'blur' }”,明显达到期望,自己重新写了一个如下:
^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
用校验工具校验了一下,成功匹配到了heck.jiang@heckjj.com这个邮箱。
12月29
一、所有库在同一节点上
当业务垂直拆分出很多业务库的时候,如果都部署在同一个源上(同一个机器节点上),那么这种情况是最好办的,直接库名+表名 join就可以。
二、不在一个节点
当不同的库来自不同的节点,那么就没办法直接join查询了,有以下方式和思路:
1.全局表
所谓全局表,就是有可能系统中所有模块都可能会依赖到的一些表。比较类似我们理解的“数据字典”。为了避免跨库join查询,我们可以将这类表在其他每个数据库中均保存一份。同时,这类数据通常也很少发生修改(甚至几乎不会),
所以也不用太担心“一致性”问 题。
2.字段冗余
这是一种典型的反范式设计,在互联网行业中比较常见,通常是为了性能来避免join查询。字段冗余能带来便利,是一种“空间换时间”的体现。但其适用场景也比较有限,比较适合依赖字段较少的情况。
最复杂的还是数据一致性问题,这点很难保证,可以借助数据库中的触发器或者在业务代码层面去保证。当然,也需要结合实际业务场景来看一致性的要求。
3.数据同步
定时A库中的tab_a表和B库中tbl_b有关联,可以定时将指定的表做同步。当然,同步本来会对数据库带来一定的影响,需要性能影响和数据时效性中取得一个平衡。这样来避免复杂的跨库查询。笔者曾经在项目中是通过ETL工具来实施的。
4.第三方插件
1.cobar
2.MyCAT
3.shardding-jdbc
当业务垂直拆分出很多业务库的时候,如果都部署在同一个源上(同一个机器节点上),那么这种情况是最好办的,直接库名+表名 join就可以。
二、不在一个节点
当不同的库来自不同的节点,那么就没办法直接join查询了,有以下方式和思路:
1.全局表
所谓全局表,就是有可能系统中所有模块都可能会依赖到的一些表。比较类似我们理解的“数据字典”。为了避免跨库join查询,我们可以将这类表在其他每个数据库中均保存一份。同时,这类数据通常也很少发生修改(甚至几乎不会),
所以也不用太担心“一致性”问 题。
2.字段冗余
这是一种典型的反范式设计,在互联网行业中比较常见,通常是为了性能来避免join查询。字段冗余能带来便利,是一种“空间换时间”的体现。但其适用场景也比较有限,比较适合依赖字段较少的情况。
最复杂的还是数据一致性问题,这点很难保证,可以借助数据库中的触发器或者在业务代码层面去保证。当然,也需要结合实际业务场景来看一致性的要求。
3.数据同步
定时A库中的tab_a表和B库中tbl_b有关联,可以定时将指定的表做同步。当然,同步本来会对数据库带来一定的影响,需要性能影响和数据时效性中取得一个平衡。这样来避免复杂的跨库查询。笔者曾经在项目中是通过ETL工具来实施的。
4.第三方插件
1.cobar
2.MyCAT
3.shardding-jdbc
12月29
最近在做项目时有一个这样需求,上传文件需要显示预览,当我了解之后,我以为和普通的下载一样呢,结果后台返回的是文件流格式,据说这是因为后台是分布式部署,不能持久化存储,没办法,只能前端来处理这个文件流了,用ajax请求图片资源,服务器以文件流的形式返回。
1、返回类型需要设置为“blob”,所以需要用原生ajax,不能使用jq(原因:jquery将返回的数据转换为了string,不支持blob类型)(当然,你也可以引入组件拓展jq的能力,我知道的有一个:jquery-ajax-blob-arraybuffer.js);
2、使用FileReader将文件流转换成base64格式;
3.1、然后通过模拟点击a标签下载该文件;
3.2、或者可以设置在img元素的src属性上,在当前页面显示出来。
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement('a');
a.download = 'data.xlsx';
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
}
}
};
// 发送ajax请求
xhr.send()
xhr.open('POST', CONTACT_ACTION_FILES_DOWNLOAD, true);
xhr.setRequestHeader("Accept", "application/json;q=0.5");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function () {
$("#imgTest").attr("src", reader.result);
}
}
};
// 发送ajax请求
xhr.send("filePath=" + filePath);
下载文件
export const downloadStream = (method = 'GET', url, downloadName) => {
const ctoken = getCookie('AIB_TOKEN')
if (ctoken) {
let xmlResquest = new XMLHttpRequest();
xmlResquest.open(method, url, true);
xmlResquest.setRequestHeader("Content-type", "application/json;charset=UTF-8");
//这里需要在请求头添加该参数,已防止CSRF
xmlResquest.setRequestHeader("csrfToken", hashStr(ctoken));
xmlResquest.responseType = "blob";
xmlResquest.onload = function (oEvent) {
let content = xmlResquest.response;
let elink = document.createElement('a');
elink.download = downloadName;
elink.style.display = 'none';
let blob = new Blob([content]);
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
};
xmlResquest.send();
}
}
1、返回类型需要设置为“blob”,所以需要用原生ajax,不能使用jq(原因:jquery将返回的数据转换为了string,不支持blob类型)(当然,你也可以引入组件拓展jq的能力,我知道的有一个:jquery-ajax-blob-arraybuffer.js);
2、使用FileReader将文件流转换成base64格式;
3.1、然后通过模拟点击a标签下载该文件;
3.2、或者可以设置在img元素的src属性上,在当前页面显示出来。
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement('a');
a.download = 'data.xlsx';
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
}
}
};
// 发送ajax请求
xhr.send()
xhr.open('POST', CONTACT_ACTION_FILES_DOWNLOAD, true);
xhr.setRequestHeader("Accept", "application/json;q=0.5");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function () {
$("#imgTest").attr("src", reader.result);
}
}
};
// 发送ajax请求
xhr.send("filePath=" + filePath);
下载文件
export const downloadStream = (method = 'GET', url, downloadName) => {
const ctoken = getCookie('AIB_TOKEN')
if (ctoken) {
let xmlResquest = new XMLHttpRequest();
xmlResquest.open(method, url, true);
xmlResquest.setRequestHeader("Content-type", "application/json;charset=UTF-8");
//这里需要在请求头添加该参数,已防止CSRF
xmlResquest.setRequestHeader("csrfToken", hashStr(ctoken));
xmlResquest.responseType = "blob";
xmlResquest.onload = function (oEvent) {
let content = xmlResquest.response;
let elink = document.createElement('a');
elink.download = downloadName;
elink.style.display = 'none';
let blob = new Blob([content]);
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
};
xmlResquest.send();
}
}
12月25
一. 错误信息
先上阿里云上的报警信息。有个最大的问题是:top命令查看自己服务器CPU运行情况,会发现kdevtmpfsi的进程,CPU使用率为100%,第一次删除干净了kdevtmpfsi程序,没曾想几分钟以后,就出现了第二个警告。使用netstat -antp命令查看端口使用情况,又出现了kdevtmpfsi如图所示
netstat -antp

二.解决方法
一般出现kdevtmpfsi病毒都会伴有定时任务,就会出现我上面说的处理一次后,又会继续出现,反反复复处理不干净。
1.首先停掉kdevtmpfsi的程序
ps aux
找到kdevtmpfsi的进程
删除掉与kdevtmpfsi相关的进程

kill -9 20267
kill -9 20367
2.删除Linux下的异常定时任务
crontab -l 查看定时任务
crontab -r 表示删除用户的定时任务,当执行此命令后,所有用户下面的定时任务会被删除
如下图所示
3.结束kdevtmpfsi进程及端口占用
netstat -antp
找到kdevtmpfsi端口 我这里是28244 图中可以看到。不要直接杀掉,因为有守护线程还会重启。
ps -aux | grep kinsing
ps -aux | grep kdevtmpfsi
kill -9 28244
kill -9 28829
4.删除掉kdevtmpfsi的相关文件
cd /tmp
ls
rm -rf kdevtmpfsi
rm -rf /var/tmp/kinsing
最后自己可以再检查一下是否还有kdevtmpfsi的相关文件,有的话就继续删除
find / -name kdevtmpfsi
find / -name kinsing
三.怎么预防处理这个病毒
最根本的原因可能是自己的redis 6379配置不当导致的。大家可以参考阿里云的Redis服务安全加固
当然也可能是弱密码,被强行扫描了,建议定期更换系统密码。
也可以使用下面工具清除
#! /bin/sh
step=1
for (( i = 0; i < 60; i = (i+step) )); do
date >> /data/shell/clear_date_log.txt
KID=$(ps -ef |grep kdevtmpfsi |grep -w 'kdevtmpfsi'|grep -v 'grep'|awk '{print $2}')
if [ $KID];then #
echo "[info]kdevtmpfsiIDΪ:$KID" >> /data/shell/clear_date_log.txt
kill -9 $KID
rm -f /tmp/kdevtmpfsi
fi
sleep $step
done
exit 0
复制上面代码另存为kill_kdevtmpfsi.sh
先上阿里云上的报警信息。有个最大的问题是:top命令查看自己服务器CPU运行情况,会发现kdevtmpfsi的进程,CPU使用率为100%,第一次删除干净了kdevtmpfsi程序,没曾想几分钟以后,就出现了第二个警告。使用netstat -antp命令查看端口使用情况,又出现了kdevtmpfsi如图所示
netstat -antp
二.解决方法
一般出现kdevtmpfsi病毒都会伴有定时任务,就会出现我上面说的处理一次后,又会继续出现,反反复复处理不干净。
1.首先停掉kdevtmpfsi的程序
ps aux
找到kdevtmpfsi的进程
删除掉与kdevtmpfsi相关的进程
kill -9 20267
kill -9 20367
2.删除Linux下的异常定时任务
crontab -l 查看定时任务
crontab -r 表示删除用户的定时任务,当执行此命令后,所有用户下面的定时任务会被删除
如下图所示
3.结束kdevtmpfsi进程及端口占用
netstat -antp
找到kdevtmpfsi端口 我这里是28244 图中可以看到。不要直接杀掉,因为有守护线程还会重启。
ps -aux | grep kinsing
ps -aux | grep kdevtmpfsi
kill -9 28244
kill -9 28829
4.删除掉kdevtmpfsi的相关文件
cd /tmp
ls
rm -rf kdevtmpfsi
rm -rf /var/tmp/kinsing
最后自己可以再检查一下是否还有kdevtmpfsi的相关文件,有的话就继续删除
find / -name kdevtmpfsi
find / -name kinsing
三.怎么预防处理这个病毒
最根本的原因可能是自己的redis 6379配置不当导致的。大家可以参考阿里云的Redis服务安全加固
当然也可能是弱密码,被强行扫描了,建议定期更换系统密码。
也可以使用下面工具清除
#! /bin/sh
step=1
for (( i = 0; i < 60; i = (i+step) )); do
date >> /data/shell/clear_date_log.txt
KID=$(ps -ef |grep kdevtmpfsi |grep -w 'kdevtmpfsi'|grep -v 'grep'|awk '{print $2}')
if [ $KID];then #
echo "[info]kdevtmpfsiIDΪ:$KID" >> /data/shell/clear_date_log.txt
kill -9 $KID
rm -f /tmp/kdevtmpfsi
fi
sleep $step
done
exit 0
复制上面代码另存为kill_kdevtmpfsi.sh
12月25
使用win10的朋友有没有遇到这样的情况,笔记本上连接过的wifi密码忘记了,现在没法连接又想找到以前记录的密码。如果你不知道或是正被这个问题困扰,可以参考下我的经验(●'◡'●)
注:现在可以连接上的wifi可以用本文方法查询,也可以参考下文
这种方法通过命令的方式查询所有连接过的WiFi,然后用命令查询具体要查询密码的WiFi。运行命令可以通过命令提示符窗口,也可以通过Windows PowerShell窗口,二者都是一样的。Windows PowerShell更为强大先进,所以用它来做操作说明。以下是具体操作:
A、右键单击开始菜单,点击Windows PowerShell
B、在【Windows PowerShell】窗口输入netsh,按下enter键
C、在netsh>后面输入wlan show profile或者wlan show profiles,按下enter键。在netsh语句里面profile和profiles是一样的。
D、我要CMCC-LJfh这个wifi的密码,那么输入命令wlan show profile CMCC-LJfh key=clear,敲下回车键。
命令提示符法比系统简单操作法稍微复杂一点,需要熟悉netsh命令。不熟悉也没关系,照上述说明操作即可。
也可以按下如下方式操作:
打开命令提示符(管理员)界面,输入命令 netsh wlan show profile
点击回车执行,显示以前连接并记录过的所有wifi配置
选择想要查询的wifi,输入命令 netsh wlan export profile name="所选wifi名称" folder=. key=clear
点击回车执行,配置信息自动保存到“系统安装盘的 windows/system32文件夹”下
注:不要修改命令中的folder参数,若是改到其他位置可能导致输出文件中的密码为加密后的而不是明文的
打开文件资源管理器(此电脑),进入C:\windows\system32文件夹,并定位到文件 WLAN-所选wifi名称.xml
右键选择打开方式用文本文件或浏览器打开,找到以下位置即为所选wifi的密码
注:现在可以连接上的wifi可以用本文方法查询,也可以参考下文
这种方法通过命令的方式查询所有连接过的WiFi,然后用命令查询具体要查询密码的WiFi。运行命令可以通过命令提示符窗口,也可以通过Windows PowerShell窗口,二者都是一样的。Windows PowerShell更为强大先进,所以用它来做操作说明。以下是具体操作:
A、右键单击开始菜单,点击Windows PowerShell
B、在【Windows PowerShell】窗口输入netsh,按下enter键
C、在netsh>后面输入wlan show profile或者wlan show profiles,按下enter键。在netsh语句里面profile和profiles是一样的。
D、我要CMCC-LJfh这个wifi的密码,那么输入命令wlan show profile CMCC-LJfh key=clear,敲下回车键。
命令提示符法比系统简单操作法稍微复杂一点,需要熟悉netsh命令。不熟悉也没关系,照上述说明操作即可。
也可以按下如下方式操作:
打开命令提示符(管理员)界面,输入命令 netsh wlan show profile
点击回车执行,显示以前连接并记录过的所有wifi配置
选择想要查询的wifi,输入命令 netsh wlan export profile name="所选wifi名称" folder=. key=clear
点击回车执行,配置信息自动保存到“系统安装盘的 windows/system32文件夹”下
注:不要修改命令中的folder参数,若是改到其他位置可能导致输出文件中的密码为加密后的而不是明文的
打开文件资源管理器(此电脑),进入C:\windows\system32文件夹,并定位到文件 WLAN-所选wifi名称.xml
右键选择打开方式用文本文件或浏览器打开,找到以下位置即为所选wifi的密码
12月17
一、执行程序切换后台
执行java -jar xxx.jar & 或者nohup java -jar xxxx.jar &。nohup不挂断的运行,注意并没有后台运行的功能,就是指,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系。
ctrl+z退出到控制台,执行 bg
执行exit
完成以上3步,退出SHELL后,jar服务一直在后台运行。
nohup java -jar XXX.jar >log.out &;
nohup是保证ssh连接关闭后,jar任然运行的关键,& 相当于后台运行,你后面还可以输入命令, >log.out 是输出日志的地方
ps aux|grep XXX.jar 查看某jar包的运行的进程号
二、结束进程
通过执行ps auxwww | grep XXX.jar通过查找进程关键字 找到进程PID。
执行kill -9 {PID} 杀死进程PID数字结束进程。
执行java -jar xxx.jar & 或者nohup java -jar xxxx.jar &。nohup不挂断的运行,注意并没有后台运行的功能,就是指,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系。
ctrl+z退出到控制台,执行 bg
执行exit
完成以上3步,退出SHELL后,jar服务一直在后台运行。
nohup java -jar XXX.jar >log.out &;
nohup是保证ssh连接关闭后,jar任然运行的关键,& 相当于后台运行,你后面还可以输入命令, >log.out 是输出日志的地方
ps aux|grep XXX.jar 查看某jar包的运行的进程号
二、结束进程
通过执行ps auxwww | grep XXX.jar通过查找进程关键字 找到进程PID。
执行kill -9 {PID} 杀死进程PID数字结束进程。
12月9
有个同事说使用Minio时发现返回的url访问直接访问不到,需要登录并且有有效期生成的文件地址,下面主要讲下在Minio中通过程序上传后的文件,返回的地址无法对外访问的问题。
MinioClient minioClient = new MinioClient(minio_url, minio_name, minio_pass);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String ymd = sdf.format(new Date());
String objectName = ymd + "/" + UUID.randomUUID().toString() + (suffix != null ? suffix : "");
minioClient.putObject(bucketName, objectName, inputStream, contentType);
String url = minioClient.getObjectUrl(bucketName, objectName);
这里程序得到的地址,如果你想在浏览器直接访问是不行的。如果想要访问,需要对Minio进行一些设置。
Minio的称之为policy 即桶策略。如果想要直接访问图片,需要设置Bucket的访问策略。
官方文档 https://docs.minio.io/cn/minio-client-complete-guide.html#mb
下面介绍两种方法来实现永久访问,两种方法效果是一样的。
一、通过管理界面实现
登录后台管理界面,在右下角有个红色的加号图标,点击它,然后会看到下面的效果
点击create bucket ,输入要创建的bucket,如test
回车就可创建成功。
创建成功之后对bucket进行编辑。在页面的右上角。找到刚刚创建的test bucket。
点击那三个点,选择Edit policy ,会弹出下面的弹窗。

在Prefix中输入* ,即允许所有访问。右边的选项选择 Read and write。

然后点击Add 按钮就可以了。
-----------------------------------------------------------------------------------------------------------------------------------------
二、通过Minio提供的客户端来实现
Minio单独提供了一个客户端来设置Minio的服务端。
1、下载客户端程序
下载地址 https://dl.minio.io/client/mc/release/windows-amd64/mc.exe
2、启动一个cmd窗口,进入mc.exe的目录
输入 .\mc.exe --h 可以查看mc.exe的命令帮助。
3、设置服务端
使用 minio client 将自己的 minio server 添加到 mc 的配置管理,命令如下
.\mc.exe config host add minio http://192.168.50.179:9000 3K2287Q20OW3HWQ2FJXJ L0eTMaBzVQwUgbeuo05f+qmSA
buZiWt4yZfDzrMv
Added `minio` successfully.
此命令将 http://192.168.50.179:9000 取一个别名 minio ,并交给mc进行配置管理。
4、查看minio中的桶,命令
.\mc.exe ls minio
[2021-12-08 20:34:25 CST] 0 B asiatrip\
[2021-12-08 21:15:55 CST] 0 B tonnyyy\
[2021-12-08 20:54:28 CST] 0 B xzspfj\
5、设置桶的访问策略,命令
.\mc.exe policy public minio/xzspfj/20211208/
Access permission for `minio/xzspfj/20211208/` is set to `public`
通过以上步骤,图片就可以直接通过地址进行访问了。
MinioClient minioClient = new MinioClient(minio_url, minio_name, minio_pass);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String ymd = sdf.format(new Date());
String objectName = ymd + "/" + UUID.randomUUID().toString() + (suffix != null ? suffix : "");
minioClient.putObject(bucketName, objectName, inputStream, contentType);
String url = minioClient.getObjectUrl(bucketName, objectName);
这里程序得到的地址,如果你想在浏览器直接访问是不行的。如果想要访问,需要对Minio进行一些设置。
Minio的称之为policy 即桶策略。如果想要直接访问图片,需要设置Bucket的访问策略。
官方文档 https://docs.minio.io/cn/minio-client-complete-guide.html#mb
下面介绍两种方法来实现永久访问,两种方法效果是一样的。
一、通过管理界面实现
登录后台管理界面,在右下角有个红色的加号图标,点击它,然后会看到下面的效果
点击create bucket ,输入要创建的bucket,如test
回车就可创建成功。
创建成功之后对bucket进行编辑。在页面的右上角。找到刚刚创建的test bucket。
点击那三个点,选择Edit policy ,会弹出下面的弹窗。
在Prefix中输入* ,即允许所有访问。右边的选项选择 Read and write。
然后点击Add 按钮就可以了。
-----------------------------------------------------------------------------------------------------------------------------------------
二、通过Minio提供的客户端来实现
Minio单独提供了一个客户端来设置Minio的服务端。
1、下载客户端程序
下载地址 https://dl.minio.io/client/mc/release/windows-amd64/mc.exe
2、启动一个cmd窗口,进入mc.exe的目录
输入 .\mc.exe --h 可以查看mc.exe的命令帮助。
3、设置服务端
使用 minio client 将自己的 minio server 添加到 mc 的配置管理,命令如下
.\mc.exe config host add minio http://192.168.50.179:9000 3K2287Q20OW3HWQ2FJXJ L0eTMaBzVQwUgbeuo05f+qmSA
buZiWt4yZfDzrMv
Added `minio` successfully.
此命令将 http://192.168.50.179:9000 取一个别名 minio ,并交给mc进行配置管理。
4、查看minio中的桶,命令
.\mc.exe ls minio
[2021-12-08 20:34:25 CST] 0 B asiatrip\
[2021-12-08 21:15:55 CST] 0 B tonnyyy\
[2021-12-08 20:54:28 CST] 0 B xzspfj\
5、设置桶的访问策略,命令
.\mc.exe policy public minio/xzspfj/20211208/
Access permission for `minio/xzspfj/20211208/` is set to `public`
通过以上步骤,图片就可以直接通过地址进行访问了。
12月7
平时我们经常查看容器的日志,命令如下:
docker logs -f 容器名或者容器id
随着时间的推移,日志文件越来越大,那么我们该如何清理日志文件呢?下面来讲解清理的步骤:
1.进入docker容器目录:
cd /var/lib/docker/containers/
2.查看容器的id,获取容器id,容器id就是容器目录名字
docker ps -a
3.进入容器,删除以log结尾的文件就是日志文件了,删除即可:
rm -rf 容器id.log
4.重启容器
docker restart 容器名或者容器id
打完收工!
docker logs -f 容器名或者容器id
随着时间的推移,日志文件越来越大,那么我们该如何清理日志文件呢?下面来讲解清理的步骤:
1.进入docker容器目录:
cd /var/lib/docker/containers/
2.查看容器的id,获取容器id,容器id就是容器目录名字
docker ps -a
3.进入容器,删除以log结尾的文件就是日志文件了,删除即可:
rm -rf 容器id.log
4.重启容器
docker restart 容器名或者容器id
打完收工!