一些记录

代码 & 开发

  • 启动springboot项目jar包时给main方法传入参数,根据参数执行不同的方法,可在main方法的形参String[] args中获取
java -jar xxx.jar hello java
    public static void main(String[] args) throws Exception {
        SpringApplication.run(VDSRVDSTATApplication.class, args);
        System.out.println(args[0]);
        System.out.println(args[1]);
    }
  • MVN打包跳过测试的命令:mvn package -DskipTests 或者直接点击IDEA中maven按钮“蓝色闪电”图标
  • 将仓库地址动态化放在 标签中,打包时可直接使用命令 mvn package -Drepository.url=XXX 设置仓库
  • 记一次打包失败:maven异常信息:No Sources to Compile。 原因:项目文件结构错误,java包和resources包没有放在main包下
  • 使用IDEA打包失败时,首先尝试删除配置的仓库中的依赖,如果不行在CMD中进入项目所在文件使用Maven命令打包:
    mvn clean package -Dmaven.test.skip=true -Dproject.version=0.0.1
  • 当服务需要进行HTTPS连接时,需要在服务启动时设置证书。可使用KeyTool生成假证书
  • 启动加载类:在Spring容器初始化完毕之后执行重写的 run 方法
    • 实现ApplicationRunner接口:run方法形参进行了封装是 ApplicationArguments args
    • 实现CommandLineRunner接口:run方法形参是字符串:String…args
    • 实现接口的类都需要添加 @Component 注解,且都可配合 @Order 注解指定执行顺序,数字越小优先级越高。
  • DateFormat不需要手动指定格式 'yyyy-HH-dd’等格式
		DateFormat format1 = DateFormat.getDateInstance();		//日期格式,精确到日
		DateFormat format2 = DateFormat.getDateTimeInstance();	//可以精确到时分秒  
		DateFormat format3 = DateFormat.getTimeInstance();		//只显示出时分秒
  • SimpleDateFormat通常只需要定义一次但线程不安全:在调用format方法时,多个线程会同时调用calender.setTime方法,导致time被别的线程修改。
    • 解决方式1:使用1.8的 DateTimeFormatter 配合 LocalDateTime ,即使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat
    • 解决方式2:使用ThreadLocal给每个线程提供独立的对象副本,解决线程安全问题。
  • 异常打印:直接使用 e.printStack() 时记录的堆栈信息太多,占用太多内存,且日志交错混合不易读
    • 解决方式:使用 logger.error(各类参数或者对象toString + “_” + e.getMessage(), e)
  • RateLimiter rateLimiter = RateLimiter.create(2); 定义一个令牌桶,每秒产生2个令牌,可用来实现每秒最多处理2个请求
  • String.format的使用 (%s 字符串类型 %d十进制整数 %f 浮点数)
    • 将十进制数转成8位的二进制数 0补位:String.format("%08d",Integer.valueOf(Integer.toBinaryString(value)))
    • 保留两位小数四舍五入:String.format("%.2f",value)
    • 正数或者负数添加符号:String.format(“%+d”,value)
  • Integer.valueOf(“num”, X) 把X进制转换为十进制 ; Integer.parseInt() 和 valueOf 作用类似:parseInt转为基本类型int ,valueOf转为Integer包装类型
  • 类中的序列化ID的作用:在反序列化的时候需要校验序列化ID是否一致,用于验证版本即判断对象内部是否修改。
    原理:java可以将一个对象序列化 经过远程传输,在另一端进行反序列化 重新得到原始数据;序列化id存在的意义 差不多等于锁的version,用于验证版本即判断对象内部是否修改。如果不显式地声明一个serialVersionUID,系统也会隐性地内置,声明出来方便出错时排查
  • 创建线程池时一定要指定ThreadFactory名字
public class ThreadPoolUtils {
    private ThreadPoolUtils() {}
    public static ThreadFactory getThreadFactory(String threadName) {
        return new VdsRvdThreadFactory(threadName);
    }
    private static class VdsRvdThreadFactory implements ThreadFactory {
        private final String preFix;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private VdsRvdThreadFactory(String preFix) {
            this.preFix = preFix;
        }
        @Override
        public Thread newThread(@NotNull Runnable r) {
            return new Thread(r, preFix + "-" + threadNumber.getAndIncrement());
        }
    }
}
  • 当需要重定向时:接口方法返回值类型是String、返回值前缀 “redirect:" ,所在类不能用@RestController修饰应该是@Controller
  • 定时任务实现方式
    • @Scheduled:不支持对“年”的设置,方便直接静态定义cron表达式
    • Quartz:支持设置”年“的周期,可动态配置cron表达式(可设置startAt/endAt)
    • ThreadPoolTaskScheduler:直接线程池开启周期任务,直接@Autowired可使用(也可自定义参数)

@Schedule使用的是spring的任务调度线程池ThreadPoolTaskScheduler,ThreadPoolTaskScheduler底层使用的为JDK自带的ScheduledExecutorService(其实现类为ScheduledThreadPoolExecutor)。执行任务时线程池默认只有一个线程,多个任务时串行。
实现多个任务之间并行执行:配置ThreadPoolTaskScheduler的@schedule+@Async
@Scheduled支持SpringEL表达式:@Scheduled(cron = “${schedule.cycle.history}”)

  • Windows关闭指定端口任务:任务管理器—性能—资源监视器(左下)—网络—找到端口对应的PID—返回到进程—右键展示PID—找到目标进程
  • 使用Gson转换成List时 使用 TypeToken:gson.fromJson(bean, new TypeToken<List>() {}.getType())
  • 读取本地 JSON 文件
    • 引入apache.commom包,直接 FileUtils.readFileToString(file,“UTF-8”)
    • 使用 InputStreamReader 和 StringBuffer: Reader reader = new InputStreamReader(new FileInputStream(new File(fileName)),“utf-8”)

组件和框架

  • Debug kafka消费服务时间过长导致kafka未及时提交commit,引起消息重发
  • 主表 left join on 从表时,如果 on 连接的字段存在主表:从表 = 1:N 时,连接查询的结果数量会大于主表数量,可在sql最后添加group by 来保证数据唯一
  • Jenkins打包build成功但部署失败,可以考虑是否磁盘已满或者网络问题。查看磁盘占用:df -h
  • Jenkins核心配置:Git仓库地址(需要认证)、build构建jarb包的命令(一般是执行Shell脚本)
  • kafka 命令:在apache-kafka_*\bin\windows目录下开启cmd窗口
在这里插入代码片
  • SQL Server的 CONVERT 函数可以用不同的格式显示日期/时间数据
  • SQL Server 正则表达式查询数字开头:select t.ID from tableName t where t.ID LIKE ‘[0-9]%’
  • 当数据库里的值可能为null时,注意在查询时添加 null 值判断 。避免使用包装类型封装时值为null,并引发操作数据时空指针的问题
    • MySQL:ifnull(字段,0)
    • SQL Server :isnull(字段,0)
  • SQL根据小时进行分组 group by DATE_FORMAT(start_time,’%H’) 或者 hour(beg_time)
  • 对 datetime 做日期范围判断时:date_format(DATE_TIME,’%Y-%m-%d’) BETWEEN ‘2020-01-01’ and ‘2020-12-31’
  • 按2小时进行分组,统计时间范围内的平均值
SELECT
	ROUND(avg(a.power),2) as cost,
	count(1) as noOfCars,
	hTime 
FROM
	(
	SELECT
		power,
		DATE_FORMAT(concat(date(beg_time), ' ', floor(HOUR(beg_time)/2) * 2 ),'%H') AS hTime 
	FROM
		`my_table` 
	WHERE  
		`status` in ('7','8') and beg_time between '2020-01-01 00:00:00' and '2020-12-01 23:00:00'  
	) a
GROUP BY hTime
  • JPA的@OneToMany 配合其属性cascade = CascadeType.ALL的使用
  • 使用 EntityManager 操作数据库时可以不给实体类配置@Entity、@ID等相关注解,但是查询结果只能是List<Object[]>
  • 使用 EntityManager 的 save 方法批量保存数据实际是 for 循环依次插入,效率低下,可使用 createNativeQuery 拼接 values(),(),()… 完成原生SQL的批量插入
  • SQLServer批量插入时存在的问题:最大容量规范中规定,每个用户定义函数的参数个数最大为2100,即values后面的参数占位符数量不能超过2100。且values后面接的数据条数不超过1000
  • 如果遇到异常:MappingException: No Dialect mapping for JDBC type: -157 。 是数据库中的字段类型无法对应,要指定配置文件中的hibernate方言Dialect
  • 截断表时如果出现存在关联外键异常,需要先删除从表关联的外键再截断主表
  • 使用 SpringCloud Config 配置中心时在配置中设置的 logfile 和启动jar包时设置的路径不一致,导致在预期路径中的日志打印终止到Fetching config from server…,检查发现服务正常运行,实际上后续的日志全部输出到配置中心指定的目录中
  • 搜索日志复杂关键字使用 NodePad++ 配合正则表达式
    • 匹配ab首cd尾: ab.*cd
    • 换行匹配ab首cd尾:ab.*?[\r\n.]*cd
  • logback.xml 规定日志最大容量、最大保存时间、实现按天分类压缩保存。注意配置的参数顺序会影响最终日志效果
  • 排查生产环境问题时可以给相关异常所在的类,提高日志打印等级 :
    标签中设置属性 additivity=“false”, 则子Logger只会在自己的appender里输出,不会在root的logger的appender里输出(可以狭义理解为不会在rootLogger中打印相关日志)
  • 一些Linux命令
    • 查看磁盘占用情况:df -h
    • 查看端口情况 : netstat -nptl | grep 8080
    • 打包 : tar -zcvf target.tar.gz source.txt
    • vim 修改jar包内文件(需要先安装 vim/zip/unzip 命令):vim target.file 进入终端输入“ / ” 加上文件名,再Enter进入查看页面,“ i ”进行编辑
    • 修改文件权限
	chown aa xx.txt :修改文件和文件夹的用户和用户组属性,把 xx.txt 的用户访问权限应用到aa作为所有者 
	chmod 777 xx.txt :修改文件和文件夹读写执行属性,把xx.txt文件修改为可写可读可执行  
	chmod -R 777 /a/b :修改 /a/b下所有的文件和文件夹及其子文件夹属性为可写可读可执行
* 同时复制多个文件
	cp /home/{file1,file2,file3,file4} /home/destination/
	cp /home/file1  /home/file2  /home/file3  /home/file4 /home/destination/
* 访问某个地址失败,首先尝试Ping IP(Ping域名可解析出IP) ,能Ping通再考虑端口是否开放,开放端口实际上是设置防火墙暴露TCP/UDP对应端口
* 查看某端口是否有数据发出、是否有数据发往某端口
   telnet 10.100.20.137 7780  # LINUX&WIN 查看10.100.20.137服务器的7780是否有数据发出
   tcpdump udp port 11011 # LINUX 是否有数据走UDP协议往端口11011发
   tcpdump tcp port 8888 # LINUX 是否有数据走TCP协议往端口8888发
* 找到正在运行的 jar 包位置
# 方式1
find / -name 'x.jar' # 直接全局搜索找出jar包位置
# 方式2
ps-ef | grep 'x.jar' # 找出正在运行的进程pid号
lsof -p pid | grep 'x.jar' # 根据pid找出使用这个进程的文件信息
* 列出最新的三个文件
ll -t logs/vd* |head -3
* 复制最新的三个文件到当前目录
ls -t logs/vd* |head -n 3 |xargs -i cp -r {} .
* 输出指定文件中关键字所在行
cat myfile.txt | grep 'keyword' -C 0	# -C num:匹配到搜索到的行以及上下各num行
  • 生成实体类:添加hibernate.cfg.xml \ mybatis-generator (还可生成mapper、实体类、接口)
  • IDEA快捷键转换大小写 crtl+shift+u ,shift+alt 可出现多处光标,Ctrl+Shift+Alt 可多处双击选择

设计

  • 配置文件:
    • bootstrap.yml配置spring cloud config 动态获取环境配置
    • application.properties 静态设置环境配置
    • 注意修改静态环境配置时也要同时修改config server 在 git 上的配置
  • RabbitMQ和WebSocket整合实现消息实时推送和实时页面数据刷新

概念

  • 测试代码覆盖率
  • 敏捷开发
  • 分析业务逻辑时绘制流程图、分析代码时注意数据的输入输出和处理单位、测试时提交简单报告
  • KeyCloak 组件封装实现了 oauth2 的认证授权以及网关功能
  • Java反编译工具:Java Decompiler

启动jar包的Shell脚本

#!/bin/bash 启动jar包的Shell脚本
# COMMAND LINE VARIABLES

# FIRST ARGUMENT deploy jar name
jarFileName=$1 # service-0.1.war

# SECOND ARGUMENT project folder
projectFolder=$2 # /opt/service/

# THIRD ARGUMENT log file name
logFileName=$3 # service.log

# FOURTH ARGUMENT profile name
profileName=$4 # dev

# FIFTH ARGUMENT stop file name
jarFileWildCardName=$5  # AID*.jar

## CONSTANT VARIABLES DECLARATION ##
dstLogFile=$projectFolder/$logFileName

#function to stop the existing service on the port
function stop() {
	echo " "
	echo "Stoping process for jar file $jarFileWildCardName"
	/usr/bin/kill -9 $(/usr/sbin/fuser $projectFolder/$jarFileWildCardName) &
	echo "Killed process using the file $projectFolder/$jarFileWildCardName"
	echo " "
}

#function to run the service on the port
function start() {
        echo "Application $projectFolder/$jarFileName starting with profile $profileName..."
        nohup java -Xmx1024M -Djavax.net.ssl.trustStorePassword="password" -Djavax.net.ssl.trustStore=/opt/service/truststore.jks -Djavax.net.ssl.trustStoreType=jks -Dspring.profiles.active=$profileName -Dlogging.file="$projectFolder/logs/$logFileName"  -jar $projectFolder/$jarFileName $> $dstLogFile 2>&1 &
        echo "Application $projectFolder/$jarFileName started with profile $profileName."
        echo " "
}

#function to change the jar file permissions
function changeFilePermission() {
	echo "Changing File Permission: chmod 775 $projectFolder/$jarFileName"
	chmod 775 $projectFolder/$jarFileName
	echo "Changing File Permission: chmod 775 $projectFolder/logs/$logFileName"
	chmod 775 $projectFolder/logs/$logFileName
#	echo "Changing the File Permission: chmod 775 $dstLogFile"
#	chmod 775 $dstLogFile
	echo " "
}

#function to sleep for 10 ms
function sleepCommand() {
	/usr/bin/sleep 10
}

# 1 - stop server on port ...
stop
sleepCommand
# 2 - change file permissions to run
changeFilePermission
sleepCommand
# 3 - start server
start
exit 0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值