第五个任务:
1.定义HttpResponse类:
1)定义HTTPResponse类在com.tedu.http包中
2)定义变量:
OutputStream out;
File entity;
定义setEntity()和getEntity()方法。
3)定义构造方法:HttpResponse(OutputStream out)
功能:初始化out成员变量
4)定义方法: println(String line) :void
功能:
向客户端发送一行字符串,该字符串会通过ISO8859-1转换为一组字节并写出.写出后会自动连续写出CRLF
out.write(line.getBytes(“ISO8859-1”));
out.write(13);
out.write(10);
5)定义方法sendStatusLine():void
功能:发送状态行信息
String line = “HTTP/1.1 200 OK”;
6)在sendStatusLine()放中调用println(String line)方法。
7)定义方法:getMimeTypeByEntity():String
功能:根据实体文件的名字获取对应的介质类型,Content-Type使用的值(常用的几种):根据文件扩展名返回文件的介质类型
if(“html”.equals(name)){
return “text/html”;
}else if(“jpg”.equals(name)){
return “image/jpg”;
}else if(“png”.equals(name)){
return “image/png”;
}
else if(“gif”.equals(name)){
return “image/gif”;
}
return “”;
测试:
8)定义方法:sendHeaders();
功能:响应头信息
println(“Content-Type:”+getMimeTypeByEntity());
println(“Content-Length:”+entity.length());
println("");//单独发送CRLF表示头发送完毕
9)定义方法: sendContent()
功能:发送响应正文信息
10)定义方法:flush():void
功能:调用sendStatusLine();sendHeaders();sendContent()
public class WebServer {
ServerSocket server;
public WebServer() {
try {
server = new ServerSocket(8888);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
while (true) {
Socket socket;
try {
while (true) {
System.out.println("等待客户端的请求");
socket = server.accept();
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
Socket socket;
public ClientHandler() {
}
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// \r\n ASCⅡ 13 10
System.out.println("接收客户端请求");
//获取请求状态行
try {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
HttpRequest request =new HttpRequest(in);
HttpResponse response = new HttpResponse(out);
// System.out.println(request.getMethod());
// System.out.println(request.getUrl());
// System.out.println(request.getProtocol());
File file = new File("webapps"+request.getUrl());
//响应页面
response.setEntity(file);
//响应的文档内容
response.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new WebServer().start();
}
}
public class HttpRequest {
public String method;
public String url;
public String protocol;
public HttpRequest() {
}
public HttpRequest(InputStream in) {
try {
parseRequestLine(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getMethod() {
return method;
}
public String getUrl() {
return url;
}
public String getProtocol() {
return protocol;
}
public void parseRequestLine(InputStream in) throws IOException {
StringBuilder builder = new StringBuilder();
char c1 = 0,c2 = 0;
int d = -1;
while((d=in.read())!=-1) {
c2 = (char)d;
//解析第一行,遇到 \r\n,break
if(c1 == 13 && c2 == 10) {
break;
}
builder.append(c2);
c1 = c2;
}
String str = builder.toString().trim();
String[] data = str.split(" ");
this.method = data[0];//获取请求方式get
this.url = data[1];//url请求
this.protocol = data[2];//协议名称
}
}
public class HttpResponse {
OutputStream out;
File entity;
public HttpResponse(OutputStream out) {
this.out = out;
}
public File getEntity() {
return entity;
}
public void setEntity(File entity) {
this.entity = entity;
}
public void println(String line) {
try {
out.write(line.getBytes());
out.write(13);
out.write(10);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendStatusLine() {
String line = "HTTP/1.1 200 OK";
this.println(line);
}
public void sendHeader() {
String contentType = "Content -Type" + getMineTypeByEntity();
this.println(contentType);
long length = entity.length();
String contentLength = "Content-Length:" + entity.length();
this.println(contentLength);
this.println("");
}
public void sendContent() throws IOException {
try {
FileInputStream fin = new FileInputStream(entity);
byte[] buffer = new byte[(int) entity.length()];
fin.read(buffer);
out.write(buffer);
fin.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void flush() {
this.sendStatusLine();
this.sendHeader();
try {
this.sendContent();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getMineTypeByEntity() {
// 文件的扩展名
int index = this.entity.getName().lastIndexOf(".");
String name = this.entity.getName().substring(index + 1);
if ("html".equals(name)) {
return "text/html";
} else if ("jpg".equals(name)) {
return "image/jpg";
} else if ("png".equals(name)) {
return "image/png";
} else if ("gif".equals(name)) {
return "image/gif";
}
return "";
}
}
第六个任务:
设置媒体类型
1.在com.tedu.core中添加一个类HttpContext
该类用于定义相关Http协议的内容.
比如头信息中Content-Type的值与文件后缀的关系等.
1)在com.tedu.core包中定义HttpContext类
2)定义两个常量int CR = 13; int LF = 10;
3)定义介质的类型静态变量 Map<String,String> mimeTypeMapping;
4)定义方法private static void initMimeTypeMapping()
功能:初始化介质的类型
mimeTypeMapping = new HashMap<String,String>();
mimeTypeMapping.put(“html”, “text/html”);
mimeTypeMapping.put(“jpg”, “image/jpeg”);
mimeTypeMapping.put(“gif”, “image/gif”);
mimeTypeMapping.put(“png”, “image/png”);
5)定义public static String getContentTypeByMime(String mime)方法
功能:根据给定的介质类型获取对应的Content-Type的值
return mimeTypeMapping.get(mime);
6)定义初始化的方法public static void init()
功能:完成HTTPContext初始化的功能
//1 初始化介质类型映射
initMimeTypeMapping();
7)定义静态块
功能:HttpContext加载的时候开始初始化
static{
//HttpContext加载的时候开始初始化
init();
}
2.在HttpResponse中进行代码重构
1)添加一个Map属性,用于保存响应的所有响应头信息.
private Map<String,String> headers = new HashMap<String,String>();
2)添加常用头的设置方法,供外界设置响应头:
public void setContentType(String contentType){
//把内容类型添加到头信息中
//this.headers.put(“Content-Type”, contentType);
}
public void setContentLength(int length){
//把响应文件的长度添加到头信息中
this.headers.put(“Content-Length”, length+"");
}
3)重新实现sendHeaders方法
private void sendHeaders(){
Set set = headers.keySet();
for(String name:set){
String line = name+":"+headers.get(name);
print(line);//发送每一个头信息
}
print("");//单独发送CRLF表示头发送完毕
}
3.重构WebServer的run方法
String contentType = HttpContext.getContentTypeByMime(name);
//设置响应头:媒体类型和文件长度
//设置响应正文
//响应客户端
4.测试
public class WebServer {
ServerSocket server;
public WebServer() {
try {
server = new ServerSocket(8888);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
while (true) {
Socket socket;
try {
while (true) {
System.out.println("等待客户端的请求");
socket = server.accept();
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
Socket socket;
public ClientHandler() {
}
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// \r\n ASCⅡ 13 10
System.out.println("接收客户端请求");
//获取请求状态行
try {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
HttpRequest request =new HttpRequest(in);
HttpResponse response = new HttpResponse(out);
// System.out.println(request.getMethod());
// System.out.println(request.getUrl());
// System.out.println(request.getProtocol());
File file = new File("webapps"+request.getUrl());
//设置文档长度
response.setContentLength((int)file.length());
//设置文档类型
int index = file.getName().indexOf(".");
String name = file.getName().substring(index+1);
response.setContentType(HttpContext.getMimeType(name));
//响应页面
response.setEntity(file);
//响应的文档内容
response.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public