jyoryo 发布的文章

Java Mail发送邮件email 支持SSL加密、TSL加密

类型服务名称服务器地址SSL协议端口非SSL协议端口TSL协议端口
收件服务器POPpop.163.com995110
收件服务器IMAPmap.163.com993143
发件服务器SMTPsmtp.163.com465/99425587

POM依赖:
注意:不要依赖javax.mail javax.mail-api 1.6.2,不然会提示:java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

Java Mail代码如下:

/**
 * 发送邮件
 *
 * @param toEmails    收件人列表
 * @param ccEmails    抄送人列表
 * @param subject     主题
 * @param htmlContent 邮件正文
 * @param files       附件。Key:附件的文件 Value:显示文件名
 */
public void sendByJavaMail(String[] toEmails, String[] ccEmails, String subject, String htmlContent, Map<String, String> files) {
    // 获取邮件配置
    final String mailServerUsername = "{你的邮箱地址,例如:xxx@163.com}",
        mailServerPassword = "{你的邮箱密码或授权密码}",      
        mailFrom = "{你的邮箱发件人地址,例如:xxx@163.com}",
        mailFromDisplayName = "{希望收件人看到的发件人显示名称,例如:报警服务}";
    if (Strings.isBlank(mailServerUsername) || Strings.isBlank(mailServerPassword) || Strings.isBlank(mailFrom)) {
        throw new ApiException("Email sending service is not set up, please contact the platform if there are any issues.");
    }
    // 设置邮箱服务属性
    Properties props = new Properties();
    props.setProperty("mail.smtp.host", "smtp.163.com");
    props.setProperty("mail.smtp.auth", "true");
    // "mail.smtp.host":"smtp.gmail.com" "mail.smtp.auth":"true" "mail.smtp.port":"587" "mail.smtp.starttls.enable":"true" "mail.smtp.ssl.protocols":"TLSv1.2"
    // TLS需要内容项:"mail.smtp.starttls.enable":"true" "mail.smtp.port":"587"
    // SSL需要内容项:"mail.smtp.ssl.enable":"true" "mail.smtp.port":"465" "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory"
    props.setProperty("mail.smtp.ssl.enable", "true");
    props.setProperty("mail.smtp.port", "465");
    props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");    

    // 获取默认的 Session 对象。
    Session session = Session.getInstance(props, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(mailServerUsername, mailServerPassword);
        }
    });
    // 是否配置debug打印日志信息
    session.setDebug(true);
    try {
        // 创建默认的 MimeMessage 对象。
        MimeMessage message = new MimeMessage(session);
        // 发送方邮箱
        Address fromAddress = Strings.isBlank(mailFromDisplayName) ? new InternetAddress(mailFrom) : new InternetAddress(mailFrom, mailFromDisplayName, "utf-8");
        message.setFrom(fromAddress);
        // 接收方邮箱
        for (String toEmail : toEmails) {
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
        }
        // 抄送邮件列表
        if (null != ccEmails && ccEmails.length > 0) {
            for (String ccEmail : ccEmails) {
                message.addRecipient(Message.RecipientType.CC, new InternetAddress(ccEmail));
            }
        }
        // 设置主题
        message.setSubject(subject);

        /* 消息部分 */
        // 正文
        Multipart multipart = new MimeMultipart();
        // HTML消息
        BodyPart htmlBodyPart = new MimeBodyPart();
        htmlBodyPart.setContent(htmlContent, "text/html;charset=UTF-8");
        multipart.addBodyPart(htmlBodyPart);
        // 设置附件
        if (null != files && !files.isEmpty()) {
            for (Map.Entry<String, String> entry : files.entrySet()) {
                final String file = entry.getKey(), filename = entry.getValue();
                BodyPart fileBodyPart = new MimeBodyPart();
                DataSource source = new FileDataSource(file);
                fileBodyPart.setDataHandler(new DataHandler(source));
                // fileBodyPart.setFileName(filename);
                fileBodyPart.setFileName(MimeUtility.encodeText(filename, "UTF-8", "B"));
                multipart.addBodyPart(fileBodyPart);
            }
        }
        message.setContent(multipart);
        // 发送消息
        log.debug(">>>>>>>>>>sendByJavaMail---sending--<<<<<<<<<<<<<<");
        Transport.send(message);
    } catch (Exception e) {
        log.error("", e);
    } finally {
        // 根据业务需求,是否删除附件的文件
        if (null != files && !files.isEmpty()) {
            for (Map.Entry<String, String> entry : files.entrySet()) {
                Files.deleteQuietly(new File(entry.getKey()));
            }
        }
    }
}

Nginx搭建WebDAV服务器

搭建webDAV服务前,先确认已安装nginx

配置webdav.conf

创建用于webdav的nginx配置文件:

vim /etc/nginx/conf.d/webdav.conf

设置内容:

server {
    listen 80;
    listen [::]:80;

    server_name webdav.youdomain.com;

    # 认证方式
    auth_basic              realm_name;
    # 存放认证用户名、密码文件(确认有对应权限)
    auth_basic_user_file    /data/www/webdav/.credentials.list;
    root /data/www/webdav/;

    # dav allowed method
    dav_methods     PUT DELETE MKCOL COPY MOVE;
    # Allow current scope perform specified DAV method
    dav_ext_methods PROPFIND OPTIONS;

    # In this folder, newly created folder or file is to have specified permission. If none is given, default is user:rw. If all or group permission is specified, user could be skipped
    dav_access      user:rw group:rw all:r;

    # MAX size of uploaded file, 0 mean unlimited
    client_max_body_size    0;

    # Allow autocreate folder here if necessary
    create_full_put_path    on;
}

创建用户

用户名

echo -n '$yourname:' | tee -a /data/www/webdav/.credentials.list

设置密码

openssl passwd -apr1 | tee -a /data/www/webdav/.credentials.list

重新加载nginx

# 检验配置文件
nginx -t

# 重启nginx
nginx -s reload

参考文章

vim使用

vim-key

官方文档:http://vimdoc.sourceforge.net/htmldoc/ 中文文档:http://vimcdoc.sourceforge.net/doc/

vim配置

vim 的配置文件分为系统配置文件 /etc/vimrc/usr/share/vim/ 和用户配置文件 ~/.vimrc~/.vim/

vim 的配置文件载入过程为:

  1. /etc/vimrc
  2. $HOME/.vim, $HOME/.vimrc
  3. $VIMRUNTIME/.vim,$VIMRUNTIME/.vimrc
  4. $HOME/.vim/after/
通过vim -V可以查看整个初始化过程。

vim常用的一些配置选项:

" .vimrc
" See: http://vimdoc.sourceforge.net/htmldoc/options.html for details
" For multi-byte character support (CJK support, for example):
" set fileencodings=ucs-bom,utf-8,cp936,big5,euc-jp,euc-kr,gb18030,latin1       
set tabstop=4       " Number of spaces that a <Tab> in the file counts for.

set shiftwidth=4    " Number of spaces to use for each step of (auto)indent.
 
set expandtab       " Use the appropriate number of spaces to insert a <Tab>.
                    " Spaces are used in indents with the '>' and '<' commands
                    " and when 'autoindent' is on. To insert a real tab when
                    " 'expandtab' is on, use CTRL-V <Tab>.
 
set smarttab        " When on, a <Tab> in front of a line inserts blanks
                    " according to 'shiftwidth'. 'tabstop' is used in other
                    " places. A <BS> will delete a 'shiftwidth' worth of space
                    " at the start of the line.
 
set showcmd         " Show (partial) command in status line.

set number          " Show line numbers.

set showmatch       " When a bracket is inserted, briefly jump to the matching
                    " one. The jump is only done if the match can be seen on the
                    " screen. The time to show the match can be set with
                    " 'matchtime'.
 
set hlsearch        " When there is a previous search pattern, highlight all
                    " its matches.
 
set incsearch       " While typing a search command, show immediately where the
                    " so far typed pattern matches.
 
set ignorecase      " Ignore case in search patterns.
 
set smartcase       " Override the 'ignorecase' option if the search pattern
                    " contains upper case characters.
 
set backspace=2     " Influences the working of <BS>, <Del>, CTRL-W
                    " and CTRL-U in Insert mode. This is a list of items,
                    " separated by commas. Each item allows a way to backspace
                    " over something.
 
set autoindent      " Copy indent from current line when starting a new line
                    " (typing <CR> in Insert mode or when using the "o" or "O"
                    " command).
 
set textwidth=79    " Maximum width of text that is being inserted. A longer
                    " line will be broken after white space to get this width.
 
set formatoptions=c,q,r,t " This is a sequence of letters which describes how
                    " automatic formatting is to be done.
                    "
                    " letter    meaning when present in 'formatoptions'
                    " ------    ---------------------------------------
                    " c         Auto-wrap comments using textwidth, inserting
                    "           the current comment leader automatically.
                    " q         Allow formatting of comments with "gq".
                    " r         Automatically insert the current comment leader
                    "           after hitting <Enter> in Insert mode. 
                    " t         Auto-wrap text using textwidth (does not apply
                    "           to comments)
 
set ruler           " Show the line and column number of the cursor position,
                    " separated by a comma.
 
set background=dark " When set to "dark", Vim will try to use colors that look
                    " good on a dark background. When set to "light", Vim will
                    " try to use colors that look good on a light background.
                    " Any other value is illegal.
 
set mouse=a         " Enable the use of the mouse.
 
filetype plugin indent on
syntax on

vim光标移动

常用移动:

h,j,k,l:分别对应光标⬅️,⬇️,⬆️,➡️。

w,b,$,^,gg,G:分别对应下一单词,前一单词,行末,行首,文件头,文件末尾。

- 阅读剩余部分 -

Debian Ubuntu下Redis源码安装

安装依赖

# 更新
apt-get update
# 安装依赖工具
apt-get install -y build-essential tcl pkg-config

安装Redis

工作目录未/tmp

cd /tmp
# 下载
wget https://download.redis.io/releases/redis-6.2.1.tar.gz
# 解压
tar zxf redis-6.2.1.tar.gz
# 进入源码文件目录
cd redis-6.2.1/
# 编译源码
make
# 测试
make test
# 测试通过后,进行安装redis
make install

make test 完成

image-20210326090559219

配置Redis

设置配置文件redis.conf

- 阅读剩余部分 -

Debian安装Certbot获取SSL证书

安装snapd

# 安装snapd
apt-get update
apt-get install snapd

# 安装 snapd core
snap install core
snap refresh core

通过snapd安装certbot

snap install --classic certbot

# 软链接
ln -s /snap/bin/certbot /usr/bin/certbot

如果遇到无法下载,可能需要翻墙,请给snap设置代理:

sudo snap set system proxy.http=http://127.0.0.1:1081
sudo snap set system proxy.https=http://127.0.0.1:1081

获取SSL证书

执行certbot certonly

certbot certonly -d "*.youdomain.com" --manual --preferred-challenges dns-01  --server https://acme-v02.api.letsencrypt.org/directory
root@docker00:/usr/bin# certbot certonly -d "*.youdomain.com" --manual --preferred-challenges dns-01  --server https://acme-v02.api.letsencrypt.org/directory
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): xxx@xxx.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Account registered.
Requesting a certificate for *.youdomain.com
Performing the following challenges:
dns-01 challenge for youdomain.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.youdomain.com with the following value:

<your_dns_txt_value>

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/youdomain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/youdomain.com/privkey.pem
   Your certificate will expire on 2021-07-01. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

- 阅读剩余部分 -

清除SVN版本控制

关于清除SVN版本控制,本人目前是采用如下方法:通过运行一个.bat文件,删除此目录下所有.svn的文件夹包括子目录下的.svn文件夹

简易版

新建一个clean.bat的文件,用记事本打开,写入:

@echo On @Rem 删除SVN版本控制目录 @PROMPT [Com]
@for /r . %%a in (.) do @if exist "%%a\.svn" rd /s /q "%%a\.svn" @Rem for /r . %%a in (.) do @if exist "%%a\.svn" @echo "%%a\.svn"
@echo Mission Completed. @pause

完整版

@echo off
echo ***********************************************************
echo 清除SVN版本信 息
echo ***********************************************************
:start
::启动过程,切换目录
:set pwd=%cd%
:cd %1
echo 工作目录是:& chdir
:input
::获取输入,根据输入进行处理
set source=:
set /p source=确定要清楚当前目录下的.svn信息吗?[Y/N/Q]
set "source=%source:"=%"
if "%source%"=="y" goto clean
if "%source%"=="Y" goto clean
if "%source%"=="n" goto noclean
if "%source%"=="N" goto noclean
if "%source%"=="q" goto end
if "%source%"=="Q" goto end
goto input
:clean
::主处理过程,执行清理工作
@echo on
@for /d /r %%c in (.svn) do @if exist %%c ( rd /s /q %%c & echo 删除目录%%c)
@echo off
echo "当前目录下的svn信息已清除"
goto end
:noclean
::分支过程,取消清理工作
echo "svn信息清楚操作已取消"
goto end
:end
::退出程序
cd "%pwd%"
pause

Debian jessie升级至buster

注意:不要跨版本升级,需要逐版本升级。

备份数据

升级前请做好备份操作,防止升级后相关服务不可用或数据无法正常读取。

  1. 程序代码
  2. 数据库文件
  3. 配置文件,如:Nginx、MySQL、PHP等
  4. 系统添加的用户和SSH Key等。
说明,下面操作建议使用root账号。

更新当前系统

apt-get update
apt-get upgrade
apt-get dist-upgrade

# 更新好后,建议重启下
reboot

升级至stretch

替换软件源

# 备份软件源
cp /etc/apt/sources.list /etc/apt/sources.list_bak

# 替换jessie为stretch
sed -i 's/jessie/stretch/g' /etc/apt/sources.list

- 阅读剩余部分 -

Lombok介绍

Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现 Lombok,开发人员可以节省构建诸如 hashCode() 和 equals() 这样的方法以及以往用来分类各种 accessor 和 mutator 的大量时间。

SpringToolSuite4安装Lombok

下载 lombok.jar

可以通过下面地址进行下载:

https://repo1.maven.org/maven2/org/projectlombok/lombok/1.18.18/lombok-1.18.18.jar

拷贝lombok.jar至STS目录

目录:/Applications/SpringToolSuite4.app/Contents/MacOS

接着需要将lombok-1.18.18.jar重命名为lombok.jar
(下面截图名称没有改,实际操作时,请将lombok-1.18.18.jar改为lombok.jar)

7c2yiab8hz4.png

在STS路径运行命令

cd /Applications/SpringToolSuite4.app/Contents/MacOS

java -jar lombok.jar

- 阅读剩余部分 -

Linux下压缩、解压war文件包。
首先系统中必须安装有JDK,如果没有请安装:

apt-get install default-jdk

jar 命令说明

jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目录] 文件名 ...

其中{ctxu}是jar命令的子命令,每次jar命令中只能包含c、t、x、u中的一个,不可同时存在,因为不能同时压缩与解压缩。

  • -c:创建新的 JAR 文件包
  • -t:列出 JAR 文件包的内容列表
  • -x:展开 JAR 文件包的指定文件或者所有文件
  • -u:更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中)
  • -f:定 JAR 文件名,通常这个参数是必须的。注意:在 f 之后要立即接档名,不要再加参数!
  • -m:指定需要包含的 MANIFEST 清单文件
  • -0:只存储,不压缩,这样产生的 JAR 文件包会比不用该参数产生的体积大,但速度更快
  • -M:不产生所有项的清单(MANIFEST〕文件,此参数会忽略 -m 参数
  • [jar-文件] :需要生成、查看、更新或者解开的 JAR 文件包,它是 -f 参数的附属参数
  • [-C 目录] :表示转到指定目录下去执行这个 jar 命令的操作。它相当于先使用 cd 命令转该目录下再执行不带 -C 参数的 jar 命令,它只能在创建和更新 JAR 文件包的时候可用
  • 文件名 ... :指定一个文件/目录列表,这些文件/目录就是要添加到 JAR 文件包中的文件/目录。如果指定了目录,那么 jar 命令打包的时候会自动把该目录中的所有文件和子目录打入包中。

实战:添加压缩包操作

jar -cvfM0 your_war.war ./

# 参数说明
# -c: 表示创建war包
# -v: 显示过程信息
# -f: 指定 JAR 文件名,通常这个参数是必须的
# -M: 不产生所有项的清单(MANIFEST〕文件,此参数会忽略 -m 参数
# -0: 这个是阿拉伯数字,只打包不压缩的意思

实战:解压war操作

jar -xvf your_war.war