/** * A {@link Bootstrap} that makes it easy to bootstrap a {@link Channel} to use * for clients. 引导程序Bootstrap使客户端很容易启动一个通道。 * * The {@link #bind()} methods are useful in combination with connectionless transports such as datagram (UDP). * For regular TCP connections, please use the provided {@link #connect()} methods.
绑定方法#bind对无连接的报文通信UDP非常有用。对于Socket连接TCP,可以使用#connect连接方法。 */ public class Bootstrap extends AbstractBootstrap {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
private static final AddressResolverGroup> DEFAULT_RESOLVER = DefaultAddressResolverGroup.INSTANCE; //引导配置 private final BootstrapConfig config = new BootstrapConfig(this);
/** * Connect a {@link Channel} to the remote peer. */ public ChannelFuture connect(String inetHost, int inetPort) { return connect(InetSocketAddress.createUnresolved(inetHost, inetPort)); }
/** * Connect a {@link Channel} to the remote peer. */ public ChannelFuture connect(InetAddress inetHost, int inetPort) { return connect(new InetSocketAddress(inetHost, inetPort)); }
/** * Connect a {@link Channel} to the remote peer. */ public ChannelFuture connect(SocketAddress remoteAddress) { if (remoteAddress == null) { throw new NullPointerException("remoteAddress"); }
/** * Connect a {@link Channel} to the remote peer. */ public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { if (remoteAddress == null) { throw new NullPointerException("remoteAddress"); } validate(); return doResolveAndConnect(remoteAddress, localAddress); }
从上面来了,连接远端socket地址,实际委托给doResolveAndConnect方法:
/** * @see #connect() 连接操作 */ private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) { //初始化通道,并注册通道到事件循环组 final ChannelFuture regFuture = initAndRegister(); final Channel channel = regFuture.channel();
if (regFuture.isDone()) { if (!regFuture.isSuccess()) { return regFuture; } //初始化成功,则委托给doResolveAndConnect0完成实际连接操作 return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise()); } else { //如果初始化和注册工作没有完成,添加任务结果监听器,待完成时,更新注册状态,完成实际连接操作 // Registration future is almost always fulfilled already, but just in case it's not. final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); regFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { // Directly obtain the cause and do a null check so we only need one volatile read in case of a // failure. Throwable cause = future.cause(); if (cause != null) { // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an // IllegalStateException once we try to access the EventLoop of the Channel. promise.setFailure(cause); } else { // Registration was successful, so set the correct executor to use. // See https://github.com/netty/netty/issues/2586 promise.registered(); doResolveAndConnect0(channel, remoteAddress, localAddress, promise); } } }); return promise; } }
final Map, Object> attrs = attrs0(); synchronized (attrs) { for (Entry, Object> e: attrs.entrySet()) { channel.attr((AttributeKey
//实际连接操作 private ChannelFuture doResolveAndConnect0(final Channel channel, SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { try { final EventLoop eventLoop = channel.eventLoop(); final AddressResolver resolver = this.resolver.getResolver(eventLoop); if (!resolver.isSupported(remoteAddress) || resolver.isResolved(remoteAddress)) { // Resolver has no idea about what to do with the specified remote address or it's resolved already. //如果地址解析器不知道如何应对远端地址,或已经解决则连接远端地址,完成实际连接 doConnect(remoteAddress, localAddress, promise); return promise; }
final Future resolveFuture = resolver.resolve(remoteAddress);
if (resolveFuture.isDone()) {
final Throwable resolveFailureCause = resolveFuture.cause();
if (resolveFailureCause != null) { // Failed to resolve immediately channel.close(); promise.setFailure(resolveFailureCause); } else { //远端地址解析完毕,并支持,完成实际连接 // Succeeded to resolve immediately; cached? (or did a blocking lookup) doConnect(resolveFuture.getNow(), localAddress, promise); } return promise; } //如果地址解析任务没有完成,添加监听器,待任务完成时,完成连接操作 // Wait until the name resolution is finished. resolveFuture.addListener(new FutureListener() { @Override public void operationComplete(Future future) throws Exception { if (future.cause() != null) { channel.close(); promise.setFailure(future.cause()); } else { doConnect(future.getNow(), localAddress, promise); } } }); } catch (Throwable cause) { promise.tryFailure(cause); } return promise; }
//连接远端地址 private static void doConnect( final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise connectPromise) {
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up // the pipeline in its channelRegistered() implementation. final Channel channel = connectPromise.channel(); //创建一个任务线程完成实际连接远端地址操作,实际委托给通道的连接方法,任务线程交由通道所在的事件循环去执行 channel.eventLoop().execute(new Runnable() { @Override public void run() { if (localAddress == null) { channel.connect(remoteAddress, connectPromise); } else { //实际委托给通道的连接方法 channel.connect(remoteAddress, localAddress, connectPromise); } connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } }); }
//配置远端socket地址 /** * The {@link SocketAddress} to connect to once the {@link #connect()} method * is called. */ public Bootstrap remoteAddress(SocketAddress remoteAddress) { this.remoteAddress = remoteAddress; return this; }
/** * @see #remoteAddress(SocketAddress) */ public Bootstrap remoteAddress(String inetHost, int inetPort) { remoteAddress = InetSocketAddress.createUnresolved(inetHost, inetPort); return this; }
/** * @see #remoteAddress(SocketAddress) */ public Bootstrap remoteAddress(InetAddress inetHost, int inetPort) { remoteAddress = new InetSocketAddress(inetHost, inetPort); return this; }
/** * Connect a {@link Channel} to the remote peer. 连接远端peer通道 */ public ChannelFuture connect() { validate(); SocketAddress remoteAddress = this.remoteAddress; if (remoteAddress == null) { throw new IllegalStateException("remoteAddress not set"); } return doResolveAndConnect(remoteAddress, config.localAddress()); }
//验证引导配置是否有效 @Override public Bootstrap validate() { super.validate(); if (config.handler() == null) { throw new IllegalStateException("handler not set"); } return this; } //克隆配置 @Override @SuppressWarnings("CloneDoesntCallSuperClone") public Bootstrap clone() { return new Bootstrap(this); }
/** * Returns a deep clone of this bootstrap which has the identical configuration except that it uses * the given {@link EventLoopGroup}. This method is useful when making multiple {@link Channel}s with similar * settings. */ public Bootstrap clone(EventLoopGroup group) { Bootstrap bs = new Bootstrap(this); bs.group = group; return bs; } //获取引导配置 @Override public final BootstrapConfig config() { return config; } //获取远端socket地址 final SocketAddress remoteAddress() { return remoteAddress; } //获取地址解析组 final AddressResolverGroup> resolver() { return resolver; }
/** * A {@link AddressResolverGroup} of {@link DefaultNameResolver}s. */ @UnstableApi public final class DefaultAddressResolverGroup extends AddressResolverGroup {
public static final DefaultAddressResolverGroup INSTANCE = new DefaultAddressResolverGroup(); private DefaultAddressResolverGroup() { } //创建地址解析器 @Override protected AddressResolver newResolver(EventExecutor executor) throws Exception { return new DefaultNameResolver(executor).asAddressResolver(); } }
/** * A {@link InetNameResolver} that resolves using JDK's built-in domain name lookup mechanism. * Note that this resolver performs a blocking name lookup from the caller thread. */ @UnstableApi public class DefaultNameResolver extends InetNameResolver {
public DefaultNameResolver(EventExecutor executor) { super(executor); }
/** * A skeletal {@link NameResolver} implementation that resolves {@link InetAddress}. */ @UnstableApi public abstract class InetNameResolver extends SimpleNameResolver { private volatile AddressResolver addressResolver;//地址解析器
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(String)} */ protected InetNameResolver(EventExecutor executor) { super(executor); }
/** * Return a {@link AddressResolver} that will use this name resolver underneath. * It's cached internally, so the same instance is always returned. 这个方法时我们要找的 */ public AddressResolver asAddressResolver() { AddressResolver result = addressResolver; if (result == null) { synchronized (this) { result = addressResolver; if (result == null) { //如果内部地址解析器为空,则创建一个socket地址解析器 addressResolver = result = new InetSocketAddressResolver(executor(), this); } } } return result; } }
/** * A skeletal {@link NameResolver} implementation. */ @UnstableApi public abstract class SimpleNameResolver implements NameResolver {
private final EventExecutor executor;
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(String)} */ protected SimpleNameResolver(EventExecutor executor) { this.executor = checkNotNull(executor, "executor"); }
/** * Returns the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(String)}. */ protected EventExecutor executor() { return executor; }
@Override public final Future resolve(String inetHost) { final Promise promise = executor().newPromise(); return resolve(inetHost, promise); }
@Override public Future resolve(String inetHost, Promise promise) { checkNotNull(promise, "promise");
/** * Invoked by {@link #resolve(String)} to perform the actual name resolution. */ protected abstract void doResolve(String inetHost, Promise promise) throws Exception;
/** * Invoked by {@link #resolveAll(String)} to perform the actual name resolution. */ protected abstract void doResolveAll(String inetHost, Promise> promise) throws Exception;
/** * Resolves an arbitrary string that represents the name of an endpoint into an address. */ @UnstableApi public interface NameResolver extends Closeable {
/** * Resolves the specified name into an address. * * @param inetHost the name to resolve * * @return the address as the result of the resolution */ Future resolve(String inetHost);
/** * Resolves the specified name into an address. * * @param inetHost the name to resolve * @param promise the {@link Promise} which will be fulfilled when the name resolution is finished * * @return the address as the result of the resolution */ Future resolve(String inetHost, Promise promise);
/** * Resolves the specified host name and port into a list of address. * * @param inetHost the name to resolve * * @return the list of the address as the result of the resolution */ Future> resolveAll(String inetHost);
/** * Resolves the specified host name and port into a list of address. * * @param inetHost the name to resolve * @param promise the {@link Promise} which will be fulfilled when the name resolution is finished * * @return the list of the address as the result of the resolution */ Future> resolveAll(String inetHost, Promise> promise);
/** * Closes all the resources allocated and used by this resolver. */ @Override void close(); }
回到InetNameResolver的asAddressResolver方法的这一句
//如果内部地址解析器为空,则创建一个socket地址解析器 addressResolver = result = new InetSocketAddressResolver(executor(), this);
/** * A {@link AbstractAddressResolver} that resolves {@link InetSocketAddress}. */ @UnstableApi public class InetSocketAddressResolver extends AbstractAddressResolver {
final NameResolver nameResolver;//命名解决器,默认为DefaultNameResolver
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(java.net.SocketAddress)} * @param nameResolver the {@link NameResolver} used for name resolution */ public InetSocketAddressResolver(EventExecutor executor, NameResolver nameResolver) { super(executor, InetSocketAddress.class); this.nameResolver = nameResolver; } @Override public void close() { nameResolver.close(); } }
/** * Checks whether the address has been resolved or not. * * @return true if the hostname couldn't be resolved into * an InetAddress. */ public final boolean isUnresolved() { return holder.isUnresolved(); }
再看另外两个地址解决方法,
@Override protected void doResolve(final InetSocketAddress unresolvedAddress, final Promise promise) throws Exception { // Note that InetSocketAddress.getHostName() will never incur a reverse lookup here, // because an unresolved address always has a host name. //委托给命令解决器 nameResolver.resolve(unresolvedAddress.getHostName()) .addListener(new FutureListener() { @Override public void operationComplete(Future future) throws Exception { if (future.isSuccess()) { promise.setSuccess(new InetSocketAddress(future.getNow(), unresolvedAddress.getPort())); } else { promise.setFailure(future.cause()); } } }); }
@Override protected void doResolveAll(final InetSocketAddress unresolvedAddress, final Promise> promise) throws Exception { // Note that InetSocketAddress.getHostName() will never incur a reverse lookup here, // because an unresolved address always has a host name. //委托给命令解决器 nameResolver.resolveAll(unresolvedAddress.getHostName()) .addListener(new FutureListener>() { @Override public void operationComplete(Future> future) throws Exception { if (future.isSuccess()) { List inetAddresses = future.getNow(); List socketAddresses = new ArrayList(inetAddresses.size()); for (InetAddress inetAddress : inetAddresses) { socketAddresses.add(new InetSocketAddress(inetAddress, unresolvedAddress.getPort())); } promise.setSuccess(socketAddresses); } else { promise.setFailure(future.cause()); } } }); }
/** * A skeletal {@link AddressResolver} implementation. */ @UnstableApi public abstract class AbstractAddressResolver implements AddressResolver {
private final EventExecutor executor;//事件执行器 private final TypeParameterMatcher matcher;//socket地址匹配器
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(SocketAddress)} */ protected AbstractAddressResolver(EventExecutor executor) { this.executor = checkNotNull(executor, "executor"); matcher = TypeParameterMatcher.find(this, AbstractAddressResolver.class, "T"); }
/** * @param executor the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(SocketAddress)} * @param addressType the type of the {@link SocketAddress} supported by this resolver */ protected AbstractAddressResolver(EventExecutor executor, Class extends T> addressType) { this.executor = checkNotNull(executor, "executor"); matcher = TypeParameterMatcher.get(addressType); }
/** * Returns the {@link EventExecutor} which is used to notify the listeners of the {@link Future} returned * by {@link #resolve(SocketAddress)}. */ protected EventExecutor executor() { return executor; } //命名Resolver是否支持socket地址 @Override public boolean isSupported(SocketAddress address) { return matcher.match(address); } //socket地址是否可以Resolve @Override public final boolean isResolved(SocketAddress address) { if (!isSupported(address)) { throw new UnsupportedAddressTypeException(); }
@SuppressWarnings("unchecked") final T castAddress = (T) address; //具体Resolve工作委托给doIsResolved方法 return doIsResolved(castAddress); }
/** * Invoked by {@link #isResolved(SocketAddress)} to check if the specified {@code address} has been resolved * already. */ protected abstract boolean doIsResolved(T address);
@Override public final Future resolve(SocketAddress address) { if (!isSupported(checkNotNull(address, "address"))) { // Address type not supported by the resolver return executor().newFailedFuture(new UnsupportedAddressTypeException()); }
if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return executor.newSucceededFuture(cast); }
try { @SuppressWarnings("unchecked") final T cast = (T) address; final Promise promise = executor().newPromise(); //具体Resolve工作委托给doIsResolved方法 doResolve(cast, promise); return promise; } catch (Exception e) { return executor().newFailedFuture(e); } }
@Override public final Future resolve(SocketAddress address, Promise promise) { checkNotNull(address, "address"); checkNotNull(promise, "promise");
if (!isSupported(address)) { // Address type not supported by the resolver return promise.setFailure(new UnsupportedAddressTypeException()); }
if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return promise.setSuccess(cast); }
@Override public final Future> resolveAll(SocketAddress address) { if (!isSupported(checkNotNull(address, "address"))) { // Address type not supported by the resolver return executor().newFailedFuture(new UnsupportedAddressTypeException()); }
if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return executor.newSucceededFuture(Collections.singletonList(cast)); }
try { @SuppressWarnings("unchecked") final T cast = (T) address; final Promise> promise = executor().newPromise(); //具体Resolve工作委托给doResolveAll方法 doResolveAll(cast, promise); return promise; } catch (Exception e) { return executor().newFailedFuture(e); } }
@Override public final Future> resolveAll(SocketAddress address, Promise> promise) { checkNotNull(address, "address"); checkNotNull(promise, "promise");
if (!isSupported(address)) { // Address type not supported by the resolver return promise.setFailure(new UnsupportedAddressTypeException()); }
if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; return promise.setSuccess(Collections.singletonList(cast)); }
try { @SuppressWarnings("unchecked") final T cast = (T) address; //具体Resolve工作委托给doResolveAll方法 doResolveAll(cast, promise); return promise; } catch (Exception e) { return promise.setFailure(e); } } //下面几个方法待子类实现,见InetSocketAddressResolver的定义 /** * Invoked by {@link #resolve(SocketAddress)} to perform the actual name * resolution. */ protected abstract void doResolve(T unresolvedAddress, Promise promise) throws Exception;
/** * Invoked by {@link #resolveAll(SocketAddress)} to perform the actual name * resolution. */ protected abstract void doResolveAll(T unresolvedAddress, Promise> promise) throws Exception;
/** * Resolves a possibility unresolved {@link SocketAddress}. */ @UnstableApi public interface AddressResolver extends Closeable {
/** * Returns {@code true} if and only if the specified address is supported by this resolved. */ boolean isSupported(SocketAddress address);
/** * Returns {@code true} if and only if the specified address has been resolved. * * @throws UnsupportedAddressTypeException if the specified address is not supported by this resolver */ boolean isResolved(SocketAddress address);
/** * Resolves the specified address. If the specified address is resolved already, this method does nothing * but returning the original address. * * @param address the address to resolve * * @return the {@link SocketAddress} as the result of the resolution */ Future resolve(SocketAddress address);
/** * Resolves the specified address. If the specified address is resolved already, this method does nothing * but returning the original address. * * @param address the address to resolve * @param promise the {@link Promise} which will be fulfilled when the name resolution is finished * * @return the {@link SocketAddress} as the result of the resolution */ Future resolve(SocketAddress address, Promise promise);
/** * Resolves the specified address. If the specified address is resolved already, this method does nothing * but returning the original address. * * @param address the address to resolve * * @return the list of the {@link SocketAddress}es as the result of the resolution */ Future> resolveAll(SocketAddress address);
/** * Resolves the specified address. If the specified address is resolved already, this method does nothing * but returning the original address. * * @param address the address to resolve * @param promise the {@link Promise} which will be fulfilled when the name resolution is finished * * @return the list of the {@link SocketAddress}es as the result of the resolution */ Future> resolveAll(SocketAddress address, Promise> promise);
/** * Closes all the resources allocated and used by this resolver. */ @Override void close(); }
androi中提到了布尔数组;
布尔数组默认的是false, 并且只会打印false或者是true
布尔数组的例子; 根据字符数组创建布尔数组
char[] c = {'p','u','b','l','i','c'};
//根据字符数组的长度创建布尔数组的个数
boolean[] b = new bool
文章摘自:http://blog.csdn.net/yangwawa19870921/article/details/7553181
在编写HQL时,可能会出现这种代码:
select a.name,b.age from TableA a left join TableB b on a.id=b.id
如果这是HQL,那么这段代码就是错误的,因为HQL不支持
1. 简单的for循环
public static void main(String[] args) {
for (int i = 1, y = i + 10; i < 5 && y < 12; i++, y = i * 2) {
System.err.println("i=" + i + " y="
异常信息本地化
Spring Security支持将展现给终端用户看的异常信息本地化,这些信息包括认证失败、访问被拒绝等。而对于展现给开发者看的异常信息和日志信息(如配置错误)则是不能够进行本地化的,它们是以英文硬编码在Spring Security的代码中的。在Spring-Security-core-x
近来工作中遇到这样的两个需求
1. 给个Date对象,找出该时间所在月的第一天和最后一天
2. 给个Date对象,找出该时间所在周的第一天和最后一天
需求1中的找月第一天很简单,我记得api中有setDate方法可以使用
使用setDate方法前,先看看getDate
var date = new Date();
console.log(date);
// Sat J
MyBatis的update元素的用法与insert元素基本相同,因此本篇不打算重复了。本篇仅记录批量update操作的
sql语句,懂得SQL语句,那么MyBatis部分的操作就简单了。 注意:下列批量更新语句都是作为一个事务整体执行,要不全部成功,要不全部回滚。
MSSQL的SQL语句
WITH R AS(
SELECT 'John' as name, 18 as