YII Framework学习教程-YII的日志
netty
- package com.dxz.nettydemo.http;
- import java.io.UnsupportedEncodingException;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- import io.netty.handler.codec.http.DefaultFullHttpResponse;
- import io.netty.handler.codec.http.FullHttpResponse;
- import io.netty.handler.codec.http.HttpRequest;
- import io.netty.handler.codec.http.HttpResponseStatus;
- import io.netty.handler.codec.http.HttpVersion;
- import io.netty.handler.codec.http.QueryStringDecoder;
- class HttpServerHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException {
- if (msg instanceof HttpRequest) {
- // 请求,解码器将请求转换成HttpRequest对象
- HttpRequest request = (HttpRequest) msg;
- // 获取请求参数
- QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
- String name = "World";
- if (queryStringDecoder.parameters().get("name") != null) {
- name = queryStringDecoder.parameters().get("name").get(0);
- }
- // 响应HTML
- String responseHtml = "<html><body>Hello, " + name + "</body></html>";
- byte[] responseBytes = responseHtml.getBytes("UTF-8");
- int contentLength = responseBytes.length;
- // 构造FullHttpResponse对象,FullHttpResponse包含message body
- FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
- Unpooled.wrappedBuffer(responseBytes));
- response.headers().set("Content-Type", "text/html; charset=utf-8");
- response.headers().set("Content-Length", Integer.toString(contentLength));
- ctx.writeAndFlush(response);
- }
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- cause.printStackTrace();
- ctx.close();
- }
- }
主类:
- package com.dxz.nettydemo.http;
- import io.netty.bootstrap.ServerBootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelPipeline;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioServerSocketChannel;
- import io.netty.handler.codec.http.HttpServerCodec;
- public class HttpServer {
- public static void main(String[] args) throws InterruptedException {
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- ServerBootstrap b = new ServerBootstrap();
- b.group(bossGroup, workerGroup)
- .channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) throws Exception {
- ChannelPipeline pipeline = ch.pipeline();
- pipeline.addLast(new HttpServerCodec());
- pipeline.addLast(new HttpServerHandler());
- }
- });
- ChannelFuture f = b.bind(8080).sync();
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- }
- }
- }
测试:
用浏览器访问:http://localhost:8080/
netty构建的文件服务器
1、首先加入的是HTTP请求消息解码器
ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
2、第2添加HttpObjectAggregator解密器,其作用是将多个消息转换为单一的FullHttpRequest或者FullHttpResponse,原因是HTTP解码器在每个HTTP消息中会生成多个消息对象:有1、HttpRequest/HttpResponse;2、HttpContent;3、LastHttpContent;
ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536));
3、第3增加HTTP响应编码器,对HTTP响应信息进行编码
ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());
4、第4Chunked handler的主要作用是支持异步发送大的码流(例如大的文件传输),但不占用过多的内存,防止发生JAVA内存溢出错误
ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
5、第5HttpFileServerHandler用于文件服务器的业务逻辑处理
- package com.dxz.nettydemo.http;
- import io.netty.bootstrap.ServerBootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioServerSocketChannel;
- import io.netty.handler.codec.http.HttpObjectAggregator;
- import io.netty.handler.codec.http.HttpRequestDecoder;
- import io.netty.handler.codec.http.HttpResponseEncoder;
- import io.netty.handler.stream.ChunkedWriteHandler;
- public class HttpFileServer {
- private static final String DEFAULT_URL = "/src/main/java/com/dxz/nettydemo/http";
- public void run(final int port, final String url) throws Exception {
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- ServerBootstrap b = new ServerBootstrap();
- b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- protected void initChannel(SocketChannel ch) throws Exception {
- //首先加入的是HTTP请求消息解码器
- ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
- //第2添加HttpObjectAggregator解密器,其作用是将多个消息转换为单一的FullHttpRequest或者FullHttpResponse,
- //原因是HTTP解码器在每个HTTP消息中会生成多个消息对象:有1、HttpRequest/HttpResponse;2、HttpContent;3、LastHttpContent;
- ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536));
- //第3增加HTTP响应编码器,对HTTP响应信息进行编码
- ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());
- //第4Chunked handler的主要作用是支持异步发送大的码流(例如大的文件传输),但不占用过多的内存,防止发生JAVA内存溢出错误
- ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
- //第5HttpFileServerHandler用于文件服务器的业务逻辑处理
- ch.pipeline().addLast("fileServerHandler", new HttpFileServerHandler(url));
- }
- });
- ChannelFuture future = b.bind("localhost", port).sync();
- System.out.println("HTTP文件目录服务器启动,网址是 : " + "http://localhost:" + port + url);
- future.channel().closeFuture().sync();
- } finally {
- bossGroup.shutdownGracefully();
- workerGroup.shutdownGracefully();
- }
- }
- public static void main(String[] args) throws Exception {
- int port = 8080;
- if (args.length > 0) {
- try {
- port = Integer.parseInt(args[0]);
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- }
- String url = DEFAULT_URL;
- if (args.length > 1)
- url = args[1];
- new HttpFileServer().run(port, url);
- }
- }
文件读取下载
- package com.dxz.nettydemo.http;
- import static io.netty.handler.codec.http.HttpHeaders.isKeepAlive;
- import static io.netty.handler.codec.http.HttpHeaders.setContentLength;
- import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;
- import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
- import static io.netty.handler.codec.http.HttpHeaders.Names.LOCATION;
- import static io.netty.handler.codec.http.HttpMethod.GET;
- import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
- import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
- import static io.netty.handler.codec.http.HttpResponseStatus.FOUND;
- import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
- import static io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
- import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
- import static io.netty.handler.codec.http.HttpResponseStatus.OK;
- import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelFutureListener;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelProgressiveFuture;
- import io.netty.channel.ChannelProgressiveFutureListener;
- import io.netty.channel.SimpleChannelInboundHandler;
- import io.netty.handler.codec.http.DefaultFullHttpResponse;
- import io.netty.handler.codec.http.DefaultHttpResponse;
- import io.netty.handler.codec.http.FullHttpRequest;
- import io.netty.handler.codec.http.FullHttpResponse;
- import io.netty.handler.codec.http.HttpHeaders;
- import io.netty.handler.codec.http.HttpResponse;
- import io.netty.handler.codec.http.HttpResponseStatus;
- import io.netty.handler.codec.http.LastHttpContent;
- import io.netty.handler.stream.ChunkedFile;
- import io.netty.util.CharsetUtil;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.RandomAccessFile;
- import java.io.UnsupportedEncodingException;
- import java.net.URLDecoder;
- import java.util.regex.Pattern;
- import javax.activation.MimetypesFileTypeMap;
- public class HttpFileServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
- private final String url;
- public HttpFileServerHandler(String url) {
- this.url = url;
- }
- @Override
- public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
- //http请求消息解码结果的判断,如果解码失败,直接返回构造HTTP400 错误返回
- if (!request.getDecoderResult().isSuccess()) {
- sendError(ctx, BAD_REQUEST);
- return;
- }
- if (request.getMethod() != GET) {
- sendError(ctx, METHOD_NOT_ALLOWED);
- return;
- }
- final String uri = request.getUri();
- final String path = sanitizeUri(uri);
- if (path == null) {
- sendError(ctx, FORBIDDEN);
- return;
- }
- File file = new File(path);
- if (file.isHidden() || !file.exists()) {
- sendError(ctx, NOT_FOUND);
- return;
- }
- if (file.isDirectory()) {
- if (uri.endsWith("/")) {
- sendListing(ctx, file);
- } else {
- sendRedirect(ctx, uri + '/');
- }
- return;
- }
- if (!file.isFile()) {
- sendError(ctx, FORBIDDEN);
- return;
- }
- RandomAccessFile randomAccessFile = null;
- try {
- randomAccessFile = new RandomAccessFile(file, "r");// 以只读的方式打开文件
- } catch (FileNotFoundException fnfe) {
- sendError(ctx, NOT_FOUND);
- return;
- }
- //待下载文件的长度
- long fileLength = randomAccessFile.length();
- HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
- setContentLength(response, fileLength);
- setContentTypeHeader(response, file);
- if (isKeepAlive(request)) {
- response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
- }
- ctx.write(response);
- ChannelFuture sendFileFuture;
- //通过netty的ChunkedFile对象将文件写入到发送缓冲区
- sendFileFuture = ctx.write(new ChunkedFile(randomAccessFile, 0, fileLength, 8192), ctx.newProgressivePromise());
- sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
- public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
- if (total < 0) { // total unknown
- System.err.println("Transfer progress: " + progress);
- } else {
- System.err.println("Transfer progress: " + progress + " / " + total);
- }
- }
- public void operationComplete(ChannelProgressiveFuture future) throws Exception {
- System.out.println("Transfer complete.");
- }
- });
- //使用chunked编码,最后需要发送一个编码结束 的空消息体,将LastHttpContent的EMPTY_LAST_CONTENT发送到缓冲区中,标识所有的消息体已经发送完成,同时
- //用flush方法将之前在发送缓冲区的消息刷新到SocketChannel中发送给对方
- ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
- //如果不是keep-alive,服务端在发送完成之后,服务端主动关闭连接
- if (!isKeepAlive(request)) {
- lastContentFuture.addListener(ChannelFutureListener.CLOSE);
- }
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- cause.printStackTrace();
- if (ctx.channel().isActive()) {
- sendError(ctx, INTERNAL_SERVER_ERROR);
- }
- }
- private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");
- /**
- * 请求路径的处理
- * @param uri
- * @return
- */
- private String sanitizeUri(String uri) {
- try {
- uri = URLDecoder.decode(uri, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- try {
- uri = URLDecoder.decode(uri, "ISO-8859-1");
- } catch (UnsupportedEncodingException e1) {
- throw new Error();
- }
- }
- if (!uri.startsWith(url)) {
- return null;
- }
- if (!uri.startsWith("/")) {
- return null;
- }
- uri = uri.replace('/', File.separatorChar);
- if (uri.contains(File.separator + '.') || uri.contains('.' + File.separator) || uri.startsWith(".")
- || uri.endsWith(".") || INSECURE_URI.matcher(uri).matches()) {
- return null;
- }
- return System.getProperty("user.dir") + File.separator + uri;
- }
- private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");
- private static void sendListing(ChannelHandlerContext ctx, File dir) {
- //创建成功的HTTP响应消息
- FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
- //设置消息头类型
- response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
- //构造响应消息体
- StringBuilder buf = new StringBuilder();
- String dirPath = dir.getPath();
- buf.append("<!DOCTYPE html>\r\n");
- buf.append("<html><head><title>");
- buf.append(dirPath);
- buf.append(" 目录:");
- buf.append("</title></head><body>\r\n");
- buf.append("<h3>");
- buf.append(dirPath).append(" 目录:");
- buf.append("</h3>\r\n");
- buf.append("<ul>");
- buf.append("<li>链接:<a href=\"../\">..</a></li>\r\n");
- for (File f : dir.listFiles()) {
- if (f.isHidden() || !f.canRead()) {
- continue;
- }
- String name = f.getName();
- if (!ALLOWED_FILE_NAME.matcher(name).matches()) {
- continue;
- }
- buf.append("<li>链接:<a href=\"");
- buf.append(name);
- buf.append("\">");
- buf.append(name);
- buf.append("</a></li>\r\n");
- }
- buf.append("</ul></body></html>\r\n");
- //分配对应消息的缓冲对象
- ByteBuf buffer = Unpooled.copiedBuffer(buf, CharsetUtil.UTF_8);
- //将缓冲区中的响应消息存放到HTTP应答消息中
- response.content().writeBytes(buffer);
- //释放缓冲区
- buffer.release();
- //将响应消息刷新到SocketChannel中
- ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
- }
- private static void sendRedirect(ChannelHandlerContext ctx, String newUri) {
- FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND);
- response.headers().set(LOCATION, newUri);
- ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
- }
- private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
- FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status,
- Unpooled.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8));
- response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
- ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
- }
- private static void setContentTypeHeader(HttpResponse response, File file) {
- MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
- response.headers().set(CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
- }
- }
演示:
YII Framework学习教程-YII的日志的更多相关文章
- YII Framework学习教程-YII的异常处理
异常无处不在,作为程序员,活着就是为了创造这些异常,然后修复这些异常而存在的.YII框架封装了PHP的异常,让异常处理起来更简单. 使用 YII处理错误和异常的配置方法: 你可以在入口文件中定义YII ...
- YII Framework学习教程-YII的Model-开发规范-路径别名-命名空间
到这里,大概的YII开发已经基本可以,但是下面要将的所有课程,学完之后可以让你更爱YII.下面的教程是讲的MVC的M,model.数据,业务,代码的集中地区.所以开始之前,学学开发规范-路径别名-命名 ...
- YII Framework学习教程-YII的安全
web应用的安全问题是很重要的,在“黑客”盛行的年代,你的网站可能明天都遭受着攻击,为了从某种程度上防止被攻击,YII提供了防止攻击的几种解决方案.当然这里讲的安全是片面的,但是值得一看. 官方提供的 ...
- YII Framework学习教程-YII的国际化
一个web应用,发布到互联网,就是面向全球用户.用户在世界的各个角落都可以访问到你的web应用,当然要看你的网站和不和谐,不和谐的web应用在和谐社会是不让你访问的. YII提供了国际化的支持,可以让 ...
- Yii Framework 开发教程Zii组件-Tabs示例
有关Yii Tab类: http://www.yiichina.com/api/CTabView http://www.yiichina.com/api/CJuiTabs http://blog.cs ...
- Yii 简明学习教程
Yii是一个基于组件的高性能PHP框架,用于快速开发Web应用程序(下面内容基于Yii 1.1) 1. 典型的工作流 用户向入口脚本index.php发起请求 入口脚本加载应用配置config.php ...
- YII之yiic创建YII应用
yii提供了强大的命令行工具来快速的创建相关组件和应用.下面就来讲解用yiic工具快速创建yii应用我的web目录在 d:\www下 yiiframework在 D:\www\yii\framewor ...
- Yii框架学习 新手教程(一)
本人小菜鸟一仅仅,为了自我学习和交流PHP(jquery,linux,lamp,shell,javascript,server)等一系列的知识,小菜鸟创建了一个群.希望光临本博客的人能够进来交流.寻求 ...
- Yii框架的学习指南(策码秀才篇)1-1 如何认识Yii framework
Yii的框架和其他框架的区别在于:它是更加 快速,安全,专业的PHP框架 Yii是一个高性能的,适用于开发WEB2.0应用的PHP框架. Yii是一个基于组件.用于开发大型 Web 应用的 高性能 P ...
随机推荐
- Linux软链接和硬链接
Linux中的链接有两种方式,软链接和硬链接.本文试图清晰彻底的解释Linux中软链接和硬链接文件的区别. 1.Linux链接文件 1)软链接文件 软链接又叫符号链接,这个文件包含了另一个文件的路径 ...
- 复习一下,? extends T 和 ? super T
前话 最近学一些杂七杂八的东西,都把基础给忘了. 比如Java泛型中的 ? extends T和 ? super T 吧. 刚看开源项目的时候遇到它,表情如下: 源码分析 直接用源码来讲解吧 pack ...
- 《mysql悲观锁总结和实践》-悲观锁
最近学习了一下数据库的悲观锁和乐观锁,根据自己的理解和网上参考资料总结如下: 悲观锁介绍(百科): 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持 ...
- ubuntu安装postgresql与postgis
版本信息 ubuntu 14.04.1LTS postgresql 9.3.5 postgis 2.1.2 今天尝试着安装了postgis 2.1.2,(较简便的包安装,不是源码 ...
- 原生javascript-常用的函数
[一]添加监听事件 addHandler:function(node,type,fn){if(node.addEventListener){ node.addEventListener(type,fn ...
- 使用Windows Azure PowerShell远程管理Windows Azure虚拟机
对于Windows Azure,如果你还在使用windowsazure.com门户来管理虚拟机,那就显得不怎么高上大了.Windows Azure PowerShell 是一个功能强大的脚本环境,可用 ...
- 防止SQL注入和XSS攻击Filter
nbsp;今天系统使用IBM的安全漏洞扫描工具扫描出一堆漏洞,下面的filter主要是解决防止SQL注入和XSS攻击 一个是Filter负责将请求的request包装一下. 一个是request包装器 ...
- SQL SERVER 常用字符类型的区别
长度为 n 个字节的固定长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为 n 个字节.char 在 SQL-92 中的同义词为 character. ...
- DBContext
http://www.entityframeworktutorial.net/EntityFramework4.3/dbcontext-vs-objectcontext.aspx As you hav ...
- 第一篇 ERP是什么?-从道的层面浅谈我的理解
世界上称为ERP软件的软件很多,国外的有SAP,ORACLE,国内的有金蝶,用友,浪潮.这些由不同的厂商开发制作的软件总有其软件适用的场合.这个场合就是企业,而且是市场经济中的企业.个人是不会购买ER ...