当前位置: 首页 > news >正文

陕西服装网站建设seo排名优化怎么样

陕西服装网站建设,seo排名优化怎么样,关于我的大学的网站建设模板,网站建设制作需求前言: 之前,我们写了两个版本的 Http 服务器,本篇,再继续实现第三个版本 V3 将满足: 1.支持返回一个静态的 html 文件 2.解析处理 cookie (把 cookie 处理成键值对结构) 3.解析处理 body (把 body 中的数据处理成键值对…

前言:
之前,我们写了两个版本的 Http 服务器,本篇,再继续实现第三个版本
V3 将满足:
1.支持返回一个静态的 html 文件
2.解析处理 cookie (把 cookie 处理成键值对结构)
3.解析处理 body (把 body 中的数据处理成键值对结构)
4.实现一个完整的登录功能 (session 的简单实现)

request 类:

public class Request {private String method;private String url;private String version;private Map<String,String> headers = new HashMap<>();// url 中的参数和 body中的参数都放在 parameters 哈希表里private Map<String,String> parameters = new HashMap<>();private Map<String,String> cookies = new HashMap<>();private String body;public static Request build(InputStream inputStream) throws IOException {Request request = new Request();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));//1.处理首行String fistLine = bufferedReader.readLine();String[] firstLineTokens = fistLine.split(" ");request.method = firstLineTokens[0];request.url = firstLineTokens[1];request.version = firstLineTokens[2];//2.解析 urlint pos = request.url.indexOf("?");if(pos != -1){String queryString = request.url.substring(pos + 1);parseKV(queryString,request.parameters);}//3.循环处理 header 部分String line = "";while ((line = bufferedReader.readLine()) != null && line.length() != 0){String[] headerTokens = line.split(": ");request.headers.put(headerTokens[0],headerTokens[1]);}//4.解析 cookieString cookie = request.headers.get("Cookie");if(cookie != null){// 把 cookie 进行解析parseCookie(cookie,request.cookies);}//5.解析 bodyif("POST".equalsIgnoreCase(request.method)|| "PUT".equalsIgnoreCase(request.method)) {// 其他方法暂时不考虑// 需要把 body 读取出来// 此处的长度单位是 "字节"int contentLength = Integer.parseInt(request.headers.get("Content-Length"));// contentLength 长度单位是字节// contentLength 为100, body中有100个字节// 创建的缓冲区长度是 100个char (相当于200个字符)char[] buffer = new char[contentLength];int len = bufferedReader.read(buffer);request.body = new String(buffer,0,len);// body 中的格式形如: username=huahua&password=666parseKV(request.body, request.parameters);}return request;}private static void parseCookie(String cookie, Map<String, String> cookies) {//1.按照 "; " 拆分成多个键值对String[] KVTokens = cookie.split(": ");//2.按照 = 拆分每个键和值for(String kv : KVTokens){String[] result = kv.split("=");cookies.put(result[0],result[1]);}}private static void parseKV(String queryString, Map<String, String> parameters) {//1.按照 & 拆分成多个键值对String[] KVTokens = queryString.split("&");//2.按照 = 拆分每个键和值for(String kv : KVTokens){String[] result = kv.split("=");parameters.put(result[0],result[1]);}}public String getMethod() {return method;}public String getUrl() {return url;}public String getVersion() {return version;}public String getBody() {return body;}public String getParameter(String key) {return parameters.get(key);}public String getHeader(String key) {return headers.get(key);}public String getCookie(String key) {return cookies.get(key);}
}

response 类:

public class Response {private String version = "HTTP//1.1";private int status;private String message;private Map<String,String> headers = new HashMap<>();private StringBuilder body = new StringBuilder(); //方便拼接private OutputStream outputStream = null;//工厂方法public static Response build(OutputStream outputStream){Response response = new Response();response.outputStream = outputStream;return response;}public void setVersion(String version) {this.version = version;}public void setStatus(int status) {this.status = status;}public void setMessage(String message) {this.message = message;}public void setHeader(String key,String value) {headers.put(key,value);}public void writeBody(String content) {body.append(content);}public void flush() throws IOException {BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));bufferedWriter.write(version + " " + status + " " + message + "\n");headers.put("Content-Length", body.toString().getBytes().length + " ");for (Map.Entry<String,String> entry : headers.entrySet()) {bufferedWriter.write(entry.getKey() + ": " + entry.getValue() + "\n");}bufferedWriter.write("\n");bufferedWriter.write(body.toString());bufferedWriter.flush();}
}

主类:

public class HttpServerV3 {private ServerSocket serverSocket = null;public HttpServerV3(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动...");ExecutorService executorService = Executors.newCachedThreadPool();while (true) {Socket clientSocket = serverSocket.accept();executorService.execute(new Runnable() {@Overridepublic void run() {process(clientSocket);}});}}public void process(Socket clientSocket){try {//1.读取请求并解析Request request = Request.build(clientSocket.getInputStream());Response response = Response.build(clientSocket.getOutputStream());//2.根据请求计算响应 按照不同的 Http 方法,拆分成不同的逻辑if("GET".equalsIgnoreCase(request.getMethod())){doGet(request,response);}else if("POST".equalsIgnoreCase(request.getMethod())){doPost(request,response);}else{// 其他方法,返回一个405response.setStatus(405);response.setMessage("Method Not Allowed");}//3.把响应写回客户端response.flush();} catch (IOException | NullPointerException e) {e.printStackTrace();} finally {try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}private void doGet(Request request, Response response) throws IOException {//1.能够支持返回一个 html 文件if(request.getUrl().startsWith("/index.html")){// 让代码读取一个 /index.html 这样的文件// 要想读文件,需要先知道文件路径 (只知道文件名)// 此时 html 文件所属的路径,可以自己约定// 把文件内容写到响应的 body 中response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html; charset=utf-8");// HttpServerV3.class获取一个类对象// getClassLoader() 获取当前类的类加载器InputStream inputStream = HttpServerV3.class.getClassLoader().getResourceAsStream("index.html");BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));//按行读取内容,把数据写入到 response 中String lint = " ";while ((lint = bufferedReader.readLine()) != null){response.writeBody(lint + "\n");}bufferedReader.close();}}private void doPost(Request request, Response response) {}public static void main(String[] args) throws IOException {HttpServerV3 httpServerV3 = new HttpServerV3(6060);httpServerV3.start();}
}

要想能够支持返回一个 html 文件,就需要让代码读取一个 类似 /index.html 这样的文件,要想读文件,需要先知道文件路径 (但我们只知道文件名)

解决方法:

new 一个 和 src 同级的 Directory

在这里插入图片描述
右击新创建的 xxx (Directory):Mark Directory as — xxx Root

在这里插入图片描述
然后 new 一个 file:index.html

<html>
<head><title>登录界面</title><meta charset="UTF-8">
</head><body><!-- /login操作服务器端还没有实现 --><form method="post" action="/login"><div style="margin-bottom: 8px"><input type="text" name="username" placeholder="请输入用户名"></div><div style="margin-bottom: 8px"><input type="password" name="password" placeholder="请输入密码"></div><div><input type="submit" value="登录"></div></form>
</body></html>

写到这里,服务器已经可以返回一个指定的静态页面了
这个页面中包含了一个 form 表单,借助表单来实现登录操作

在这里插入图片描述
此时,启动服务器

在这里插入图片描述

由于表单是把数据提交到 /login 这个 path 中
服务器紧接着就要实现 POST 请求下的 /login 的处理

doPost 方法:

private void doPost(Request request, Response response) {//2.实现 /login 的处理if(request.getUrl().startsWith("/login")) {//读取用户提交的用户名和密码String userName = request.getParameter("username");String password = request.getParameter("password");System.out.println("userName: " + userName);System.out.println("password: " + password);}
}

再次重启服务器,使用 fiddler 抓包:

在这里插入图片描述

流程:

接着,请求到达服务器上,解析成 Request 对象
用户名和密码这种键值对,就保存到 body 中,同时会把 body 中的键值对解析保存到 parameters 表中

在这里插入图片描述
doPost 方法获取参数:

在这里插入图片描述
在这里插入图片描述
在这个基础上,在继续实现验证用户名密码是否正确

private void doPost(Request request, Response response) {//2.实现 /login 的处理if(request.getUrl().startsWith("/login")) {//读取用户提交的用户名和密码String userName = request.getParameter("username");String password = request.getParameter("password");//登录逻辑需要验证用户名密码是否正确// 此处为了简单,把用户名和密码在代码中写死// 更科学的处理方式: 从数据库中读取用户名对应密码,检验密码是否一致if("hh".equals(userName) && "666".equals(password)){// 登陆成功response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html;charset=utf-8");response.writeBody("<html>");response.writeBody("<div>欢迎您!" + userName + "</div>");response.writeBody("</html>");}else{// 登陆失败response.setStatus(403);response.setMessage("Forbidden");response.setHeader("Content-Type","text/html;charset=utf-8");response.writeBody("<html>");response.writeBody("<div>登陆失败</div>");response.writeBody("</html>");}}
}

重启服务器,进入页面:

在这里插入图片描述
使用 fiddler 抓包验证:

在这里插入图片描述

对于页面来说,若登录成功之后,刷新页面,自己仍然处于登陆状态
访问该网站的其他页面,此时仍然处在登录状态

如何实现上述功能? 就需要使用 Cookie

在 doPost 中再加上:

response.setHeader("Set-Cookie","username=" + userName);

此时我们就在 Http 的响应中加上了 Set-Cookie 这样的字段,浏览器就会自动存储刚才的这个 Cookie 数据

重启服务器,观察抓包效果:

Http 响应报文中就多了 Set-Cookie 字段:

在这里插入图片描述
此时浏览器端就保存了一个 Cookie

在这里插入图片描述
接下来访问服务器的其他页面时,Cookie 就会自动带上

刷新页面,查看请求报文:

进而服务器就可以根据这个 Cookie 的内容来判断当前页面对应的登陆状态

在这里插入图片描述
上述 Cookie 内容是 username=666,此时再访问 index/html 就不需要再登录
修改代码,实现上述功能:

 private void doGet(Request request, Response response) throws IOException {//1.能够支持返回一个 html 文件if(request.getUrl().startsWith("/index.html")){String userName = request.getCookie("username");// userName == null 表示当前用户尚未登陆if(userName == null){// 让代码读取一个 /index.html 这样的文件// 要想读文件,需要先知道文件路径 (只知道文件名)// 此时 html 文件所属的路径,可以自己约定// 把文件内容写到响应的 body 中response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html; charset=utf-8");// HttpServerV3.class获取一个类对象// getClassLoader() 获取当前类的类加载器InputStream inputStream = HttpServerV3.class.getClassLoader().getResourceAsStream("index.html");BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));//按行读取内容,把数据写入到 response 中String lint = " ";while ((lint = bufferedReader.readLine()) != null){response.writeBody(lint + "\n");}bufferedReader.close();}// 已经登陆了else {response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html; charset=utf-8");response.writeBody("<html>");response.writeBody("您已登录,无需再次登录!用户名: " + userName);response.writeBody("</html>");}}
}

重启服务器,刷新页面:

刷新页面,此时的 http 请求中带有了 Cookie 信息,服务器分析了 Cookie 之后,认为已经登陆成功,此时就不需要再继续登录
在这里插入图片描述
借助 Cookie 已经实现了登录保持功能,但用户信息在 Cookie 中,每次数据传输都要把这个 Cookie 再发给服务器,那么 Cookie 中的信息就很容易泄露
应该把用户的敏感信息保存到服务器端,在服务器端登陆成功时,把用户信息保存到一个哈希表中(value),同时生成一个 key (保证唯一性的字符串) SessionId,最终只要把 SessionId 写回到 Cookie 中即可
后续用户访问页面时,Cookie 中带有的内容就是 SessionId,SessionId 就是一个没规律的字符串(不涉及敏感信息),但服务器可以通过 SessionId 进一步找到用户的信息

再次修改代码,实现上述功能:

//保存用户的相关信息
static class User {public String username;public int age;public String school;
}
// sessions 会话 —— 指的是同一个用户的一组访问服务器的操作,归类到一起,就是一个会话
private HashMap<String,User> sessions = new HashMap<>();

在这里插入图片描述
在这里插入图片描述
重启服务器,删除浏览器 Cookie,刷新页面:

首次访问的时候,由于用户浏览器中没有 Cookie,此时看到的页面是一个未登录的状态

请求中没有 Cookie
在这里插入图片描述
输入用户名密码,提交表单,进行验证登录:

请求中也没有 Cookie
在这里插入图片描述
响应中带有 Set-Cookie字段

进而浏览器就会保存这个内容 (sessionId 内容)

在这里插入图片描述

接下来再次访问服务器时,此时浏览器就会带有 Cookie

在这里插入图片描述
服务器会根据此处的 sessionId 就能获取到当前用户的登陆状态

在这里插入图片描述
sessionId 在 Cookie 中存在,并且拿着 sessionId 也能在 sessions 中找到对应的 User 信息,从而就可以确认现在是登陆成功状态
用户信息都在服务器中,不涉及泄露问题~

但是: 若别人拿到 sessionId,短期内是可以冒充该用户的
因此 session 一般要搭配"过期机制",可以在 session 中保存一个该用户的 session 何时创建和何时过期;可以使用一个单独的线程不停的扫描 sessions,只要发现过期的 session 就自动删掉,后续再使用这个过期的 session 去访问,此时就会让你重新登陆

附最终全部代码:

Request 类

public class Request {private String method;private String url;private String version;private Map<String,String> headers = new HashMap<>();// url 中的参数和 body中的参数都放在 parameters 哈希表里private Map<String,String> parameters = new HashMap<>();private Map<String,String> cookies = new HashMap<>();private String body;public static Request build(InputStream inputStream) throws IOException {Request request = new Request();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));//1.处理首行String fistLine = bufferedReader.readLine();String[] firstLineTokens = fistLine.split(" ");request.method = firstLineTokens[0];request.url = firstLineTokens[1];request.version = firstLineTokens[2];//2.解析 urlint pos = request.url.indexOf("?");if(pos != -1){String queryString = request.url.substring(pos + 1);parseKV(queryString,request.parameters);}//3.循环处理 header 部分String line = "";while ((line = bufferedReader.readLine()) != null && line.length() != 0){String[] headerTokens = line.split(": ");request.headers.put(headerTokens[0],headerTokens[1]);}//4.解析 cookieString cookie = request.headers.get("Cookie");if(cookie != null){// 把 cookie 进行解析parseCookie(cookie,request.cookies);}//5.解析 bodyif("POST".equalsIgnoreCase(request.method)|| "PUT".equalsIgnoreCase(request.method)) {// 其他方法暂时不考虑// 需要把 body 读取出来// 此处的长度单位是 "字节"int contentLength = Integer.parseInt(request.headers.get("Content-Length"));// contentLength 长度单位是字节// contentLength 为100, body中有100个字节// 创建的缓冲区长度是 100个char (相当于200个字符)char[] buffer = new char[contentLength];int len = bufferedReader.read(buffer);request.body = new String(buffer,0,len);// body 中的格式形如: username=huahua&password=666parseKV(request.body, request.parameters);}return request;}private static void parseCookie(String cookie, Map<String, String> cookies) {//1.按照 "; " 拆分成多个键值对String[] KVTokens = cookie.split(": ");//2.按照 = 拆分每个键和值for(String kv : KVTokens){String[] result = kv.split("=");cookies.put(result[0],result[1]);}}private static void parseKV(String queryString, Map<String, String> parameters) {//1.按照 & 拆分成多个键值对String[] KVTokens = queryString.split("&");//2.按照 = 拆分每个键和值for(String kv : KVTokens){String[] result = kv.split("=");parameters.put(result[0],result[1]);}}public String getMethod() {return method;}public String getUrl() {return url;}public String getVersion() {return version;}public String getBody() {return body;}public String getParameter(String key) {return parameters.get(key);}public String getHeader(String key) {return headers.get(key);}public String getCookie(String key) {return cookies.get(key);}
}

Response 类

public class Response {private String version = "HTTP//1.1";private int status;private String message;private Map<String,String> headers = new HashMap<>();private StringBuilder body = new StringBuilder(); //方便拼接private OutputStream outputStream = null;//工厂方法public static Response build(OutputStream outputStream){Response response = new Response();response.outputStream = outputStream;return response;}public void setVersion(String version) {this.version = version;}public void setStatus(int status) {this.status = status;}public void setMessage(String message) {this.message = message;}public void setHeader(String key,String value) {headers.put(key,value);}public void writeBody(String content) {body.append(content);}public void flush() throws IOException {BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));bufferedWriter.write(version + " " + status + " " + message + "\n");headers.put("Content-Length", body.toString().getBytes().length + " ");for (Map.Entry<String,String> entry : headers.entrySet()) {bufferedWriter.write(entry.getKey() + ": " + entry.getValue() + "\n");}bufferedWriter.write("\n");bufferedWriter.write(body.toString());bufferedWriter.flush();}
}

主类

public class HttpServerV3 {//保存用户的相关信息static class User {public String username;public int age;public String school;}private ServerSocket serverSocket = null;// sessions 会话 —— 指的是同一个用户的一组访问服务器的操作,归类到一起,就是一个会话private HashMap<String,User> sessions = new HashMap<>();public HttpServerV3(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动...");ExecutorService executorService = Executors.newCachedThreadPool();while (true) {Socket clientSocket = serverSocket.accept();executorService.execute(new Runnable() {@Overridepublic void run() {process(clientSocket);}});}}public void process(Socket clientSocket){try {//1.读取请求并解析Request request = Request.build(clientSocket.getInputStream());Response response = Response.build(clientSocket.getOutputStream());//2.根据请求计算响应 按照不同的 Http 方法,拆分成不同的逻辑if("GET".equalsIgnoreCase(request.getMethod())){doGet(request,response);}else if("POST".equalsIgnoreCase(request.getMethod())){doPost(request,response);}else{// 其他方法,返回一个405response.setStatus(405);response.setMessage("Method Not Allowed");}//3.把响应写回客户端response.flush();} catch (IOException | NullPointerException e) {e.printStackTrace();} finally {try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}private void doGet(Request request, Response response) throws IOException {//1.能够支持返回一个 html 文件if(request.getUrl().startsWith("/index.html")){String sessionId = request.getCookie("sessionId");// userName == null 表示当前用户尚未登陆User user = sessions.get(sessionId);if(sessionId == null || user == null){// 让代码读取一个 /index.html 这样的文件// 要想读文件,需要先知道文件路径 (只知道文件名)// 此时 html 文件所属的路径,可以自己约定// 把文件内容写到响应的 body 中response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html; charset=utf-8");// HttpServerV3.class获取一个类对象// getClassLoader() 获取当前类的类加载器InputStream inputStream = HttpServerV3.class.getClassLoader().getResourceAsStream("index.html");BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));//按行读取内容,把数据写入到 response 中String lint = " ";while ((lint = bufferedReader.readLine()) != null){response.writeBody(lint + "\n");}bufferedReader.close();}// 已经登陆了else {response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html; charset=utf-8");response.writeBody("<html>");response.writeBody("<div>" + "您已登录,无需再次登录!用户名: " + user.username + "</div>");response.writeBody("<div>" + user.age + "</div>");response.writeBody("<div>" + user.school + "</div>");response.writeBody("</html>");}}}private void doPost(Request request, Response response) {//2.实现 /login 的处理if(request.getUrl().startsWith("/login")) {//读取用户提交的用户名和密码String userName = request.getParameter("username");String password = request.getParameter("password");
//            System.out.println("userName: " + userName);
//            System.out.println("password: " + password);//登录逻辑需要验证用户名密码是否正确// 此处为了简单,把用户名和密码在代码中写死// 更科学的处理方式: 从数据库中读取用户名对应密码,检验密码是否一致if("hh".equals(userName) && "666".equals(password)){// 登陆成功response.setStatus(200);response.setMessage("OK");response.setHeader("Content-Type","text/html;charset=utf-8");// 原来登录成功是给浏览器写了一个 cookie,cookie中保存的是用户名//response.setHeader("Set-Cookie","username=" + userName);// 现有的对于登录成功的处理,给这次登录的用户分配了一个 session// (在 hash 中新增了一个键值对),key是随机生成的,value 就是用户的身份信息// 身份信息保存到服务器中,此时就不再有泄露信息的问题// 给浏览器返回的 Cookie 中只需要包含 sessionIdString sessionId = UUID.randomUUID().toString(); // 会生成一个随机的字符串,能够保证每次调用这个方法,生成的字符串都不一样User user = new User();user.username = "hh";user.age = 3;user.school = "Coding666";sessions.put(sessionId,user);response.setHeader("Set-Cookie","sessionId=" + sessionId);response.writeBody("<html>");response.writeBody("<div>欢迎您!" + userName + "</div>");response.writeBody("</html>");}else{// 登陆失败response.setStatus(403);response.setMessage("Forbidden");response.setHeader("Content-Type","text/html;charset=utf-8");response.writeBody("<html>");response.writeBody("<div>登陆失败</div>");response.writeBody("</html>");}}}public static void main(String[] args) throws IOException {HttpServerV3 httpServerV3 = new HttpServerV3(6060);httpServerV3.start();}
}

在这里插入图片描述

http://www.wooajung.com/news/34664.html

相关文章:

  • 机械加工外发订单平台北京seo专员
  • wordpress 布局插件系统优化助手
  • 网站注册空间百度推广排名代发
  • 做网站销售是干什么的2022国内外重大新闻事件10条
  • 珠海模板网站建设360站长工具seo
  • 手机网站怎么开发南宁优化网站网络服务
  • 外国网站dns招聘网站排名
  • 淘宝做网站费用抖音视频排名优化
  • 如何做网站滚动条网络营销策划包括哪些内容
  • ui设计的网站有哪些俄罗斯搜索引擎推广
  • 在百度做网站需要什么资料国外域名注册网站
  • 凡科做网站友情链接怎么做百度旗下13个app
  • 网站建设标准流程及外包注意事项一个产品的营销方案
  • 企业平台有哪些搜索引擎优化的基本原理
  • 阿里云服务器做网站多少钱正规网站优化推广
  • q a wordpress插件下载地址广州seo关键词优化是什么
  • 松原手机网站开发郑州专业seo哪家好
  • 深圳市网站开发公司今日新闻头条新闻最新
  • 深圳网站建设的服务怎么样搜索引擎营销的优缺点
  • 做网站是不是就能上传东西网站alexa排名
  • 转运网站建设百度关键词关键词大全
  • 网站建设收费价格北京seo网站设计
  • 哈尔滨seo推广汕头seo网络推广
  • 南昌定制网站公司大连企业网站建站模板
  • 网站开发 合同今日热点新闻素材
  • 网站源码出售制作网页的软件有哪些
  • c2c网站的特点怎么做营销推广方案
  • 展览展会网站建设北京seo做排名
  • 昆明网站开发价格查看网站流量的工具
  • 发布网站建设平面设计关键词搜索推广