【插件锦集】你在撸代码的时候,会用到这些吗?

前言

Eclipse/IDEA提供了一个可扩展插件的开发系统,这使得它们在运行系统之上可以实现各种功能。在我们日常开发中,合理的利用一些插件,可以大大提升我们的开发效率。以下只是本人在日常工作中的一些总结和常用插件的整理,希望能帮助到大家~

一、Lombok

Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些臃肿JAVA代码的工具,通过使用对应的注解,可以在编译代码的时候生成对应的方法,使我们的代码看起来更加的整洁简练。比如实体类中的getter,setter之类的一系列方法。

1.Lombok安装

1.1 IDEA安装Lombok

1.在线安装:菜单File->Settings->Plugins->Browse
repositories…->搜索框内搜索lombok->得到结果Lombok plugin,下载(install)并重新启动就ok了。
2.离线安装:首先要下载lombok.jar,下载网址:lombok.jar,然后菜单File->Settings->Plugins->Install
plug from disk->选择你下载的lombok.jar,然后apply->OK,重启就ok了。

1.2 Eclipse安装Lombok

(1) 首先在下载lombok.jar,并打开myeclipse或eclipse的安装目录,找到myeclipse.ini/eclipse.ini所在的文件目录。

(2)打开myeclipse.ini/eclipse.ini,在配置的最后加上

-javaagent:lombok.jar

-Xbootclasspath/a:lombok.jar

(3)保存后重启myeclipse或eclipse。

2. Java maven项目中使用lombok,添加Lombok依赖

<dependency>

          <groupId>org.projectlombok</groupId>

          <artifactId>lombok</artifactId>

          <version>1.16.18</version>

          <scope>provided</scope>

 </dependency>	

Lombok的scope=provided,说明它只在编译阶段生效,不需要打入包中。事实正是如此,Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件。

3. Lombok注解的使用

@Getter/@Setter: 作用类上,生成所有成员变量的getter/setter方法;作用于成员变量上,生成该成员变量的getter/setter方法。可以设定访问权限及是否懒加载等。

@ToString:作用于类,覆盖默认的toString()方法,可以通过of属性限定显示某些字段,通过exclude属性排除某些字段。

@EqualsAndHashCode:作用于类,覆盖默认的equals和hashCode

@NonNull:主要作用于成员变量和参数中,标识不能为空,否则抛出空指针异常。

@NoArgsConstructor, @RequiredArgsConstructor,
@AllArgsConstructor:作用于类上,用于生成构造函数。有staticName、access等属性。

staticName属性一旦设定,将采用静态方法的方式生成实例,access属性可以限定访问权限。

@NoArgsConstructor:生成无参构造器;

@RequiredArgsConstructor:生成包含final和@NonNull注解的成员变量的构造器;

@AllArgsConstructor:生成全参构造器

@Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor

@Builder:作用于类上,将类转变为建造者模式

@Log:作用于类上,生成日志变量。针对不同的日志实现产品,有不同的注解:

package com.kaplan.pojo;

import lombok.*;

import lombok.extern.log4j.Log4j;
//默认生成的方法是 public 的,如果要修改方法修饰符可以设置 AccessLevel 的值
@ToString(of = {
    
    "name","age"},exclude = {
    
    "age"})
@Getter(access = AccessLevel.PROTECTED)
@Setter(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class TestDemo {
    
    

@NonNull
private String name;
private int age ;
private String email;
private String address; 

@Getter
@Setter 
private String dob;
}

以上只是介绍了POJO类的常用注解,Lombok的注解包括但不限于此,还有很多注解在这里就不一一介绍了,各位感兴趣的可以私下了解

二、FindBugs

随着项目越做越大,时间越来越长,代码的审查工作是个巨大的负担,我们每天的JAVA代码在提交SVN之前都要经过FindBugs检查。那么说到底FindBugs到底是什么呢?FindBugs是一个静态分析工具,它检查类或者JAR文件,将字节码与一组缺陷模式进行对比以发现问题。Findbugs自带检测器,其中有60余种Bad
practice,80余种Correctness,1种 Internationalization,12种Malicious code
vulnerability,27种Multithreaded
correctness,23种Performance,43种Dodgy。这里面有个人性化的设置:我们可以自己配置检查规则(做哪些检查,不做哪些检查),也可以自己来实现独有的校验规则(用户自定义特定的bug模式需要继承它的接口,编写自己的校验类,属于高级技巧)。FindBugs是检查java字节码,也就是*.class文件。

1.代码检测的必要性
换句话说,我们为什么要进行代码检测?由于某种代码写法虽然没有语法错误,但是可能存在错误,比如会导致线程死锁等等潜在的Bug,这些都是错误列表要检查的,静态检查的可操作方式:

1.1 代码走查:(上家公司采用方式)  
程序员之间可以隔一定的时间抽取代码进行走查。

走查的时候根据汇总报告,把这些经验汇成列表,作为下次代码走查的依据。

该方式的特点是,手工、多人讨论、操作简单,但是效率会比较低。
2.2 代码扫描

使用软件对我们的代码进行扫描,查找出潜在的问题。现在有许多商业的工具能够进行扫描,比如Parasoft JTest、Software
Analyzer、pclint、Findbugs等工具.软件扫描的特点是,机器扫描、效率高,但是不够灵活,不利于扩展。

2.FindBugs安装

2.1 IDEA安装FindBugs

(1)在线安装:菜单File->Settings->Plugins->Browse
repositories…->搜索框内搜索FindBugs->得到结果FindBugs-IDEA,下载(install)并重新启动就ok了。

(2)离线安装:首先要下载FindBugs压缩包,下载网址:FindBugs压缩包,然后菜单File->Settings->Plugins->Install
plug from disk->选择你下载的FindBugs压缩包(因为包含jar包较多),然后apply->OK,重启就ok了。

2.2 eclipse安装FindBugs

(1)在线安装:
eclipse:Help->Install New
Software->Add->Name:findbugs,Location:http://findbugs.cs.umd.edu/eclipse

然后点击OK,选择FindBugs,然后可以一路Next到Finish,重启eclipse,选中任意项目,右击鼠标,如弹出的框中出现findbugs,则表示安装成功或打开eclipse->window->Preferences,搜索关键字findbugs,如果能找到配置项,那么表示安装成功。

(2)离线安装:

首先需要下载你所适用的FindBugs的压缩包:下载网址:适用eclipse的FindBugs,然后打开eclipse的安装目录,找到dropins或plugins(任意一个),将压缩包放入直接解压到此目录,然后启动eclipse,选中任意项目,右击鼠标,如弹出的框中出现findbugs,则安装成功或打开eclipse->window->Preferences,搜索关键字findbugs,如果能找到配置项,那么表示安装成功。

(3)若是点击项目Find Bugs->Find Bugs后没有出现Bug
Explorer,则Window->ShowView->Other->FindBugs->Bug Explorer。找出的bug有3中颜色,
黑色的臭虫标志是分类, 红色的臭虫表示严重bug发现后必须修改代码,橘黄色的臭虫表示潜在警告性bug 。

3.IDEA中使用FindBugs

选中项目,包,类,右击鼠标,选择FindBugs, Analyze Selected File(s)单个文件,Analyze Package(s) Files包下文件,Analyze Module Files整个module,Analyze Project Files整个工程

4. 一些常见的错误:以下是复制,修改别人的,为了以后方便自己学习,请见谅

4.1 Bad practice 主要是代码中的一些坏习惯,没有按Java规范来
Class names should start with an upper case letter 主要包括类名的命名,以大写字母开头
Method names should start with a lower case letter 方法名以小写字母开头
Field names should start with a lower case letter 字段名以小写字母开头
equals()method does not check for null argument equals()方法应该检查非空
Class defines equals() and uses Object.hashCode() 一个类覆写了equals方法,没有覆写hashCode方法,使用了Object对象的hashCode方法
Method ignores exceptional return value 方法忽略返回值的异常信息
Equals method should not assume anything about the type of its argument equals(Object o)方法不能对参数o的类型做任何的假设。比较此对象与指定的对象。当且仅当该参数不为 null,并且是表示与此对象相同的类型的对象时,结果才为 true。
Comparison of String objects using == or != 用==或者!=去比较String类型的对象
Method might ignore exception 方法可能忽略异常
Method invokes System.exit() 在方法中调用System.exit(…)语句,考虑用RuntimeException来代替
Method ignores result of InputStream.read() InputStream.read方法忽略返回的多个字符,如果对结果没有检查就没法正确处理用户读取少量字符请求的情况。

4.2 Dodgy code 糟糕的代码(一般是没有按Java规范来写代码,或语句不全,类型转换,多余的语句,判断)
Switch statement found where default case is missing Switch没有默认情况下执行的case语句
Switch statement found where one case falls through to the next case Switch语句中一个分支执行后又执行了下一个分支。通常case后面要跟break 或者return语句来跳出。
Dead store to local variable 该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。
Write to static field from instance method 在实例方法写入静态字段
Redundant nullcheck of value known to be non-null 方法中对不为空的值进行为空的判断。
Method uses the same code for two branches 此方法使用相同的代码,以实现两个有条件的分支。检查以确保这是不是一个编码错误
Exception is caught when Exception is not thrown 在try/catch块中捕获异常,但是异常没有在try语句中抛出而RuntimeException又没有明确的被捕获
Integral division result cast to double or float 整形数除法强制转换为double或者float类型。
Possible null pointer dereference due to return value of called method 方法的返回值没有进行是否为空的检查就重新赋值,这样可能会出现空指针异常。
Useless object created 对象创建了并没有用
Unread public/protected field 没有用到的字段

4.3 Internationalization 关于代码国际化相关方面的
Consider using Locale parameterized version of invoked method
使用平台默认的编码格式对字符串进行大小写转换,这可能导致国际字符的转换不当。使用以下方式对字符进行转换

4.4 Performance 关于代码性能相关方面的(多为声明了无用的属性)
Boxing/unboxing to parse a primitive 类型转换 比如字符串转换成int 应该使用Integer.parseInt(“”) 代替Integer.valueOf(“”)
Method concatenates string using + in aloop
每次循环里的字符串+连接,都会新产生一个string对象,在java中,新建一个对象的代价是很昂贵的,特别是在循环语句中,效率较低
解决办法:使用StringBuffer或者StringBuilder重用对象。
Private method is never called 私有方法没有被调用
Explicit garbage collection;extremely dubious except in benchmarking code
在代码中显式的调用垃圾回收命名,这样做并不能起作用。在过去,有人在关闭操作或者finalize方法中调用垃圾回收方法导致了很多的性能浪费。这样大规模回收对象时会造成处理器运行缓慢。
Unread field:should this field be static? 没有用到的static 字段
should be a static inner class 此内部类应该使用static修饰

4.5 Experimental
Method may fail to clean up stream or resource on checked exception
这种方法可能无法清除(关闭,处置)一个流,数据库对象,或其他资源需要一个明确的清理行动
解决方法:流的关闭都写在finally里面

4.6 Malicious code vulnerability 关于恶意破坏代码相关方面的(主要是一些属性,建议改为private并为其提供get,set方法 )
May expose internal representation by incorporating reference to mutable object
此代码把外部可变对象引用存储到对象的内部表示。如果实例受到不信任的代码的访问和没有检查的变化危及对象和重要属性的安全。存储一个对象的副本,在很多情况下是更好的办法。
Field isn’t final but should be 此字段前应该加final
Field isn’t final and can’t be protected from malicious code 此字段前应该加final
Field should be package protected
一个静态字段是可以被恶意代码或其他的包访问修改。可以把这种类型的字段声明为final类型的以防止这种错误。

4.7 Multithreaded correctness 关于代码正确性相关方面的
Static DateFormat DateFormat 在多线程中本身就是不安全的,如果在线程范围中共享一个DateFormat的实例而不使用一个同步的方法在应用中就会出现一些奇怪的行为。
Call to static DateFormat DateFormats多线程使用本事就是不安全的,改进方法:需要创建多实例或线程同步

4.8 Correctness 关于代码正确性相关方面的
Nullcheck of value previously dereferenced 此代码之前废弃null值检查。解决办法 进行null检查
Possible null pointer dereference 可能为null
Null pointer dereference 对象赋为null值后 没有被重新赋值
Possible null pointer dereference in method on exception path 在异常null值处理分支调用的方法上,可能存在对象去除引用操作
value is null and guaranteed to be dereferenced on exception path exception分支上,存在引用一个null对象的方法,引发空指针异常。
Self comparison of value with itself 方法中对一个局部变量自身进行比较运算,并可说明错误或逻辑错误。请确保您是比较正确的事情。

An apparent infinite recursive loop 明显的无限迭代循环,将导致堆栈溢出.

三、PageHelpher

在使用java Spring开发的时候,Mybatis算是对数据库操作的利器了。但是在处理分页的时候,我们习惯的分页是用limit来分页,成本比较高。PageHelper物理分页 (官网点我丫)对单表分页或者整体结果集分页是比较方便的。

1、引入PageHelper的Maven依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>

2.配置applicationContext.xml文件
在spring的sqlsessionfactory的bean中增加一个分页拦截器属性

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="plugins">
		<array>
			<bean class="com.github.pagehelper.PageInterceptor">
				<property name="properties">
					<value>
						<!-- 这里设定你的数据库类型 -->
						helperDialect = mysql
					</value>
				</property>
			</bean>
		</array>
	</property>
</bean>

3.调用PageHelper的方法

在service方法中调用PageHelper的静态方法startPage(注意一定要在实际查询之前调用该方法),传入需要查询的页码pageNum和每页显示的条数pageSize,返回PageHelper插件提供的PageInfo对象。即可自动完成数据库的物理分页,无须在sql语句上手动加limit子句

@Override
public PageInfo<Student> testPage(Integer pageNum, Integer pageSize) {
    
    
	PageHelper.startPage(pageNum,pageSize);
	List<Student> studentList = studentMapper.selectAll();

	PageInfo pageInfo = new PageInfo(studentList);
	return pageInfo;
}

4.大数据量PageHelper产生的效率问题

在开发过程中,我们少不了用分页,正常情况下PageHelper这个插件分页还是很方便的,但是当项目数据量大的时候,就会感觉到分页插件查询速度慢。。后面对比发现是limit的偏移量导致的sql效率低下

写的sql原本是这样的:

select * from school where age >= 18;

最后执行的时候是这样的:

select * from (select * from school where age >= 18)where limit 100,10;

supportMethodsArguments在官方的解释如下:

  1. supportMethodsArguments:支持通过 Mapper接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和ArgumentsObjTest。
  2. params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置
    pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值,默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。

什么意思呢?用pageHelper插件的时候,只要传递到Mapper的参数中包含了pageNum和pageSize它就会自动追加countSql进行分页处理。**也就是说,它会拦截我们写的sql语句,自己重新包装一层,在后面添加limit。**这在数据量小的时候当然是没有什么问题的,但是一旦数据量过大,那分页到后面数据时候limti的偏移量必然增大 ,不可避免的,查询的时间就会呈几何倍数增长。

解决方法

方案1: 修改配置

检查了下pageHelper配置,发现配置如下

pagehelper:
	 helperDialect: mysql
	 reasonable: true
	 supportMethodsArguments: true  ###注意这一条

最简单的做法就是设置supportMethodsArguments属性为false,第二个做法就是修改接口

public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count) {
    
     
	return startPage(pageNum, pageSize, count, null, null); 
}

取消掉之前的注释并改写为

PageHelper.startPage(query.getPageNum(),query.getPageSize(),false);

方案2: 修改count语句

查询API发现PageHelper其实是支持自动检测count语句的。

增加手写 count 查询支持
增加 countSuffix count 查询后缀配置参数,该参数是针对 PageInterceptor配置的,默认值为 _COUNT。 分页插件会优先通过当前查询的 msId + countSuffix 查找手写的分页查询。如果存在就使用手写的 count 查询,如果不存在,仍然使用之前的方式自动创建 count 查询。

什么意思呢?比如你的分页查询接口名为getAllUser,只要将自己写的count语句命名为getAllUser_COUNT,PageHelper就会使用我们自己写的count语句,不再自动生成。

 <select id="getAllUser_COUNT" resultType="Long">

 select max(id) from student
 </select>

方案3: 修改表引擎

直接修改表引擎,如果默认是InnoDB,由于该引擎不保存表的具体行数,在数据量上百万后统计基本在1秒以上;

修改为MyISAM;但是分页查询的时候同样是在100万以后的记录查会非常慢;

四、Regex Util

Regex Util是一款正则表达式测试插件,它能够高亮显示正则表达式语法、括号匹配、错误检测。能够提醒正则表达式的功能详细描述等。

官方网站:http://myregexp.com/eclipsePlugin.html
Eclipse在线安装URL:http://regexutil.sourceforge.net/update/

楼主目前用到的插件主要是这些,后续还会补充,欢迎大家提出问题互相学习~

猜你喜欢

转载自blog.csdn.net/weixin_42777004/article/details/108646543