浅谈web服务器项目中静态请求和动态请求处理
作者:suwu150 发布时间:2022-03-01 21:26:12
注:完整项目下载
在处理了核心任务之后,我们会发现有些请求并不是都是静态的,那么我们就需要进行实现处理动态请求的要求,如下面代码是我们请求的解决方式,我们只需在HttpRequestImpl实现类中,将如下代码实现具体的判断过程
//判断当前请求的否是静态资源
public boolean isStaticResource(){
return true;
}
//判断当前请求的否是动态资源
public boolean isDynamicResource(){
return true;
}
1、实现isStaticResource()方法:
// 判断当前请求的否是静态资源
public boolean isStaticResource() {
// 存在??文件??静态??
System.out.println("进入isStaticResource()方法");
if (requestPath != null) {
String parent = ConfigUtils.getConfigValue("rootPath");
File file = new File(parent, requestPath);
return file.exists() && file.isFile();
}
return false;
}
2、实现isDynamicResource():
// 判断当前请求的否是动态资源
public boolean isDynamicResource() {
// 存在??文件??动态??
System.out.println("进入isDynamicResource()方法");
String path = ServletMappingUtils.getMappingValue(requestPath);
/*
* //使用路径判断,当时我不知道还有一个叫做isContains(key)的方法,如果知道的话 就可以使用了,请参见测试类
* if(isContainers(requestPath())) { return *; }
*/
System.out.println("ServletMapping中根据requestPath获取的映射:" + path);
if (path != null) {
return true;
}
return false;
}
在动态方法中,我们String path = ServletMappingUtils.getMappingValue(requestPath);来获取请求的资源的路径,如果存在值的话就返回结果,其实现如下所示,对于servlet_mapping.properties文件,还是复制到项目下即可:
package com.sample.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ServletMappingUtils {
private static Properties p;
static
{
InputStream in=null;
p=new Properties();
try {
//读了xx.properties文件
in=ServletMappingUtils.class.getResourceAsStream("servlet_mapping.properties");
//放置到p中,即放properties文件中的key,value
p.load(in);
} catch (IOException e) {
e.printStackTrace();
}
finally
{
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String getMappingValue(String mapping)
{
return p.getProperty(mapping);
}
public static boolean isContainsKey(String key) {
return p.containsKey(key);
}
public static void main(String[] args) {//输出测试
//Properties p=new Properties();
//p.setProperty("rootPath","ddd");
//System.out.println(p.get("rootPath"));
System.out.println(getMappingValue("/HelloWorld"));
System.out.println(isContainsKey("/Login"));
}
}
3、实现对静态请求和动态请求的封装
在处理完基本的功能性要求之后,我们实现对核心任务取得封装,在封装时,我们仍然采用类实现接口的方式,首先我们需要明确该确定一个怎么样的接口,其代码如下:
package com.sample.http;
//Http资源处理器
//负责处理http协议的资源请求
public interface HttpAccessProcessor {
//处理静态资源 页面/文件/图片等等
public void processStaticResource(HttpRequest request,HttpResponse response);
//处理动态资源 java代码 浏览器通过路径发送请求可以访问调用java代码
public void processDynamicResource(HttpRequest request,HttpResponse response);
//向浏览器返回错误信息及其页面
public void sendError(int statusCode,HttpRequest request,HttpResponse response);
}
其实现类如下所示:
package com.sample.http;
import com.sample.utils.ServletMappingUtils;
//Http资源处理器
//负责处理http协议的资源请求
public class HttpAccessProcessorImpl implements HttpAccessProcessor {
//处理静态资源 页面/文件/图片等等
public void processStaticResource(HttpRequest request,HttpResponse response)
{
System.out.println("进入方法processStaticResource(HttpRequest request,HttpResponse response)");
//获取请求中资源,并处理
String path=request.getRequestPath();
String[] str=path.split("[.]");
String contentType=str[str.length-1];
System.out.println("路径的后缀:"+contentType);
response.setStatusLine(200);
response.setContentType(MIMEUtils.getMimeValue(contentType));
response.setCRLF();
response.printResponseHeader();
response.printResponseContent(request.getRequestPath());
}
//处理动态资源 java代码 浏览器通过路径发送请求可以访问调用java代码
public void processDynamicResource(HttpRequest request,HttpResponse response)
{
System.out.println("进入processDynamicResource");
response.setStatusLine(200);
response.setContentType("text/HTML");
response.setCRLF();
response.printResponseHeader();
Class className=null;
try {
String path=ServletMappingUtils.getMappingValue(request.getRequestPath());
System.out.println("使用反射获取的servlet路径:"+path);
className = (Class.forName(path));
//ServletImpl servlet= (ServletImpl) className.newInstance();
Servlet servlet = (Servlet) className.newInstance();
System.out.println(servlet);
servlet.service(request, response);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//向浏览器返回错误信息及其页面
public void sendError(int statusCode,HttpRequest request,HttpResponse response)
{
System.out.println("进入sendError()");
//获取请求中资源,并处理
//response.setStatusLine("OK");
response.setStatusLine(statusCode);
//response.setStatusLine("OK");
response.setContentType("text/html");
response.setCRLF();
response.printResponseHeader();
//response.printResponseContent("/error/404.html");
response.printResponseContent(ErrorPageUtils.getErrorPage(statusCode+""));
}
}
同样的,在写完代码之后,在response.setContentType(MIMEUtils.getMimeValue(contentType));String path=ServletMappingUtils.getMappingValue(request.getRequestPath());response.printResponseContent(ErrorPageUtils.getErrorPage(statusCode+""));出现问题,按照以前编写的代码进行处理即可,在设置ServletMappingUtils.getMappingValue(request.getRequestPath())部分时,我们要将文件的配置路径设置为自己的类所在的包下面,比如我们的Servlet实现类在com.sample.servlet.HelloWorldServlet,则应该写为/HelloWorld=com.sample.servlet.HelloWorldServlet。
值得注意的是Servlet servlet = (Servlet) className.newInstance();处的错误信息,在这里我们需要再创建一个类进行处理动态跳转,如下所示:
package com.sample.servlet;
import com.sample.http.HttpRequest;
import com.sample.http.HttpResponse;
//只有实现这个接口的类,才可以被浏览器发送请求访问到
public interface Servlet {
//被浏览器发请求访问到的对象会调用这个指定方法service,进行处理这次浏览器的请求
public void service(HttpRequest request,HttpResponse response);
}
下面是实现类HelloWorldServlet,其代码如下所示:
package com.sample.servlet;
import java.io.PrintWriter;
import com.sample.http.HttpRequest;
import com.sample.http.HttpResponse;
//只有实现这个接口的类,才可以被浏览器发送请求访问到
public class HelloWorldServlet implements Servlet{
//被浏览器发请求访问到的对象会调用这个指定方法service,进行处理这次浏览器的请求
public void service(HttpRequest request,HttpResponse response)
{
String name=request.getParameter("name");
System.out.println(name);
try {
PrintWriter pw=response.getPrintWriter();
pw.println("<html>");
pw.println("<body>");
pw.println("<center>"+name+":这是我的Servlet</center>");
pw.println("</body>");
pw.println("</html>");
pw.flush();
pw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这样就完成了动态跳转页面,但是,我们在每次创建是都需要来new一个新对象,这样不仅浪费时间空间内存等等,最重要的用户体验都找不见了,那么我们就对其再次进行封装,其代码如下,实现request,response对象的封装:
package com.sample.http;
//负责创建http协议访问过程中使用到的对象
public interface HttpCreator {
//返回创建好的request对象
public HttpRequest getHttpRequest();
//返回创建好的response对象
public HttpResponse getHttpResponse();
//返回创建好的HttpAccessProcessor对象
public HttpAccessProcessor getHttpAccessProcessor();
}
下面就是实现类:
package com.sample.http;
import java.net.Socket;
//负责创建http协议访问过程中使用到的对象
public class HttpCreatorImpl implements HttpCreator{
private Socket s;
HttpRequestImpl request;
HttpResponseImpl response;
HttpAccessProcessorImpl hapi;
public HttpCreatorImpl(Socket s) {
this.s=s;
}
//返回创建好的request对象
public HttpRequest getHttpRequest()
{
return request=new HttpRequestImpl(s);
}
//返回创建好的response对象
public HttpResponse getHttpResponse()
{
return response=new HttpResponseImpl(s);
}
//返回创建好的HttpAccessProcessor对象
public HttpAccessProcessor getHttpAccessProcessor()
{
return hapi=new HttpAccessProcessorImpl();
}
}
到此,我们完成了所有对象的封装,下面我们进行测试,写测试类如下所示:
package com.sample.http;
<pre name="code" class="java">import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerTest {
public static void main(String[] args) {
//声明变量
ServerSocket ss=null;
Socket s=null;
boolean flag=true;
try {
int port=10002;
System.out.println("Server Port:"+port);
ss=new ServerSocket(port);
//while(flag)
{
//接受客户端发送过来的Socket
s=ss.accept();
HttpCreatorImpl hci=new HttpCreatorImpl(s);
HttpRequest request=hci.getHttpRequest();
HttpResponse response=hci.getHttpResponse();
HttpAccessProcessor hapi=hci.getHttpAccessProcessor();
//用于测试收到的信息
if(request.isStaticResource())//处理静态信息
{
hapi.processStaticResource(request, response);
}
else if(request.isDynamicResource())//处理动态请求
{
hapi.processDynamicResource(request, response);
}
else//无法处理时
{
System.out.println("无法处理");
hapi.sendError(404, request, response);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
当我们在浏览器中输入http://127.0.0.1:10002/HelloWorld?id=1212&name=suguniang
信息回车时能够看到如下所示界面,但是此时的状态是在项目文件夹webapps中根本不存在HelloWorld页面,但是我们能够正常访问到页面信息,而此时返回的信息正是我们的Servlet实现类中的内容:
而当我们在URL中输入不存在的请求资源时,则会弹出404界面
来源:https://blog.csdn.net/suwu150/article/details/52494089


猜你喜欢
- 项目已经添加了svn,但右键项目时找不到Svn选择但在VCS中却有,很奇怪这个问题是svn的根路径与当前IDEA打开的项目路径不一致的原因在
- 情景模式的设置大家应当相当熟悉了,但是在Android中如何通过自己的程序进行情景模式的设置呢,情景模
- 这篇文章主要介绍了Spring如何使用注解的方式创建bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 我就废话不多说了,大家还是直接看代码吧~ public List<FreightM> sortList(List&l
- Android开发中会有很多很新奇的交互,比如天猫商城的首页头部的分类,使用的是GridLayoutManager+横向指示器实现的,效果如
- 代码很简单,这里就不多废话了,直接奉上代码using UnityEngine;using System.Collections;public
- 本文实例讲述了C#实现解压GZip文件的方法。分享给大家供大家参考。具体实现方法如下:public void ungzip(string p
- 前言在上篇文章(Android实现圆弧滑动效果之ArcSlidingHelper篇)中,我们把圆弧滑动手势处理好了,那么这篇文章我们就来自定
- 目的:在使用mybatis框架中mapper文件有自动生成,但有时需要自己添加sql语句进行开发,当遇到需要使用 if进行条件判断的时候该怎
- 这几天看了下之前写的有关微信支付的博客,看的人还是挺多的,看了下留言不知道是因为博客写的不够细还是什么情况,大多都找我要源码,我觉得吧程序员
- 本文实例讲述了Android实现调用震动的方法。分享给大家供大家参考,具体如下:调用Android系统的震动,只需要一个类 那就是Vibra
- 本文实例为大家分享了java实现拼图游戏的具体代码,供大家参考,具体内容如下游戏说明:设计一款拼图游戏,要求点击图片按钮,实现图片按钮的移动
- 前言最近遇到很有意思转换二进制的问题,有部分童鞋俨然已了解,可能也有一部分童鞋没碰到过也就不知情,这里我们来深入学习下转换二进制所带来的问题
- jar包打包实现jar包打包可以使用jar指令实现打包,在命令行中输入jar可以查看jar指令的内容 从最后显示的两个示例看出存在两种打包的
- synchronized关键字,一般称之为”同步锁“,用它来修饰需要同步的方法和需要同步代码块,默认是当前对象作为锁的对象。同步锁锁的是同一
- 方法一:实现Comparator接口,并重写compare方法实体类代码:import java.util.Comparator;/** *
- 这篇文章主要介绍了Spring整合MyBatis图示过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- SpringMVC配置多个properties文件之通配符在springmvc中配置加载properties文件一般会在xml文件中配置如下
- 本文使用SpringBoot结合Redis进行简单的token鉴权。1.简介刚刚换了公司,所以最近有些忙碌,所以一直没有什么产出,最近朋友问
- 本文为大家分享了java组件实现文件上传功能的具体代码,供大家参考,具体内容如下1 SmartUpload上传组件SmartUpload上传