前言

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206种一棵树最好的时间是十年前,其次是现在

six-finger-web

一个Web后端框架的轮子从处理Http请求【基于Netty的请求级Web服务器】 到mvc【接口封装转发)】,再到ioc【依赖注入】,aop【切面】,再到 rpc【远程过程调用】最后到orm【数据库操作】全部自己撸一个(简易)的轮子。

github

为啥要写这个轮子

其实是这样的,小六六自己平时呢?有时候喜欢看看人家的源码比如Spring,但是小六六的水平可能不怎么样,每次看都看得晕头转向,然后就感觉里面的细节太难了,然后我就只能观其总体的思想,然后我就想我如果可以根据各位前辈的一些思考,自己撸一个简单的轮子出来,那我后面去理解作者的思想是不是简单点呢?于是呢 six-finger-web就面世了,它其实就是我的一个学习过程,然后我把它开源出来,希望能帮助那些对于学习源码有困难的同学。还有就是可以锻炼一下自己的编码能力,因为平时我们总是crud用的Java api都是那些,久而久之,很多框架类的api我们根本就不熟练了,所以借此机会,锻炼一下。

特点

  • 内置由 Netty 编写 HTTP 服务器,无需额外依赖 Tomcat 之类的 web 服务(刚好小六六把Netty系列写完,顺便用下)
  • 代码简单易懂(小六六自己写不出框架大佬那种高类聚,低耦合的代码),能力稍微强一点看代码就能懂,弱点的也没关系,小六六有配套的从0搭建教程。
  • 支持MVC相关的注解确保和SpringMVC的用法类似
  • 支持Spring IOC 和Aop相关功能
  • 支持类似于Mybatis相关功能
  • 支持类似于Dubbo的rpc相关功能
  • 对于数据返回,只支持Json格式

絮叨

此教程只适合初中级水平,因为作者本身水平不高,不喜勿喷,今天是文章的第一篇,所以先写的是 由Netty 搭建一个http服务器

使用Netty实现HTTP服务器

Netty是一个异步事件驱动的网络应用程序框架用于快速开发可维护的高性能协议服务器和客户端。Netty经过精心设计,具有丰富的协议,如FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。

Java程序员在开发web应用的时候,我们习惯于基于servlet规范,来做后端开发,就比如我们的SpringMVC其本质也是一个servlet,至于spring Webfux,我不知道有多少公司使用了,但是目前为止2020,我们公司是没有使用的,这次呢我们就试试用Netty来实现一下,其实这个很简单,以前的我写Netty系列的时候,我已经写过了,大家可以去找找https://github.com/bin392328206/six-finger

首先是创建项目

因为我们这个是six-finger-web的第一篇,所以我尽量把点点滴滴做到

首先创建一个maven项目,如果这个都不会的话,小六六建议先学习基础再来,在文章很多的地方,一些基础的小六六是默认你懂,如果有啥不懂的可以上github上找我联系方式,我如果有空会给大家解答的

  • 创建pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.xiaoliuliu</groupId><artifactId>six-finger-web</artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version><dependencies><!-- 为了代码简洁引入lombok,不需要再写setter和getter(可以不引入)--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency><!--动态代理相关--><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency><!-- Netty相关--><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.51.Final</version></dependency></dependencies>
</project>

HttpServer

Netty 编写 HTTP 服务器主类

package com.xiaoliuliu.six.finger.web.server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;import java.net.InetSocketAddress;/*** @author 小六六* @version 1.0* @date 2020/10/13 11:41* Netty 编写 HTTP 服务器* 主类*/
public class HttpServer {/*** @Des 端口 http请求的端口* @Author 小六六* @Date 2020/10/13 11:42* @Param* @Return*/int port;/*** @Des 构造方法* @Author 小六六* @Date 2020/10/13 11:42* @Param* @Return*/public HttpServer(int port) {this.port = port;}/*** @Des 服务的启动方法* @Author 小六六* @Date 2020/10/13 11:43* @Param* @Return*/public void start() throws Exception {//启动引导类ServerBootstrap bootstrap = new ServerBootstrap();NioEventLoopGroup boss = new NioEventLoopGroup();NioEventLoopGroup work = new NioEventLoopGroup();bootstrap.group(boss, work).handler(new LoggingHandler(LogLevel.DEBUG)).channel(NioServerSocketChannel.class).childHandler(new HttpServerInitializer());ChannelFuture cf = bootstrap.bind(new InetSocketAddress(port)).sync();System.out.println(" server start up on port : " + port);cf.channel().closeFuture().sync();}
}

HttpServerInitializer

package com.xiaoliuliu.six.finger.web.server;import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;/*** @author 小六六* @version 1.0* @date 2020/10/13 11:57* 用于配置 pipeline的处理链*/
public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();// http 编解码pipeline.addLast(new HttpServerCodec());// http 消息聚合器pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024));// 请求处理器pipeline.addLast(new HttpRequestHandler());}
}

HttpRequestHandler

package com.xiaoliuliu.six.finger.web.server;import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;import java.util.HashMap;
import java.util.Map;import static io.netty.handler.codec.http.HttpUtil.is100ContinueExpected;/*** @author 小六六* @version 1.0* @date 2020/10/13 12:01* 核心处理http请求的类,包括url的匹配核心方法都是在channelRead0方法*/
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {private static final String FAVICON_ICO = "/favicon.ico";private static final AsciiString CONNECTION = AsciiString.cached("Connection");private static final AsciiString KEEP_ALIVE = AsciiString.cached("keep-alive");@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) {ctx.flush();}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {System.out.println("获得的参数:"+req);if (is100ContinueExpected(req)) {ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.CONTINUE));}// 获取请求的uriString uri = req.uri();Map<String,String> resMap = new HashMap<>();resMap.put("method",req.method().name());resMap.put("uri",uri);String msg = "<html><head><title>小六六提醒你</title></head><body>你请求uri为:" + uri+"</body></html>";// 创建http响应DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));//设置头信息response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");//把消息输出到浏览器ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
}

ApplicationServer 测试类

package com.xiaoliuliu.six.finger.web.demo.server;import com.xiaoliuliu.six.finger.web.server.HttpServer;/*** @author 小六六* @version 1.0* @date 2020/10/13 14:26*  这个类 用于 搭建Netty web服务器的测试类,只适用于搭建教程的第一篇文章*/
public class ApplicationServer {public static void main(String[] args) throws Exception {HttpServer server = new HttpServer(8081);// 8081为启动端口server.start();}
}

测试结果

在浏览器上输入

http://localhost:8081/xiaoliuliu

我们看看输出

然后我们来看看控制台

发现多了一次请求,这个是什么原因呢?

这是因为HttpRequestDecoder把请求拆分成HttpRequest和HttpContent两部分,

所以我们要过滤哪个/favicon.ico的请求,所以改改代码

    if("/favicon.ico".equals(uri)) {System.out.println("请求了 favicon.ico, 不做响应");return;}

结尾

好了,今天我们用几十行代码实现了一个简单的Http服务器,很多的细节我们一一讲解,但是我的注释基本上都写了,如果你有看不懂的地方,欢迎你来找我,我有空会给大家解答的,然后下一章就是我们要写的SpringMVC相关的代码了。

日常求赞

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是真粉
创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章
六脉神剑 | 文 【原创】如果本篇博客有任何错误,请批评指教,不胜感激 !

apache为什么更适合处理动态请求_[适合初中级Java程序员修炼手册从0搭建整个Web项目](一)...相关推荐

  1. java web 显示项目下的图片_[适合初中级Java程序员修炼手册从0搭建整个Web项目](一)...

    前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206种一棵树最好的时间是十年前,其次是现在 six-finger-web 一个Web后端 ...

  2. java web项目_[适合初中级Java程序员修炼手册从0搭建整个Web项目](二)

    前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206种一棵树最好的时间是十年前,其次是现在 six-finger-web 一个Web后端 ...

  3. java程序员封闭_变态级JAVA程序员面试32问(转)

    第一,谈谈final, finally, finalize的区别. final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 ...

  4. 程序流程图_干货收藏 | Java 程序员必备的一些流程图

    阅读本文大概需要 6 分钟. 转载自:https://juejin.im/post/5d214639e51d4550bf1ae8df 1.Spring 的生命周期 Spring 作为当前 Java 最 ...

  5. 池流程图_干货收藏 | Java程序员必备的一些流程图

    前言: 整理了一些Java基础流程图/架构图,做一下笔记,大家一起学习. 1.spring的生命周期 Spring作为当前Java最流行.最强大的轻量级容器框架,了解熟悉spring的生命周期非常有必 ...

  6. 招聘java是什么意思_企业招聘Java程序员的标准到底是什么?

    为什么Java程序员找工作那么难?是否市场已经饱和?企业招聘Java程序员的标准是什么?很多找不到工作的Java程序员在经历过几次面试之后,就会对自己的技术能力产生怀疑,然而找工作和"酒香不 ...

  7. Java程序员情人节_七夕情人节 Java程序员如何表白

    作为程序员都有女朋友吗,木有女朋友的怎么办呢,也许你认为好办,那就一个字,追.看过<爱是从表白开始的>没,怎么着也得有个轰轰烈烈滴表白啊!下面就来看看程序员怎如何在七夕情人节来个创意表白吧 ...

  8. java配合什么做前端_作为一个java程序员 ,前端的技术需要达到什么水平?

    一个后端程序员,需要掌握前端技术吗? JSP时代 8年前,刚刚进入编程这个行业,当时的Web开发使用古老的SSH框架+JSP.那个时候,几乎所有的Java程序员都要懂得如何写JavaScript.如何 ...

  9. java 哪一个gc好_优秀的Java程序员必须了解的GC哪些

    作者丨灵犀一脚C http://www.cnblogs.com/ckwblogs/p/5975921.html 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的 ...

最新文章

  1. html css发展前景,网页设计的发展趋势
  2. idea2018.3.5集成scala开发环境
  3. 50 亿观众的 “云上奥运”,顶级媒体背后的数智化力量
  4. spring项目启动执行特定方法
  5. Facebook开源 PyTorch版 fairseq,准确性最高、速度比循环神经网络快9倍
  6. mongodb和mysql中自动增长id_MongoDB 自动增长
  7. 数学分析教程(科大)——1.6笔记+习题
  8. 基于Struts2的网上书城(仿当当网)系统
  9. 数学经典思想:数学归纳法 理解+实战
  10. python语言应用 智慧树满分章节测试答案_Python语言应用完整智慧树网课章节测试答案...
  11. 信息系统高级项目管理师英语词汇(一)-常见计算机技术词汇
  12. linux系统解压缩命令大全
  13. 阿里云ECS服务器环境搭建(2) —— ubuntu 16.04 安装中文输入法(搜狗输入法)
  14. 1.ffmpge的移植
  15. 计算机证是准入类吗,准入类与水平类证书的区别
  16. linux退出guest用户_linux中guest 用户就是nobody吗?
  17. java的tey语句return了_Java finally语句到底是在return之前还是之后执行?
  18. php滚动抽奖程序,PHP滚动抽奖代码
  19. 2019盖茨年信,以及30个关于比尔盖茨的真相
  20. C语言实现网页版扫雷

热门文章

  1. css 浮动和清除浮动
  2. 简化软件操作,提升用户体验
  3. php开发微信图灵机器人
  4. eureka-7-多网卡下的ip选择
  5. QScrollArea不能显示滚动条
  6. MyEclipse 6.5安装maven插件
  7. JAVA多线程和并发基础面试问答(转载)
  8. (转)会议期刊论文发表介绍(计算机科学领域)
  9. 介绍“Razor”— ASP.NET的一个新视图引擎
  10. 【SQL】sql版Split函数。用于拆分字符串为单列表格