javaweb
javaweb copied to clipboard
http://www1350.github.io/
在mvc层经常会遇到这样的一种情况,是否使用DTO(数据传输对象),还是直接使用model返回?其实这都可以,前者叫封闭领域模型风格,后者叫开放领域模型风格。因为前者可以排除一些不需要返回的字段但是需要进行拷贝,后者就不需要经过处理。另外,都会遭遇到一种情况:如性别在后台是通过0和1,但是需要返回前端男或者女。这种情况可以使用数据字典做一个良好的处理,这个这里不谈。 MapStruct可以很好的处理封闭领域模型风格的model到DTO的拷贝。 https://github.com/mapstruct/mapstruct ``` public class CycleAvoidingMappingContext { private Map knownInstances = new IdentityHashMap(); @BeforeMapping public T getMappedInstance(Object source, @TargetType Class targetType) { return (T) knownInstances.get( source ); } @BeforeMapping...
## 阻塞 假设有一个管道,进程A为管道的写入方,B为管道的读出方。 假设一开始内核缓冲区是空的,B作为读出方,被阻塞着。然后首先A往管道写入,这时候内核缓冲区由空的状态变到非空状态,内核就会产生一个事件告诉B该醒来了,这个事件姑且称之为“**缓冲区非空**”。 但是“缓冲区非空”事件通知B后,B却还没有读出数据;且内核许诺了不能把写入管道中的数据丢掉这个时候,A写入的数据会滞留在内核缓冲区中,如果内核也缓冲区满了,B仍未开始读数据,最终内核缓冲区会被填满,这个时候会产生一个I/O事件,告诉进程A,你该等等(阻塞)了,我们把这个事件定义为“**缓冲区满**”。 假设后来B终于开始读数据了,于是内核的缓冲区空了出来,这时候内核会告诉A,内核缓冲区有空位了,你可以从长眠中醒来了,继续写数据了,我们把这个事件叫做“**缓冲区非满**” 也许事件Y1已经通知了A,但是A也没有数据写入了,而B继续读出数据,知道内核缓冲区空了。这个时候内核就告诉B,你需要阻塞了!,我们把这个时间定为“**缓冲区空**”。 阻塞I/O模式下,一个线程只能处理一个流的I/O事件。如果想要同时处理多个流,要么多进程(fork),要么多线程(pthread_create) ## 非阻塞忙轮询的I/O方式 ``` while true { for i in stream[]; { if i has data read until unavailable } } ``` 如果所有的流都没有数据,那么只会白白浪费CPU...
VPN pptp 连接:vpn.sopoy.com 帐号:free 密码:free 月流量:500G shadowsock翻墙 连接:vpn.sopoy.com 密码:free 加密方式:rc4-md5 端口:443 月流量:500G shadowsock翻墙 连接:mars.sopoy.com 密码:获取密码请入群:361362936 加密方式:aes-256-cfb 端口:443 月流量:100G - [shadowsocks](https://github.com/shadowsocks/shadowsocks-windows/releases) [ios](https://github.com/shadowsocks/ShadowsocksX-NG/releases/) https://github.com/Alvin9999/new-pac/wiki/ss%E5%85%8D%E8%B4%B9%E8%B4%A6%E5%8F%B7
SPI指的是Service Provider Interface,服务提供接口 我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。 为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。Java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。 当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader. ``` package spi; public interface Search { public void search(); } package spi; public class FileSearch implements Search { @Override public void...
cglib(字节码生成库)是一个生成和转化Java字节码的高级api。被使用在AOP上。在实现内部,CGLIB库使用了ASM这一个轻量但高性能的字节码操作框架来转化字节码,产生新类 Enhancer是cglib一个很重要的类。Enhancer动态创建一个子类。 Enhancer只能在java字节码级别构造方法,但是不能构造static或者final类。 ``` public Object createProxy(Class targetClass) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(targetClass); enhancer.setCallback(NoOp.INSTANCE); return enhancer.create(); } ``` 在例子中,默认的无参构造方法被使用来创建目标对象。如果你希望CGLIB创建一个有参数的实例,你应该使用net.sf.cglib.proxy.Enhancer.create(Class[], Object[])。NoOp是内置的一个类,可以看下源码 ``` public interface NoOp extends Callback { NoOp...
java字节码被存储在一个叫做类文件的二进制文件。CtClass的对象代表一个类文件。ClassPool是存放CtClass的hash列表,用类名做key,如果CtClass没发现get()会读取一个class建造一个新的类记录到hash表并返回。 ``` ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("test.Rectangle"); cc.setSuperclass(pool.get("test.Point")); byte[] b = cc.toBytecode(); Class aClass = cc.toClass(); cc.writeFile(); ``` 如果系统使用多个类装载器,getDefault()只能搜索当前jvm的路径,可能加载不到对象。 ``` pool.insertClassPath(new ClassClassPath(this.getClass())); ClassPool pool = ClassPool.getDefault(); pool.insertClassPath("/usr/local/javalib");...
java.lang.IllegalStateException: No MethodInvocation found: Check that an AOP invocation is in progress, and that the ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that advices with order HIGHEST_PRECEDENCE will...
1.总量限流 ``` @Slf4j @WebFilter(urlPatterns = "/*", filterName = "requestFilter") public class LimitFilter implements Filter { private static final int MAX_COUNT = 20000; private final static AtomicInteger filterCount = new AtomicInteger(0);...
``` #!/bin/bash if [ $# -eq 0 ];then echo "please enter java pid" exit -1 fi pid=$1 jstack_cmd="" if [[ $JAVA_HOME != "" ]]; then jstack_cmd="$JAVA_HOME/bin/jstack" else r=`which jstack 2>/dev/null`...
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) - corePoolSize: 线程池维护线程的最少数量 - maximumPoolSize:线程池维护线程的最大数量 - keepAliveTime: 线程池维护线程所允许的空闲时间 - unit: 线程池维护线程所允许的空闲时间的单位 - workQueue: 线程池所使用的缓冲队列 - handler:...