刑事案件

刑事案件

刑事案件是指犯罪嫌疑人或者被告人被控涉嫌侵犯了《刑法》所保护的社会关系,国家为了追究犯罪嫌疑人或者被告人的刑事责任而进行立案侦察、审判并给予刑事制裁(如罚金、有期徒刑、死刑、剥夺政治权利等)的案件

Read More

立案

立案登记制

法院接到当事人提交的民事、行政起诉状时,对符合法定条件的起诉,应当登记立案;对当场不能判定是否符合起诉条件的,应当接收起诉材料,并出具注明收到日期的书面凭证。需要补充必要相关材料的,人民法院应当及时告知当事人。在补齐相关材料后,应当在七日内做出决定是否立案登记。

Read More

诉讼服务

主要的功能

当前,各地法院正在推行“诉讼服务中心”建设,其主要的功能有:
1、诉讼引导、法律宣传。由专人负责接待,根据来访人员的目的将其引导至相关区域,进行必要的诉讼指引和法律宣传。
2、登记立案、先行调解。接收案件材料,办理登记立案手续、核算诉讼费;为当事人、代理人、辩护人提供用于查询案件信息、查阅案卷的验证密码;对符合条件的当事人提供司法救助,根据规定办理诉讼费的减、缓、免除。确有需要的,为当事人提供上门立案、节假日预约立案服务。有条件的可以设置金融机构现场服务窗口,实现诉讼费等费用的现场缴纳。

设立调解工作室,由法官、专职人民调解员等进行诉前调解或立案调解,开展诉调对接工作。

Read More

log4jdbc 和 sqlfx

log4jdbc是我们公司sqlfx的基础构件,下面我来介绍一下他们之间的联系和作用

实现原理

net.sf.log4jdbc.DriverSpy这个类实现了JDBC的Driver接口,代理了原来数据库的驱动
而实现了SpyLogDelegator接口的策略通过配置文件log4jdbc.log4j2.properties打印日志,下面简述一下jdbc4log的配置

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 原来数据库的实际驱动名
log4jdbc.drivers=net.sourceforge.jtds.jdbc.Driver
# 将所有堆栈打出,这个会输出大量信息
log4jdbc.dump.fulldebugstacktrace=false
# 显示实际调用类的包前缀,jdbc4log会打印堆栈中第一个符合这个正则的调用类
log4jdbc.debug.stack.prefix=^com\.thunisoft\.np\.fy.*
# sql分割的最大行数
log4jdbc.dump.sql.maxlinelength=150
# 调用的日志策略,如果要使用sqlfx3.0需要使用蔡海滨编写的类
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
# 执行时间超过这个级别的日志将被输出为warn级别
log4jdbc.sqltiming.warn.threshold=100
# 执行时间超过这个级别的日志将被输出为error级别
log4jdbc.sqltiming.error.threshold=100

SQLFX

SQLFX是我们公司为了DBA方便的分析项目中不规范的sql而编写的软件,主要由两部分组成client和server

client的作用类似于ELK中的Filebeat,每天晚上定时(可在服务端配置)将log4jdbc日志压缩后发送到服务端

server则定时解析client发送上来的log4jdbc日志生成报告并发邮箱给DBA

IO

Java中的IO

File(文件特征与管理)

Java IO API中的FIle类可以让你访问底层文件系统,通过File类,你可以做到以下几点:

  • 检测文件是否存在
  • 读取文件长度
  • 重命名或移动文件
  • 删除文件
  • 检测某个路径是文件还是目录
  • 读取目录中的文件列表

请注意:File只能访问文件以及文件系统的元数据。如果你想读写文件内容,需要使用FileInputStream、FileOutputStream或者RandomAccessFile。如果你正在使用Java NIO,并且想使用完整的NIO解决方案,你会使用到java.nio.FileChannel(否则你也可以使用File)。

PPT

Read More

Lambda

Lambda表达式

Java为何需要Lambda

代码简洁,开发快速

减少了代码的重复,因此程序比较短,开发速度较快。

1
2
3
4
5
6
7
8
9
10
//Before Java 8:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8 ");
}
}).start();

//Java 8 way:
new Thread(() -> System.out.println("In Java8!"));

接近自然语言,易于理解

编程的自由度很高,可以写出很接近自然语言的代码。

1
2
3
4
5
6
7
8
9
10
11
//Prior Java 8 :
List features = Arrays.asList("Lambdas", "Default Method",
"Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}

//In Java 8:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API",
"Date and Time API");
features.forEach(n -> System.out.println(n));

易于”并发编程”

函数式编程不需要考虑”死锁”(deadlock),因为它不修改变量,所以根本不存在”锁”线程的问题。不必担心一个线程的数据,被另一个线程修改,所以可以很放心地把工作分摊到多个线程,部署”并发编程”(concurrency)。

假设一个业务场景:对于20元以上的商品,进行9折处理,最后得到这些商品的折后价格。

1
2
3
4
5
6
final BigDecimal totalOfDiscountedPrices = prices.stream()
.filter(price -> price.compareTo(BigDecimal.valueOf(20)) > 0)
.map(price -> price.multiply(BigDecimal.valueOf(0.9)))
.reduce(BigDecimal.ZERO,BigDecimal::add);

System.out.println("Total of discounted prices: " + totalOfDiscountedPrices);
1
2
3
4
5
6
final BigDecimal totalOfDiscountedPrices = prices.parallelStream()
.filter(price -> price.compareTo(BigDecimal.valueOf(20)) > 0)
.map(price -> price.multiply(BigDecimal.valueOf(0.9)))
.reduce(BigDecimal.ZERO,BigDecimal::add);

System.out.println("Total of discounted prices: " + totalOfDiscountedPrices);

Lambda的阴暗面

前面都是讲Lambda如何改变Java程序员的思维习惯,但Lambda确实也带来了困惑

JVM可以执行任何语言编写的代码,只要它们能编译成字节码,字节码自身是充分OO的,被设计成接近于Java语言,这意味着Java被编译成的字节码非常容易被重新组装。

但是如果不是Java语言,差距将越来越大,Scala源码和被编译成的字节码之间巨大差距是一个证明,编译器加入了大量合成类 方法和变量,以便让JVM按照语言自身特定语法和流程控制执行。

我们首先看看Java 6/7中的一个传统方法案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// simple check against empty strings
public static int check(String s) {
if (s.equals("")) {
throw new IllegalArgumentException();
}
return s.length();
}

//map names to lengths

List lengths = new ArrayList();

for (String name : Arrays.asList(args)) {
lengths.add(check(name));
}

如果一个空的字符串传入,这段代码将抛出错误,堆栈跟踪如下:

1
2
at LmbdaMain.check(LmbdaMain.java:19)
at LmbdaMain.main(LmbdaMain.java:34)

再看看Lambda的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Stream lengths = names.stream().map(name -> check(name));

at LmbdaMain.check(LmbdaMain.java:19)
at LmbdaMain.lambda$0(LmbdaMain.java:37)
at LmbdaMain$$Lambda$1/821270929.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.LongPipeline.reduce(LongPipeline.java:438)
at java.util.stream.LongPipeline.sum(LongPipeline.java:396)
at java.util.stream.ReferencePipeline.count(ReferencePipeline.java:526)
at LmbdaMain.main(LmbdaMain.java:39)

这非常类似Scala,出错栈信息太长,我们为代码的精简付出力代价,更精确的代码意味着更复杂的调试。

函数式接口

函数式接口(functional interface 也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。 @FunctionalInterface作为注解,这个注解是非必须的。

Lambda语法

包含三个部分

  1. 一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
  2. 一个箭头符号:->
  3. 方法体,可以是表达式和代码块,方法体函数式接口里面方法的实现,如果是代码块,则必须用{}来包裹起来,且需要一个return 返回值,但有个例外,若函数式接口里面方法返回值是void,则无需{}

总体看起来像这样

1
(parameters) -> expression 或者 (parameters) -> { statements; }

看一个完整的例子,方便理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 测试lambda表达式
*
* @author benhail
*/
public class TestLambda {

public static void runThreadUseLambda() {
//Runnable是一个函数接口,只包含了有个无参数的,返回void的run方法;
//所以lambda表达式左边没有参数,右边也没有return,只是单纯的打印一句话
new Thread(() ->System.out.println("lambda实现的线程")).start();
}

public static void runThreadUseInnerClass() {
//这种方式就不多讲了,以前旧版本比较常见的做法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("内部类实现的线程");
}
}).start();
}

public static void main(String[] args) {
TestLambda.runThreadUseLambda();
TestLambda.runThreadUseInnerClass();
}
}

可以看出,使用lambda表达式设计的代码会更加简洁,而且还可读。

方法引用

其实是lambda表达式的一个简化写法,所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是”::”,右边是相应的方法名。如下所示:

1
ObjectReference::methodName

一般方法的引用格式是

  1. 如果是静态方法,则是ClassName::methodName。如 Object ::equals
  2. 如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
  3. 构造函数.则是ClassName::new

再来看一个完整的例子,方便理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
*
* @author benhail
*/
public class TestMethodReference {

public static void main(String[] args) {

JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
frame.setVisible(true);

JButton button1 = new JButton("点我!");
JButton button2 = new JButton("也点我!");

frame.getContentPane().add(button1);
frame.getContentPane().add(button2);
//这里addActionListener方法的参数是ActionListener,是一个函数式接口
//使用lambda表达式方式
button1.addActionListener(e -> { System.out.println("这里是Lambda实现方式"); });
//使用方法引用方式
button2.addActionListener(TestMethodReference::doSomething);

}
/**
* 这里是函数式接口ActionListener的实现方法
* @param e
*/
public static void doSomething(ActionEvent e) {

System.out.println("这里是方法引用实现方式");

}
}

可以看出,doSomething方法就是lambda表达式的实现,这样的好处就是,如果你觉得lambda的方法体会很长,影响代码可读性,方法引用就是个解决办法

NoSuchMethodError

昨天答辩的时候考到NoSuchMethodError这个经常遇到的错误,居然没有回答上来,在此处记录一下
NoSuchMethodError按字面理解是方法找不到,这个一般不是真的没有这个方法,不然编译的时候就报错了,有可能是jar包的版本不对或者是冲突
下面是排查的思路
如果是在开发环境当然是用IDE调试,在生产环境一般是JDB调试,下面只说怎么在JDB调试
查看日志报错所在的行
使用 stop in 断点
执行eval 缺少方法的类.class.getProtectionDomain().getCodeSource()查看类所属的位置