淺談web服務(wù)器項(xiàng)目中靜態(tài)請求和動態(tài)請求處理
在處理了核心任務(wù)之后,我們會發(fā)現(xiàn)有些請求并不是都是靜態(tài)的,那么我們就需要進(jìn)行實(shí)現(xiàn)處理動態(tài)請求的要求,如下面代碼是我們請求的解決方式,我們只需在HttpRequestImpl實(shí)現(xiàn)類中,將如下代碼實(shí)現(xiàn)具體的判斷過程
//判斷當(dāng)前請求的否是靜態(tài)資源
public boolean isStaticResource(){
return true;
}
//判斷當(dāng)前請求的否是動態(tài)資源
public boolean isDynamicResource(){
return true;
}
1、實(shí)現(xiàn)isStaticResource()方法:
// 判斷當(dāng)前請求的否是靜態(tài)資源
public boolean isStaticResource() {
// 存在??文件??靜態(tài)??
System.out.println("進(jìn)入isStaticResource()方法");
if (requestPath != null) {
String parent = ConfigUtils.getConfigValue("rootPath");
File file = new File(parent, requestPath);
return file.exists() && file.isFile();
}
return false;
}
2、實(shí)現(xiàn)isDynamicResource():
// 判斷當(dāng)前請求的否是動態(tài)資源
public boolean isDynamicResource() {
// 存在??文件??動態(tài)??
System.out.println("進(jìn)入isDynamicResource()方法");
String path = ServletMappingUtils.getMappingValue(requestPath);
/*
* //使用路徑判斷,當(dāng)時(shí)我不知道還有一個叫做isContains(key)的方法,如果知道的話 就可以使用了,請參見測試類
* if(isContainers(requestPath())) { return *; }
*/
System.out.println("ServletMapping中根據(jù)requestPath獲取的映射:" + path);
if (path != null) {
return true;
}
return false;
}
在動態(tài)方法中,我們String path = ServletMappingUtils.getMappingValue(requestPath);來獲取請求的資源的路徑,如果存在值的話就返回結(jié)果,其實(shí)現(xiàn)如下所示,對于servlet_mapping.properties文件,還是復(fù)制到項(xiàng)目下即可:
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、實(shí)現(xiàn)對靜態(tài)請求和動態(tài)請求的封裝
在處理完基本的功能性要求之后,我們實(shí)現(xiàn)對核心任務(wù)取得封裝,在封裝時(shí),我們?nèi)匀徊捎妙悓?shí)現(xiàn)接口的方式,首先我們需要明確該確定一個怎么樣的接口,其代碼如下:
package com.sample.http;
//Http資源處理器
//負(fù)責(zé)處理http協(xié)議的資源請求
public interface HttpAccessProcessor {
//處理靜態(tài)資源 頁面/文件/圖片等等
public void processStaticResource(HttpRequest request,HttpResponse response);
//處理動態(tài)資源 java代碼 瀏覽器通過路徑發(fā)送請求可以訪問調(diào)用java代碼
public void processDynamicResource(HttpRequest request,HttpResponse response);
//向?yàn)g覽器返回錯誤信息及其頁面
public void sendError(int statusCode,HttpRequest request,HttpResponse response);
}
其實(shí)現(xiàn)類如下所示:
package com.sample.http;
import com.sample.utils.ServletMappingUtils;
//Http資源處理器
//負(fù)責(zé)處理http協(xié)議的資源請求
public class HttpAccessProcessorImpl implements HttpAccessProcessor {
//處理靜態(tài)資源 頁面/文件/圖片等等
public void processStaticResource(HttpRequest request,HttpResponse response)
{
System.out.println("進(jìn)入方法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());
}
//處理動態(tài)資源 java代碼 瀏覽器通過路徑發(fā)送請求可以訪問調(diào)用java代碼
public void processDynamicResource(HttpRequest request,HttpResponse response)
{
System.out.println("進(jìn)入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();
}
}
//向?yàn)g覽器返回錯誤信息及其頁面
public void sendError(int statusCode,HttpRequest request,HttpResponse response)
{
System.out.println("進(jìn)入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+""));出現(xiàn)問題,按照以前編寫的代碼進(jìn)行處理即可,在設(shè)置ServletMappingUtils.getMappingValue(request.getRequestPath())部分時(shí),我們要將文件的配置路徑設(shè)置為自己的類所在的包下面,比如我們的Servlet實(shí)現(xiàn)類在com.sample.servlet.HelloWorldServlet,則應(yīng)該寫為/HelloWorld=com.sample.servlet.HelloWorldServlet。
值得注意的是Servlet servlet = (Servlet) className.newInstance();處的錯誤信息,在這里我們需要再創(chuàng)建一個類進(jìn)行處理動態(tài)跳轉(zhuǎn),如下所示:
package com.sample.servlet;
import com.sample.http.HttpRequest;
import com.sample.http.HttpResponse;
//只有實(shí)現(xiàn)這個接口的類,才可以被瀏覽器發(fā)送請求訪問到
public interface Servlet {
//被瀏覽器發(fā)請求訪問到的對象會調(diào)用這個指定方法service,進(jìn)行處理這次瀏覽器的請求
public void service(HttpRequest request,HttpResponse response);
}
下面是實(shí)現(xiàn)類HelloWorldServlet,其代碼如下所示:
package com.sample.servlet;
import java.io.PrintWriter;
import com.sample.http.HttpRequest;
import com.sample.http.HttpResponse;
//只有實(shí)現(xiàn)這個接口的類,才可以被瀏覽器發(fā)送請求訪問到
public class HelloWorldServlet implements Servlet{
//被瀏覽器發(fā)請求訪問到的對象會調(diào)用這個指定方法service,進(jìn)行處理這次瀏覽器的請求
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();
}
}
}
這樣就完成了動態(tài)跳轉(zhuǎn)頁面,但是,我們在每次創(chuàng)建是都需要來new一個新對象,這樣不僅浪費(fèi)時(shí)間空間內(nèi)存等等,最重要的用戶體驗(yàn)都找不見了,那么我們就對其再次進(jìn)行封裝,其代碼如下,實(shí)現(xiàn)request,response對象的封裝:
package com.sample.http;
//負(fù)責(zé)創(chuàng)建http協(xié)議訪問過程中使用到的對象
public interface HttpCreator {
//返回創(chuàng)建好的request對象
public HttpRequest getHttpRequest();
//返回創(chuàng)建好的response對象
public HttpResponse getHttpResponse();
//返回創(chuàng)建好的HttpAccessProcessor對象
public HttpAccessProcessor getHttpAccessProcessor();
}
下面就是實(shí)現(xiàn)類:
package com.sample.http;
import java.net.Socket;
//負(fù)責(zé)創(chuàng)建http協(xié)議訪問過程中使用到的對象
public class HttpCreatorImpl implements HttpCreator{
private Socket s;
HttpRequestImpl request;
HttpResponseImpl response;
HttpAccessProcessorImpl hapi;
public HttpCreatorImpl(Socket s) {
this.s=s;
}
//返回創(chuàng)建好的request對象
public HttpRequest getHttpRequest()
{
return request=new HttpRequestImpl(s);
}
//返回創(chuàng)建好的response對象
public HttpResponse getHttpResponse()
{
return response=new HttpResponseImpl(s);
}
//返回創(chuàng)建好的HttpAccessProcessor對象
public HttpAccessProcessor getHttpAccessProcessor()
{
return hapi=new HttpAccessProcessorImpl();
}
}
到此,我們完成了所有對象的封裝,下面我們進(jìn)行測試,寫測試類如下所示:
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)
{
//接受客戶端發(fā)送過來的Socket
s=ss.accept();
HttpCreatorImpl hci=new HttpCreatorImpl(s);
HttpRequest request=hci.getHttpRequest();
HttpResponse response=hci.getHttpResponse();
HttpAccessProcessor hapi=hci.getHttpAccessProcessor();
// 用于測試收到的信息
if(request.isStaticResource())//處理靜態(tài)信息
{
hapi.processStaticResource(request, response);
}
else if(request.isDynamicResource())//處理動態(tài)請求
{
hapi.processDynamicResource(request, response);
}
else//無法處理時(shí)
{
System.out.println("無法處理");
hapi.sendError(404, request, response);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
當(dāng)我們在瀏覽器中輸入http://127.0.0.1:10002/HelloWorld?id=1212&name=suguniang信息回車時(shí)能夠看到如下所示界面,但是此時(shí)的狀態(tài)是在項(xiàng)目文件夾webapps中根本不存在HelloWorld頁面,但是我們能夠正常訪問到頁面信息,而此時(shí)返回的信息正是我們的Servlet實(shí)現(xiàn)類中的內(nèi)容:

而當(dāng)我們在URL中輸入不存在的請求資源時(shí),則會彈出404界面
到此這篇關(guān)于淺談web服務(wù)器項(xiàng)目中靜態(tài)請求和動態(tài)請求處理的文章就介紹到這了,更多相關(guān)web服務(wù)器中靜態(tài)請求和動態(tài)請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot項(xiàng)目test文件夾下帶main方法的類不能運(yùn)行問題
這篇文章主要介紹了springboot項(xiàng)目test文件夾下帶main方法的類不能運(yùn)行問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
JAVA面試題 從源碼角度分析StringBuffer和StringBuilder的區(qū)別
這篇文章主要介紹了JAVA面試題 從源碼角度分析StringBuffer和StringBuilder的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面我們來一起學(xué)習(xí)下吧2019-07-07
SpringBoot中的ThreadLocal保存請求用戶信息的實(shí)例demo
線程局部變量,創(chuàng)建一個線程變量后,針對這個變量可以讓每個線程擁有自己的變量副本,每個線程是訪問的自己的副本,與其他線程的相互獨(dú)立,本文介紹SpringBoot中的ThreadLocal保存請求用戶信息,需要的朋友可以參考下2024-05-05
Java8新特性之深入解析日期和時(shí)間_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java8新特性之深入解析日期和時(shí)間_動力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下2017-06-06
SpringCloud?集成Sentinel的實(shí)戰(zhàn)教程
這篇文章主要介紹了SpringCloud?集成Sentinel的詳細(xì)過程,本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-08-08
Maven學(xué)習(xí)教程之搭建多模塊企業(yè)級項(xiàng)目
本篇文章主要介紹了Maven學(xué)習(xí)教程之搭建多模塊企業(yè)級項(xiàng)目 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
從零開始Java實(shí)現(xiàn)Parser?Combinator
這篇文章主要為大家介紹了從零開始Java實(shí)現(xiàn)Parser?Combinator過程及原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(9)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07

