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

前言

文本已收录至我的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的第一篇,所以我尽量把点点滴滴做到

b935606476453ffe94365bbbf7fc4547.png

首先创建一个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

我们看看输出

e96d13a51d74ef99736498ba1532efbf.png

然后我们来看看控制台

e279ef03a4ffe04c8e65396861aff71d.png

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

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

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

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

结尾

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

9c604411fb9adec80f745e807032dc73.png

日常求赞

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python如何自动缩进_Python缩进

缩进出现问题&#xff0c;运行不出来。 正确代码如下&#xff1a;1 defbinary_search(list, item):2 low 03 high len(list)-1 4 5 while low <high:6 mid (low high)7 guess list[mid]8 if guess item:9 returnmid10 if guess >item:11 high mid-1 12 else:13 low m…

差分约束系统详解

一直不知道差分约束是什么类型题目&#xff0c;最近在写最短路问题就顺带看了下&#xff0c;原来就是给出一些形如x-y<b不等式的约束&#xff0c;问你是否满足有解的问题 好神奇的是这类问题竟然可以转换成图论里的最短路径问题&#xff0c;下面开始详细介绍下 比如给出三…

1.1.1.1校园网_Apache Flink 1.11.0 重要功能全面解析

来源 | Apache Flink 官方博客翻译 | 高赟(云骞)Apache Flink 社区很荣幸的宣布 Flink 1.11.0 版本正式发布&#xff01;超过 200 名贡献者参与了 Flink 1.11.0 的开发&#xff0c;提交了超过 1300 个修复或优化。这些修改极大的提高了 Flink 的可用性&#xff0c;并且增强了各…

显示控制器注释_欧姆龙可编程控制器CS1D-CPU产品型号说明及功能介绍

欧姆龙可编程控制器CS1D-CPU用CPU单元 CPU单元(用于双CPU系统)欧姆龙可编程控制器CS1D-CPU用CPU单元 特点可以轻松引入、使用高可靠性系统成双配备CPU单元轻松易行CPU单元内的程序或内部数据在活动/备用CPU之间完全进行自动传送并进行同步。 无需选择要同步的数据或单独进行传送…

js取字符串后四位_JS逆向 | 某验滑块加密参数逆向分析

声明&#xff1a;本文只作学习研究&#xff0c;禁止用于非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请告知删除&#xff0c;谢谢&#xff01;aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vZGVtby9zbGlkZS1mbG9hdC5odG1s抓包分析&#xff0c;看到一个加密参数w&…

挖掘城市ip_德国卡尔斯草莓农庄:旅游IP打造要创意更要形象!

什么是IP?名人圈&#xff1a;杨超越游戏圈&#xff1a;王者荣耀影视界&#xff1a;延禧攻略出版界&#xff1a;Harry Potter相声界&#xff1a;郭德纲……别忙着争先恐后&#xff0c;知道你的IP数不胜数~~你知道的IP数不胜数&#xff0c;一个人、一部作品、一个品牌、一座城市…

rust种的南瓜为什么老是消失_冷天早餐别将就,用南瓜和萝卜这样做,鲜香松软,营养好吃又管饱...

导语&#xff1a;11月我家爱吃这菜&#xff0c;加根萝卜简单一卷&#xff0c;有颜有料&#xff0c;孩子经常点名吃。冷天早餐别将就&#xff0c;用南瓜和萝卜这样做&#xff0c;鲜香松软&#xff0c;营养好吃又管饱“南瓜再大本地卖&#xff0c;辣椒再小穿省过”记得悦悦小时候…

windows下搭建python运行环境

今天python的环境炸了&#xff0c;刚好也重新做一下&#xff0c;记录下折腾的过程。 文件下载 首先打开官网&#xff0c;找到对应的文件的下载索引。 https://www.python.org/downloads/windows/ 其中3.7.0是版本号&#xff0c;a是代表稳定版本&#xff0c;b代表的是测试版本&…

python中isalpha的用法_python函数--isalpha()方法

原博文 2019-09-26 10:59 − isalpha()方法 描述&#xff1a;Python isalpha() 方法检测字符串是否只由字母组成。isalpha()方法语法&#xff1a;str.isalpha()参数&#xff1a;无。返回值&#xff1a;如果字符串至少有一个字符并且所有字符都是字母则返回 True,否则返回 False…

C#数据结构-单链表

理论基础&#xff1a; 链表是用一组任意的存储单元来存储线性表中的数据元素。 如果结点的引用域只存储该结点直接后继结点的存储地址&#xff0c;则该链表叫单链表(Singly Linked List)。 单链表由头引用H唯一确定。头引用指向单链表的第一个结点&#xff0c;也就是把单链表第…

pandas 根据单号分类_由 “猫捉老鼠”游戏联想的用户分类问题

一、说在最前 用户识别&#xff0c;用户分类&#xff0c;精准营销…这是咱们业务人员常常念叨的话。底层逻辑为无论任何营销目的&#xff0c;在营销手段上&#xff0c;越针对某一细化群体&#xff0c;达成目的的概率也就会越大。那今天就来和大家说道说道用户识别/分类的一种方…

arraylist从大到小排序_java基础算法之二叉树排序(递归)

一、二叉树介绍在计算机科学中&#xff0c;二叉树是每个结点最多有两个子树的树结构。二叉树由各种节点组成&#xff0c;如下图所示&#xff1a;每个节点都可以有左子节点&#xff0c;右子节点每一个节点都有一个值二叉树遍历&#xff1a;二叉树的遍历分左序&#xff0c;中序&a…

uvm 形式验证_IC设计职位详解之“数字验证工程师”就业必学课程

数字验证处于数字IC设计流程的前端&#xff0c;属于数字IC设计类岗位的一种。在IC设计中&#xff0c;数字验证所占的人数比重是非常多的&#xff0c;很多大公司&#xff0c;数字前端设计工程师与验证工程师的比例已经达到1&#xff1a;3。数字验证主要分成几种层次的验证&#…

关联查询数据重复怎么办_在设计数据表的时候,是一个宽表好,还是多个维度表好?...

数据仓库每张表的搭建&#xff0c;主要依赖于这个表在整个数据仓库中的作用和相关意义。首先要清楚这个表的存在是为了解决那些问题&#xff0c;什么角色使用&#xff0c;怎么保证使用者尽可能好的体验解决问题。从以上所提到的角度去看待问题&#xff0c;拆解以下几点因素&…

用python画出叶子_太疯狂了!原来用粉笔画画,也可以这么美,简单几招教你,美到邻居羡慕嫉妒...

......点进来之前先让大家瞧瞧相信这是用粉笔画的吗&#xff1f;▼玫瑰花▼山茶花▼蓝色鸢尾花▼樱花树▼这一张张让人直流鼻血的作品没错这就是用色粉笔画出来的很多人问&#xff1a;是不是平时老师上课时用的粉笔呢&#xff1f;这里给大家科普下&#xff1a;色粉画&#xff0…

jsonp react 获取返回值_必须要会的 50 个React 面试题(下)

翻译&#xff1a;疯狂的技术宅原文&#xff1a;https://www.edureka.co/blog/interview-questions/react-interview-questions29. 你对受控组件和非受控组件了解多少&#xff1f;受控组件非受控组件1. 没有维持自己的状态1. 保持着自己的状态2.数据由父组件控制2.数据由 DOM 控…

snipaste截图软件滚动截图_截图工具的逆袭,Snipaste 还可以这么玩

这是我们的历史文章。为让大家更好找到自己需要的软件&#xff0c;我们会在三条位置推送&#xff0c;那些备受关注的APP和软件。提到「截图」大家会想到什么呢&#xff1f;微信&#xff0c;QQ 或者 功能更加完善的截图工具&#xff1f;有想过「截图」可以这样用吗&#xff1f;还…

plsql developer无监听程序_微信小程序支持分享到朋友圈啦!技术解读跟我来

千呼万唤始出来&#xff01;微信小程序页面分享到朋友圈的功能&#xff0c;终于在安卓系统灰度测试了&#xff01;目前只在安卓系统&#xff01;只在安卓系统&#xff01;只在安卓系统&#xff01;iOS系统还没有办法体验。首先&#xff0c;我们看一下官方文档的描述&#xff0c…

mixin network_【译文】Mixin——以最高的安全性满足所有区块链资产的交易需求

一个免费的闪电般快速的数字资产端对端交易网络。01.概况Mixin 由一个理论上永久的内核、许多动态域和不同的多用途域扩展组成&#xff0c;以构成扩展的星形拓扑结构。Mixin Network 已经支持 BTC&#xff0c;BCH&#xff0c;ETH&#xff0c;EOS&#xff0c;ETC&#xff0c;SC&…

python柱形图代码_Python数据可视化:基于matplotlib绘制「条形图」

简介 条形图 &#xff08;bar chart&#xff09;是用宽度相同条形的高度或长短来表示数据多少的图形&#xff0c;可以横置或纵置。纵置时的条形图也称为 柱形图 &#xff08;column chart&#xff09;。 绘制条形图 1 import matplotlib.pyplot as plot 2 3 data [5., 25., 50…