java21 封装Response:
封装Response:
/**
* 封装响应信息
*/
public class Response {
//两个常量
public static final String CRLF="\r\n";
public static final String BLANK=" ";
//流
private BufferedWriter bw ; //正文
private StringBuilder content; //存储头信息
private StringBuilder headInfo;
//存储正文长度
private int len = ;
public Response(){
headInfo = new StringBuilder();
content = new StringBuilder();
len = ;
}
public Response(Socket client){
this();
try {
bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
} catch (IOException e) {
headInfo=null;
}
}
public Response(OutputStream os){
this();
bw = new BufferedWriter(new OutputStreamWriter(os));
}
/**
* 构建正文
*/
public Response print(String info){
content.append(info);
len += info.getBytes().length;
return this;
} /**
* 构建正文+回车
*/
public Response println(String info){
content.append(info).append(CRLF);
len += (info+CRLF).getBytes().length;
return this;
} /**
* 构建响应头
*/
private void createHeadInfo(int code){
//1) HTTP协议版本、状态代码、描述
headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
switch(code){
case :
headInfo.append("OK");
break;
case :
headInfo.append("NOT FOUND");
break;
case :
headInfo.append("SEVER ERROR");
break;
}
headInfo.append(CRLF);
//2) 响应头(Response Head)
headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF);
headInfo.append("Date:").append(new Date()).append(CRLF);
headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
//正文长度 :字节长度
headInfo.append("Content-Length:").append(len).append(CRLF);
headInfo.append(CRLF); //分隔符
}
//推送到客户端
void pushToClient(int code) throws IOException{
if(null==headInfo){
code =;
}
createHeadInfo(code);
//头信息+分割符
bw.append(headInfo.toString());
//正文
bw.append(content.toString());
bw.flush();
}
public void close(){
CloseUtil.closeIO(bw);
} } 测试:
/**
* 创建服务器,并启动
* 1、请求
* 2、响应
*/
public class Server4 {
private ServerSocket server;
public static final String CRLF="\r\n";
public static final String BLANK=" "; public static void main(String[] args) {
Server4 server = new Server4();
server.start();
}
/**
* 启动方法
*/
public void start(){
try {
server = new ServerSocket();
this.receive();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 接收客户端
*/
private void receive(){
try {
Socket client =server.accept();
byte[] data=new byte[];
int len =client.getInputStream().read(data);
//接收客户端的请求信息
String requestInfo=new String(data,,len).trim();
System.out.println(requestInfo);
//响应
Response rep=new Response(client.getOutputStream());
rep.println("<html><head><title>HTTP响应示例</title>");
rep.println("</head><body>Hello server!</body></html>");
rep.pushToClient(); } catch (IOException e) {
}
}
public void stop(){
}
} 封装Request:
/**
* 封装request
*/
public class Request {
//请求方式
private String method;
//请求资源
private String url;
//请求参数
private Map<String,List<String>> parameterMapValues; //内部
public static final String CRLF="\r\n";
private InputStream is;
private String requestInfo; public Request(){
method ="";
url ="";
parameterMapValues=new HashMap<String,List<String>>();
requestInfo="";
}
public Request(InputStream is){
this();
this.is=is;
try {
byte[] data = new byte[];
int len = is.read(data);
requestInfo = new String(data, , len);
} catch (Exception e) {
return ;
}
//分析请求信息
parseRequestInfo();
}
/**
* 分析请求信息
*/
private void parseRequestInfo(){
if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){
return ;
}
/**
* =====================================
* 从信息的首行分解出 :请求方式 请求路径 请求参数(get可能存在)
* 如:GET /index.html?name=123&pwd=5456 HTTP/1.1
*
* 如果为post方式,请求参数可能在 最后正文中
*
* 思路:
* 1)请求方式 :找出第一个/ 截取即可
* 2)请求资源:找出第一个/ HTTP/
* =====================================
*/
String paramString =""; //接收请求参数 //1、获取请求方式
String firstLine =requestInfo.substring(,requestInfo.indexOf(CRLF));
int idx =requestInfo.indexOf("/"); // /的位置
this.method=firstLine.substring(, idx).trim();
String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
if(this.method.equalsIgnoreCase("post")){
this.url=urlStr;
paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim(); }else if(this.method.equalsIgnoreCase("get")){
if(urlStr.contains("?")){ //是否存在参数
String[] urlArray=urlStr.split("\\?");
this.url=urlArray[];
paramString=urlArray[];//接收请求参数
}else{
this.url=urlStr;
}
} //不存在请求参数
if(paramString.equals("")){
return ;
}
//2、将请求参数封装到Map中
parseParams(paramString);
}
private void parseParams(String paramString){
//分割 将字符串转成数组
StringTokenizer token=new StringTokenizer(paramString,"&");
while(token.hasMoreTokens()){
String keyValue =token.nextToken();
String[] keyValues=keyValue.split("=");
if(keyValues.length==){
keyValues =Arrays.copyOf(keyValues, );
keyValues[] =null;
}
String key = keyValues[].trim();
String value = null==keyValues[]?null:decode(keyValues[].trim(),"gbk");
//转换成Map 分拣
if(!parameterMapValues.containsKey(key)){
parameterMapValues.put(key,new ArrayList<String>());
}
List<String> values =parameterMapValues.get(key);
values.add(value);
}
}
/**
* 解决中文
* @param value
* @param code
* @return
*/
private String decode(String value,String code){
try {
return java.net.URLDecoder.decode(value, code);
} catch (UnsupportedEncodingException e) {
//e.printStackTrace();
}
return null;
}
/**
* 根据页面的name 获取对应的多个值
* @param args
*/
public String[] getParameterValues(String name){
List<String> values=null;
if((values=parameterMapValues.get(name))==null){
return null;
}else{
return values.toArray(new String[]);
}
}
/**
* 根据页面的name 获取对应的单个值
* @param args
*/
public String getParameter(String name){
String[] values =getParameterValues(name);
if(null==values){
return null;
}
return values[];
}
public String getUrl() {
return url;
}
}
测试:
/**
* 创建服务器,并启动
* 1、请求
* 2、响应
*/
public class Server5 {
private ServerSocket server;
public static final String CRLF="\r\n";
public static final String BLANK=" "; public static void main(String[] args) {
Server5 server = new Server5();
server.start();
}
/**
* 启动方法
*/
public void start(){
try {
server = new ServerSocket();
this.receive();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 接收客户端
*/
private void receive(){
try {
Socket client =server.accept();
//请求
Request req=new Request(client.getInputStream());
//响应
Response rep=new Response(client.getOutputStream());
rep.println("<html><head><title>HTTP响应示例</title>");
rep.println("</head><body>");
rep.println("欢迎:").println(req.getParameter("uname")).println("回来");
rep.println("</body></html>");
rep.pushToClient();
} catch (IOException e) {
}
} /**
* 停止服务器
*/
public void stop(){ }
} 加入Servlet:
public class Servlet {
public void service(Request req,Response rep){
rep.println("<html><head><title>HTTP响应示例</title>");
rep.println("</head><body>"); rep.println("欢迎:").println(req.getParameter("uname")).println("回来");
rep.println("</body></html>");
}
}
/**
* 接收客户端
*/
private void receive(){
try {
Socket client =server.accept();
Servlet serv =new Servlet();
Request req =new Request(client.getInputStream());
Response rep =new Response(client.getOutputStream());
serv.service(req,rep);
rep.pushToClient(); //通过流写出去
} catch (IOException e) {
}
} 服务端利用多线程:
/**
* 创建服务器,并启动
* 1、请求
* 2、响应
*/
public class Server7 {
private ServerSocket server;
public static final String CRLF="\r\n";
public static final String BLANK=" "; private boolean isShutDown= false; public static void main(String[] args) {
Server7 server = new Server7();
server.start();
}
/**
* 启动方法
*/
public void start(){
start();
}
/**
* 指定端口的启动方法
*/
public void start(int port){
try {
server = new ServerSocket(port);
this.receive();
} catch (IOException e) {
//e.printStackTrace();
stop();//启动出错则stop。
}
}
/**
* 接收客户端
*/
private void receive(){
try {
while(!isShutDown){
new Thread(new Dispatcher(server.accept())).start();
}
} catch (IOException e) {
stop();
}
} /**
* 停止服务器
*/
public void stop(){
isShutDown=true;
CloseUtil.closeSocket(server);
}
} /**
* 一个请求与响应 就一个此对象
*/
public class Dispatcher implements Runnable{
private Socket client;
private Request req;
private Response rep;
private int code=;
Dispatcher(Socket client){
this.client=client;
try {
req =new Request(client.getInputStream());
rep =new Response(client.getOutputStream());
} catch (IOException e) {
code =;//统一到推送地方去推送。
return ;
}
}
@Override
public void run() {
Servlet serv =new Servlet();
serv.service(req,rep);
try {
rep.pushToClient(code); //流推送到客户端
} catch (IOException e) {
}
try {
rep.pushToClient();
} catch (IOException e) {
e.printStackTrace();
}
CloseUtil.closeSocket(client);
}
} public class CloseUtil {
/**
* 关闭IO流
*/
/*
public static void closeIO(Closeable... io){
for(Closeable temp:io){
try {
if (null != temp) {
temp.close();
}
} catch (Exception e) {
}
}
}*/
/**
* 使用泛型方法实现关闭IO流
* @param io
*/
public static <T extends Closeable> void closeIO(T... io){
for(Closeable temp:io){
try {
if (null != temp) {
temp.close();
}
} catch (Exception e) {
}
}
}
public static void closeSocket(ServerSocket socket){
try {
if (null != socket) {
socket.close();
}
} catch (Exception e) {
}
}
public static void closeSocket(Socket socket){
try {
if (null != socket) {
socket.close();
}
} catch (Exception e) {
}
}
public static void closeSocket(DatagramSocket socket){
try {
if (null != socket) {
socket.close();
}
} catch (Exception e) {
}
}
}
java21 封装Response:的更多相关文章
- DRF框架(五)——context传参,二次封装Response类,两个视图基类(APIView/GenericAPIView),视图扩展类(mixins),子类视图(工具视图),视图集(viewsets),工具视图集
复习 1.整体修改与局部修改 # 序列化get (给前端传递参数) #查询 ser_obj = ModelSerializer(model_obj) #只传递一个参数,默认是instance的参数,查 ...
- 二次封装Response类 | 视图类传递参数给序列化类context
二次封装Response类 源码: class Response(SimpleTemplateResponse): """ An HttpResponse that al ...
- drf序列化高级、自定义只读只写、序列化覆盖字段、二次封装Response、数据库查询优化(断关联)、十大接口、视图家族
目录 自定义只读 自定义只写 序列化覆盖字段 二次封装Response 数据库关系分析 断外键关联关系 ORM操作外键关系 ORM四种关联关系 基表 系列化类其他配置(了解) 十大接口 BaseSer ...
- 3.后台配置、环境变量、日志、异常处理、二次封装Response、路由组件
目录 环境变量 封装logger 封装项目异常处理 二次封装Response模块 路由组件配置 环境变量 dev.py # 环境变量操作:小luffyapiBASE_DIR与apps文件夹都要添加到环 ...
- 5) ModelSerializer(重点) 基表 测试脚本 多表关系建外键 正反查 级联 插拔式连表 序列化反序列化整合 增删查 封装response
一.前戏要做好 配置:settings.py #注册drf INSTALLED_APPS = [ # ... 'api.apps.ApiConfig', 'rest_framework', ] # ...
- Django(53)二次封装Response
前言 有时候我们使用drf的Response,会发现默认返回的格式不太友好,每次我们都需要写入以下的格式 return Response({ "status": 0, " ...
- 项目依赖模块解决、二次封装Response、后台数据库配置、user模块user表设计、前台创建及配置
今日内容概要 二次封装Response 后台数据库配置 user模块user表设计 前台创建及配置 内容详细 补充--项目依赖模块 # 导出项目依赖模块和安装项目依赖模块 第三方模块--->导出 ...
- Alamofire源码解读系列(九)之响应封装(Response)
本篇主要带来Alamofire中Response的解读 前言 在每篇文章的前言部分,我都会把我认为的本篇最重要的内容提前讲一下.我更想同大家分享这些顶级框架在设计和编码层次究竟有哪些过人的地方?当然, ...
- Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(一)
1,其实早就想把这些东西给封装封装的,一直没有时间,今天刚好项目进入到测试阶段了,Bug同事在哪儿测试的飞起,但发现提bug的尽然是我(得意脸),然后上午把ios的包测试了一下,顺便把服务器给测挂了( ...
随机推荐
- js设置radio选中
在页面数据绑定时,经常会遇到给radio设置选中,以下是我写的js方法,经测试可以使用.欢迎拍砖 <html> <head> <script type="tex ...
- redis高性能客户端 - redissdk
我们首先在我们自己的工程下放置redis.properties,内容如下: #redis地址 server=192.168.0.8 #redis端口 port=6379 auth=admin max_ ...
- BZOJ_1612_[Usaco2008_Jan]_Cow_Contest_奶牛的比赛_(dfs)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1612 \(n\)头奶牛比赛,给出一些胜负情况,问可以确定多少头奶牛的排名. 分析 无论胜负,只 ...
- [WebKit]浏览器的加载与页面性能优化
非常棒.非常系统的一份资料,值得阅读! 原文来自百度泛用户体验. 作者:nwind 本文将探讨浏览器渲染的loading过程,主要有2个目的: 了解浏览器在loading过程中的实现细节,具体都做了什 ...
- Servlet能读到JSessionID,读不到其它cookie问题
Servlet的Cookie值保存与获取 今天测试设置和获取Cookie遇到了一点小问题,很奇怪的问题: 把J2ee服务部署在本地 8080端口:访问任何一个服务时,如果客户端没有cookie,则下发 ...
- scp linux远程拷贝和本地拷贝命令
linux远程拷贝和本地拷贝命令 一.linux对linux 远程拷贝 scp命令 scp 文件名 root@远程ip:/路径/ 将本地home目录下的test.tar的文件拷贝 ...
- pop3
POP3_Client pop3 = new POP3_Client(); pop3, false); pop3.Authenticate("username", "pa ...
- Vim 的粘贴复制功能
Vim作为最好用的文本编辑器之一,使用vim来编文档,写代码实在是很惬意的事情.每当学会了vim的一个新功能,就会很大地提高工作效率.有人使用vim几十年,还没有完全掌握vim的功能,这也说明了vim ...
- nyoj 96 一个水题目
虽然很简单,发现自己用内存太高了了,算了,我就是这水平了. 描述 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数. 输入 第一行为M,表示 ...
- aix 文件大小相关查询
一.aix中查看文件夹占用空间大小 du命令默认是显示当前目录下每个文件以及每个子目录以及下属文件的大小的 用du -sg 可看出当前文件夹的大小,包括文件夹下文件和文件夹(以G为单位):用du -s ...