• netty的简单的应用例子


    一、简单的聊天室程序

      

    public class ChatClient {
    
        public static void main(String[] args) throws InterruptedException, IOException {
            NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
            try{
                Bootstrap bootstrap = new Bootstrap();
                bootstrap.group(nioEventLoopGroup).channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
    
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline()
    //                        .addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()))
                            .addLast(new LineBasedFrameDecoder(1024))
                            .addLast(new StringDecoder(CharsetUtil.UTF_8))
                            .addLast(new StringEncoder(CharsetUtil.UTF_8))
                            .addLast(new SimpleChannelInboundHandler<String>() {
    
                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
                                    System.out.println(msg);
                                    
                                }
                            });
                        }
                    });
                ChannelFuture future = bootstrap.connect("localhost", 8888).sync();
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                Channel channel = future.channel();
                while(true){
                    channel.writeAndFlush(br.readLine()+"
    ");
                }
                
            }finally{
                nioEventLoopGroup.shutdownGracefully().sync();
            }
        }
    
    }
    public class ChatServer {
    
        public static void main(String[] args) throws InterruptedException {
            
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workerGroup = new NioEventLoopGroup();
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline()
    //                        .addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()))
                            .addLast(new LineBasedFrameDecoder(1024))
                            .addLast(new StringDecoder(CharsetUtil.UTF_8))
                            .addLast(new StringEncoder(CharsetUtil.UTF_8))
                            .addLast(new ChatServerHandler());
                        }
                        
                    });
                ChannelFuture future = serverBootstrap.bind(8888).sync();
                future.channel().closeFuture().sync();
            }finally{
                bossGroup.shutdownGracefully().sync();
                workerGroup.shutdownGracefully().sync();
            }
            
        }
        
        
    
    }
    public class ChatServerHandler extends SimpleChannelInboundHandler<String>{
        
        public static final ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            Channel channel = ctx.channel();
            group.forEach(ch ->{
                if(channel != ch){
                    ch.writeAndFlush(channel.remoteAddress()+": "+ msg+"
    ");
                }else{
                    ch.writeAndFlush("自己: "+msg+"
    ");
                }
            });
        }
        
        @Override
        public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
            Channel channel = ctx.channel();
            group.writeAndFlush("服务器: "+channel.remoteAddress()+"加入");
            group.add(channel);
        }
        
        @Override
        public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
            Channel channel = ctx.channel();
            group.writeAndFlush("服务器 : "+channel.remoteAddress() + "离开");
            
        }
        
        
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println(ctx.channel().remoteAddress()+" 上线");
        }
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            System.out.println(ctx.channel().remoteAddress()+" 下线");
        }
        
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
        }
        
        
    
    }

    二、使用netty传递对象,使用jdk自带的序列化

    public class SubReqClient {
    
        public static void main(String[] args) {
            start();
        }
        
        public static void start(){
            NioEventLoopGroup group = new NioEventLoopGroup();
            
            try{
                Bootstrap bootstrap = new Bootstrap();
                bootstrap.group(group).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<Channel>() {
    
                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                        ch.pipeline()
                        .addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(
                                this.getClass().getClassLoader()
                        )))
                        .addLast("encoder", new ObjectEncoder())
                        .addLast(new SimpleChannelInboundHandler<Object>() {
    
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                                System.out.println(msg);
                            }
                            
                            @Override
                            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                User user = new User();
                                user.setName("runtu");
                                ctx.writeAndFlush(user);
                            }
                            
                        });
                    }
                });
                ChannelFuture future = bootstrap.connect("localhost", 8888).sync();
                future.channel().closeFuture().sync();
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                group.shutdownGracefully();
            }
        }
    
    }
    public class SubReqServer {
    
        public static void main(String[] args) {
            start();
        }
        
        public static void start(){
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workGroup = new NioEventLoopGroup();
            
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline()
                            .addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(
                                    this.getClass().getClassLoader()
                            )))
                            .addLast("encoder", new ObjectEncoder())
                            .addLast(new SimpleChannelInboundHandler<Object>() {
    
                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    User user1 = (User)msg;
                                    System.out.println(user1.getName());
                                    
                                    User user = new User();
                                    user.setName("AQ");
                                    ctx.writeAndFlush(user);
                                    
                                }
                                
                            });
                        }
                    });
                ChannelFuture future = serverBootstrap.bind(8888).sync();
                future.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                bossGroup.shutdownGracefully();
                workGroup.shutdownGracefully();
            }
        }
    
    }
    public class User implements Serializable{
    
        private String name;
        private int  age;
        private String address;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
        
        @Override
        public String toString() {
            return "User [name=" + name + ", age=" + age + ", address=" + address + "]";
        }
        
        
    }

      

    三、使用messagepack进行序列化传递实体对象

      由于java自带的序列化工具有着性能低、序列化后的码流大且不支持跨语言等各种缺陷,所以我们使用Msgpack库来进行序列化然后进行数据的传输。

      我们需要额外引入两个jar包javassist-3.18.1-GA.jar 和msgpack-0.6.12.jar

    public class NioClient {
    
        public static void main(String[] args) throws InterruptedException {
            
            NioEventLoopGroup group = new NioEventLoopGroup();
            
            try{
                Bootstrap bootStrap = new Bootstrap();
                bootStrap.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,3000)
                    .handler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline()
                            .addLast("frameDecoder",new LengthFieldBasedFrameDecoder(1024, 0, 2,0,2))
                            .addLast(new MsgpackDecoder())
                            .addLast("frameEncoder",new LengthFieldPrepender(2))
                            .addLast(new MsgpackEncoder())
                            .addLast(new ClientHandler());
                        }
                    });
                
                ChannelFuture future = bootStrap.connect("localhost", 9999).sync();
                future.channel().closeFuture().sync();
            }finally{
                group.shutdownGracefully();
            }
        }
    
    }
    public class ClientHandler extends SimpleChannelInboundHandler {
    
        @Override
        public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println(msg);
        }
    
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            //发送50个UserInfo给服务器,由于启用了粘包/拆包支持,所以这里连续发送多个也不会出现粘包的现象。
            for (int i = 0; i < 50; i++) {
                User user = new User();
                user.setName("张三"+i);
                ctx.write(user);
            }
            ctx.flush();
            System.out.println("-----------------send over-----------------");
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            System.out.println("error");
        }
    }
    public class NioServer {
        
        public static void main(String[] args) throws InterruptedException {
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workGroup = new NioEventLoopGroup();
            
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline()
                            .addLast("frameDecoder",new LengthFieldBasedFrameDecoder(1024, 0, 2,0,2))
                            .addLast(new MsgpackDecoder())
                            .addLast("frameEncoder",new LengthFieldPrepender(2))
                            .addLast(new MsgpackEncoder())
                            .addLast(new ServerHandler());
                        }
                    });
                ChannelFuture future = serverBootstrap.bind(9999).sync();
                future.channel().closeFuture().sync();
            }finally{
                bossGroup.shutdownGracefully();
                workGroup.shutdownGracefully();
            }
        }
    
    }
    public class ServerHandler extends SimpleChannelInboundHandler {
    
        @Override
        public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
            try {
            //直接输出msg
            System.out.println(msg.toString());
            User user = new User();
            user.setName("李四");
            //回复has receive 给客户端
                ctx.write(user);
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
            }
        }
    
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
        }
    
    }
    public class MsgpackDecoder extends MessageToMessageDecoder<ByteBuf>{
    
        @Override
        protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> out) throws Exception {
            
            final int length = buf.readableBytes();
            final byte[] array = new byte[length];
            buf.getBytes(buf.readerIndex(), array,0,length);
            MessagePack messagePack = new MessagePack();
            out.add(messagePack.read(array));
        }
    
    }
    public class MsgpackEncoder extends MessageToByteEncoder<Object>{
    
        @Override
        protected void encode(ChannelHandlerContext ctx, Object obj, ByteBuf out) throws Exception {
            MessagePack messagePack = new MessagePack();
            byte[] info = messagePack.write(obj);
            out.writeBytes(info);
        }
    
    }
    @Message
    public class User {
    
        private String name;
        private int  age;
        private String address;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
        
        @Override
        public String toString() {
            return "User [name=" + name + ", age=" + age + ", address=" + address + "]";
        }
        
        
    }

    四、使用Marshalling来对对象进行序列化,这种序列化方式需要对想实现Serializable接口

      需要引入jar包 jboss-marshalling-2.0.6.Final.jar和jboss-marshalling-serial-2.0.6.Final.jar

    public class SubReqClient {
    
        public static void main(String[] args) {
            start();
        }
        
        public static void start(){
            NioEventLoopGroup group = new NioEventLoopGroup();
            
            try{
                Bootstrap bootstrap = new Bootstrap();
                bootstrap.group(group).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<Channel>() {
    
                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                        ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder())
                        .addLast(MarshallingCodeCFactory.buildMarshallingEncoder())
                        .addLast(new SimpleChannelInboundHandler<Object>() {
    
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                                System.out.println(msg);
                            }
                            
                            @Override
                            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                User user = new User();
                                user.setName("runtu");
                                ctx.writeAndFlush(user);
                            }
                            
                        });
                    }
                });
                ChannelFuture future = bootstrap.connect("localhost", 8888).sync();
                future.channel().closeFuture().sync();
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                group.shutdownGracefully();
            }
        }
    
    }
    public class SubReqServer {
    
        public static void main(String[] args) {
            start();
        }
        
        public static void start(){
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workGroup = new NioEventLoopGroup();
            
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder())
                            .addLast(MarshallingCodeCFactory.buildMarshallingEncoder())
                            .addLast(new SimpleChannelInboundHandler<Object>() {
    
                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    User user1 = (User)msg;
                                    System.out.println(user1.getName());
                                    
                                    User user = new User();
                                    user.setName("AQ");
                                    ctx.writeAndFlush(user);
                                    
                                }
                                
                            });
                        }
                    });
                ChannelFuture future = serverBootstrap.bind(8888).sync();
                future.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                bossGroup.shutdownGracefully();
                workGroup.shutdownGracefully();
            }
        }
    
    }
    public class MarshallingCodeCFactory {
        
        public static MarshallingDecoder buildMarshallingDecoder(){
            final MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
            final MarshallingConfiguration configuration = new MarshallingConfiguration();
            configuration.setVersion(5);
            DefaultUnmarshallerProvider provider = new DefaultUnmarshallerProvider(factory, configuration);
            MarshallingDecoder decoder = new MarshallingDecoder(provider,1024);
            return decoder;
        }
        
        
        public static MarshallingEncoder buildMarshallingEncoder(){
            final MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
            final MarshallingConfiguration configuration = new MarshallingConfiguration();
            configuration.setVersion(5);
            MarshallerProvider provider = new DefaultMarshallerProvider(factory, configuration);
            MarshallingEncoder encoder = new MarshallingEncoder(provider);
            return encoder;
        }
    
    }
    public class User implements Serializable{
    
        private String name;
        private int  age;
        private String address;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
        
        @Override
        public String toString() {
            return "User [name=" + name + ", age=" + age + ", address=" + address + "]";
        }
        
        
    }

    五、简单的http文件服务器

      

    public class HttpServer {
    
        public static void main(String[] args) {
            start();
        }
        
        public static void start(){
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workGroup = new NioEventLoopGroup();
            
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline()
                            .addLast(new HttpRequestDecoder())
                            .addLast(new HttpObjectAggregator(65535))
                            .addLast(new HttpResponseEncoder())
                            .addLast(new ChunkedWriteHandler())
                            .addLast(new FileServerHandler1());
                        }
                    });
                ChannelFuture future = serverBootstrap.bind(8888).sync();
                future.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                bossGroup.shutdownGracefully();
                workGroup.shutdownGracefully();
            }
        }
    }
    public class FileServerHandler1 extends SimpleChannelInboundHandler<FullHttpRequest>{
    
    
            @Override
            protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
                
                if(request.uri().equals("/favicon.ico")){
                    return;
                }
                
                if(request.method() == HttpMethod.GET){
                    String uri = request.uri();
                    if(uri.startsWith("/file")){
                        
                        File file = new File("D:\12306Bypass\使用须知.txt");
                        RandomAccessFile randomAccessFile = null;
                        randomAccessFile = new RandomAccessFile(file, "r");
                        long fileLength = randomAccessFile.length();
                        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
                        response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE)
                            .set("Content-Length", fileLength)
                            .set("Content-Type","text/html")
                            .set("Content-Disposition", "attachment;fileName="+"a.txt");        
                        
                        ctx.write(response);
                        ctx.write(new ChunkedFile(randomAccessFile, 0,fileLength,8192),ctx.newProgressivePromise());
                        ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
                            
                }else{
                    FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
                    response.headers()
                    .set("Content-Type", "text/plain;charset=utf-8")
                    .set("Content_Length", response.content().readableBytes())
                    .set("aaa", "cccc");
                    response.content().writeBytes(Unpooled.copiedBuffer("服务器返回信息",CharsetUtil.UTF_8));
                    ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
                }
            }
        }
            
            
        private static void setContentTypeHeader(HttpResponse response, File file){
            MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap();
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, mimetypesFileTypeMap.getContentType(file.getPath()));
        }
    }

    六、netty编写websocket服务器

    public class WebSocketServer {
    
        public static void main(String[] args) throws InterruptedException {
            NioEventLoopGroup bossGroup = new NioEventLoopGroup();
            NioEventLoopGroup workerGroup = new NioEventLoopGroup();
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<Channel>() {
    
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline()
                            .addLast(new HttpServerCodec())
                            .addLast(new HttpObjectAggregator(65536))
                            .addLast(new ChunkedWriteHandler())
                            .addLast(new WebSocketServerHandler());
                        }
                    });
                ChannelFuture future = serverBootstrap.bind(8080).sync();
                future.channel().closeFuture().sync();
            }finally{
                bossGroup.shutdownGracefully().sync();
                workerGroup.shutdownGracefully().sync();
            }
        }
    
    }
    public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>{
    
        private WebSocketServerHandshaker handshaker;
        
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
            if(msg instanceof FullHttpRequest){
                HandleHttpRequest(ctx,(FullHttpRequest)msg);
            }
            
            if(msg instanceof WebSocketFrame){
                handleWebSocket(ctx,(WebSocketFrame)msg);
            }
            
            
        }
        
        private void HandleHttpRequest(ChannelHandlerContext ctx,FullHttpRequest request){
            WebSocketServerHandshakerFactory factory = new WebSocketServerHandshakerFactory(
                    "ws://localhost:8888/websocket",null,false);
            handshaker = factory.newHandshaker(request);
            if(handshaker == null){
                WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
            }else{
                handshaker.handshake(ctx.channel(),request);
            }
            
            
        }
        
        private void handleWebSocket(ChannelHandlerContext ctx,WebSocketFrame frame){
            
            if(frame instanceof CloseWebSocketFrame){
                handshaker.close(ctx.channel(), (CloseWebSocketFrame)frame.retain());
            }
            
            if(frame instanceof PingWebSocketFrame){
                ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
                return;
            }
            
            if(!(frame instanceof TextWebSocketFrame)){
                return;
            }
            
            String requestStr = ((TextWebSocketFrame) frame).text();
            System.out.println(requestStr);
            ctx.channel().writeAndFlush(new TextWebSocketFrame("欢迎使用netty websocket: "+ LocalDateTime.now()));
        }
        
        
    
    }
    <html>
    <head>
    <meta charset="UTF-8">
    Netty WebSocket服务器
    <head>
    <body>
    <script type="text/javascript">
    var socket;
    if(!window.WebSocket){
    window.WebSocket = window.MozWebSocket;
    }
    
    if(window.WebSocket){
    socket = new WebSocket("ws://localhost:8080/websocket");
    socket.onmessage = function(event){
        var ta = document.getElementById('responseText');
        ta.value = '';
        ta.value = event.data;
    }
    
    socket.onopen = function(event){
        var ta = document.getElementById('responseText');
        ta.value = "打开WebSocket服务器正常";
    }
    
    socket.onclose = function(event){
        var ta = document.getElementById('responseText');
        ta.value = "webSocket 关闭";
    }
    
    
    
    }
    
    function send(){
        if(socket.readyState == WebSocket.OPEN){
        var message = document.getElementById('message').value;
            socket.send(message);
        }else{
            alert("WebSocket 链接未建立成功!!");
        }
    }
    </script>
    <form onsubmit="return false;"> 
        <input id="message" type="text" name = "message" value="Netty最佳实践"/>
    
    <br/><br/>
    <input type="button" value="发送" onclick="send()"/>
    <hr color="blue"/>
    <h3>服务器应答消息</h3>
    <textarea id="responseText" style="500px;height:300px;"></textarea>
    </form>
    
    
    
    
    </body>
    
    
    </html>
  • 相关阅读:
    【LeetCode & 剑指offer刷题】数组题18:Plus One
    SQL Server 2005 的动态管理视图DMV和函数DMF
    数据库SQL优化大总结之 百万级数据库优化方案
    误删SQL Server日志文件后怎样附加数据库
    教你建立SQL数据库的表分区
    Sql Server 阻塞的常见原因和解决办法
    SQL索引优化方法
    详解如何定义SQL Server外关键字约束
    写出高性能SQL语句的十三条法则
    SQL SERVER内部函数大全
  • 原文地址:https://www.cnblogs.com/kyleinjava/p/10407926.html
Copyright © 2020-2023  润新知