FHTTP: 一个简洁易用的java http框架
FHTTP抛弃了已有的web服务器,从serversocket开始,
直接构建http服务,并对使用者提供简单的使用方法
本框架为学习http1.1协议构建
框架内部所有数据全部使用utf-8编码处理且不支持修改
version: 1.0
使用方法
启动服务器
首先,在main方法中,需要用以下代码开启一个http服务
new FHTTP("项目类路径").start();
其中,项目类路径非常重要,框架将在这个路径上搜索其它代码,
一般选择main函数所在类的路径作为项目类路径
以上代码会默认开启一个监听端口为8080的socket,如果想要更改端口,
请使用FHTTP类的setPort(int port)方法,例如
var fhttp = new FHTTP("项目类路径");
fhttp.setPort(8000);
使用FHTTP的getPort方法可以获得当前监听的端口
编写Controller
一旦框架启动,框架会在类路径范围内所有目录下搜索带有@Controller注解的类,
并寻找类中标有@Mapping注解的方法,一旦寻找成功,框架会将http请求中的url对应到相应的方法上,使用方法如下
@Controller
public class Test2 {
@Mapping("/")
public Object handleIndex() {
return something;
}
@Mapping("/x")
public void handleX() {
//TODO
}
}
当浏览器访问url为/时,框架将会调用Test2中的handleIndex方法,
当浏览器访问url为/x时,框架将会调用Test2中的handleX方法
Controller注解中也可以写入url,例如
@Controller("/c1")
public class Test2 {
@Mapping("/")
public Object handleIndex() {
return something;
}
@Mapping("/x")
public void handleX() {
//TODO
}
}
此时,如果想调用handleIndex方法,就需要浏览器访问url为/c1/,
想调用handleX方法,就需要浏览器访问url为/c1/x。
这样,不同的Controller类可以对应一组不同的url。
如何在方法中区分不同的http method,只需要在方法头部加入不同的注解即可,
框架支持get, post, put, delete, head 5种http方法。
如果在方法头部加上@Post注解,则该方法会对应到post方法上,如果此时用其它方法比如get访问对应的url,则会收到404错误。
相应的,@Put @Delete @Head注解会对应到相应的http方法,如果这些注解都没有,则默认对应到get方法。
Mapping方法
标记有@Mapping的方法,可以返回任意类型数据,也可以为void,框架内部有对应的处理方法。
框架规定,如果方法返回的数据可被解析为文本,则调用返回对象的toString方法,否则,将直接把返回对象转换为byte[]类型。
框架内部定义了一些注解,例如@JSON, @MIME, @Status,下面讲解这三个注解的使用方法。
@JSON
可以在方法头部加上@JSON注解,表示该方法返回的对象可以被json序列化,框架内部使用google的gson来序列化对象,
并向浏览器返回application/json的数据。
@MIME
在方法头部加上@MIME注解,表示该方法返回数据的mime类型,例如
@MIME("text/javascript")
public Object handle() {return "";}
不要忘记@Mapping注解!
@Status
在方法头部加上@MIME注解,表示该方法对应url的处理结果,例如
@Status("200 OK")
public Object handle() {return "";}
不要忘记@Mapping注解!
框架内部会默认将处理结果设置为200 OK,所以若处理结果是200 OK将额外不必设置。
方法参数
实际上框架支持任意多个参数的方法,这些参数有如下对应规则
- 若参数的类型为Response, 框架会将当前浏览器请求对应的Response对象传给方法
- 若参数的类型为Request, 框架会将当前浏览器请求对应的Request对象传给方法
- 若参数标记有Param系列注解,框架会将对应的浏览器参数通过gson反序列化传给方法
以上参数没有先后顺序
Response方法
public Object handle(Response response) {return "";}
Request方法
public Object handle(Request request) {return "";}
二者组合
public Object handle(Request request, Response response) {return "";}
不要忘记@Mapping注解!
Param系列注解有三个,分别是@PathParam, @UrlParam, @BodyParam,
分别对应动态路由参数,get方法参数,post等参数在请求体的情况,使用方法如下
/**
* 定义一个javaBean
*/
public class User {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
@Controller
public class Test2 {
@Mapping("/name/:userName")
public Object handleIndex(@PathParam User user) {
//当url为/name/张三时,user.userName为张三
}
@Mapping("/name")
public void handleX(@UrlParam User user) {
//当url为/name?userName=张三 时,user.userName为张三
}
@Post
@Mapping("/name")
public void handlePost(@BodyParam User user) {
//当通过表单或者javascript formdata body以post访问时,user.userName为张三
}
}
Response类
参数中的Response类,提供了以下功能
@Controller
public class Test2 {
@Mapping("/t1")
public Object t1(Response response) {
response.staticFile("文件路径"); //此方法向浏览器返回本地文件,并自动设置mime类型
response.getMimeType(); //获取当前数据的mimeType
response.setMimeType(mimeType); //设置mimeType
response.setHeadPair(key, value); //以键值对的形式设置response header,允许重复
response.setText(text); //设置response主体部分
response.setStatusCode(code); //设置url处理结果
response.setDispose(dispose); //设置response dispose
response.setStaticCache(isCache); //设置是否开启staticFile内部缓存,默认开启
response.setCacheSecond(cacheSecond); //设置http强缓存有效时间,单位为秒,默认为两天
}
}
staticFile读取文件时,默认会将文件缓存到内存中以加快读写速度,可以使用setStaticCache关闭
为加快速度,框架内部会对所有非文本类型数据作http缓存处理,
可以通过setCacheSecond设置强缓存有效时间。
mimeType设置的顺序是 方法内部response > MIME注解设置 > 默认设置
statusCode设置顺序是 方法内部response > Status注解设置 > 默认设置
Request类
参数中的Request类,提供了以下功能
@Controller
public class Test2 {
@Mapping("/t1")
public Object t1(Request request) {
String value = request.getHeadValue(key); //获取request头部键数据
byte[] data = request.getParamValue(key); //获取一个request body体中的表单数据
//以下代码获取一个由body体传来的userName参数,过于麻烦,建议使用@BodyParam注解代替
var userName = new String(request.getParamValue("userName"), StandardCharsets.UTF_8).split(":::")[1];
//以下代码获取一个由body体传来的file二进制文件
byte[] buffer = new String(request.getParamValue("userName"), StandardCharsets.ISO_8859_1).split(":::")[1].getBytes(StandardCharsets.ISO_8859_1);
}
}