HTTP响应格式
HTTP协议规定,响应与请求一样,由三部分组成,分别是:
1、HTTP协议版本、状态代码、描述
2、响应头(Response Head)
3、响应正文(Response Content)
import java.io.IOException;
import java.net.ServerSocket;
/**
* 创建服务器
*/
public class Server {
private ServerSocket serverSocket;
private boolean isShutdown=false;
public static void main(String[] args) {
Server server=new Server();
server.start();
server.receive();
}
public void start(){
start(9999);
}
public void start(int port){
try {
serverSocket=new ServerSocket(port);
} catch (IOException e) {
stop();
}
}
public void receive(){
try {
while (!isShutdown){
new Thread(new Dispatcher(serverSocket.accept())).start();
}
} catch (IOException e) {
stop();
}
}
public void stop(){
isShutdown=true;
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;
/**
* 封装Response
*/
public class Response {
private StringBuilder headInfo;
private StringBuilder content;
private BufferedWriter bw;
private static final String CRLF="\r\n";
private static final String BLANCK=" ";
private int len=0;//正文长度
public Response() {
headInfo=new StringBuilder();
content=new StringBuilder();
len=0;
}
public Response(Socket client) {
this();
try {
bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
} catch (IOException e) {
headInfo=null;
}
}
private void createHeadInfo(int code){
//http协议版本、状态代码、描述
headInfo.append("HTTP/").append(BLANCK).append(code).append(BLANCK);
switch (code){
case 200:
headInfo.append("OK").append(CRLF);
break;
case 404:
headInfo.append("NOT FOUND").append(CRLF);
break;
case 500:
headInfo.append("Server Error").append(CRLF);
break;
}
headInfo.append("Server:zhang Server/1.1").append(CRLF);
headInfo.append("Date:").append(new Date()).append(CRLF);
headInfo.append("Content-type:text/html;charset=utf-8").append(CRLF);
headInfo.append("Content-length:").append(len).append(CRLF);
headInfo.append(CRLF);
}
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+=(CRLF+info).getBytes().length;
return this;
}
public void sendToClient(int code){
createHeadInfo(code);
if(null==headInfo){
code=500;
}
try {
bw.append(headInfo.toString());
bw.append(content.toString());
bw.flush();
bw.close();
} catch (IOException e) {
code=500;
}
}
}
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.List;
import java.util.*;
/**
* 封装Request
*/
public class Request {
private String method;
public String getMethod() {
return method;
}
private String url;
public String getUrl() {
return url;
}
private String requestInfo;
private final String CRLF="\r\n";
private String content;
private Socket client;
private Map<String, List<String>> contentMap;
public Request(Socket client) {
this.client=client;
method="";
url="";
requestInfo="";
content="";
contentMap=new HashMap<>();
analy();
}
private void analy(){
if(client==null){
return;
}
try {
InputStream is=new BufferedInputStream(client.getInputStream());
byte[] data=new byte[20460];
int len=is.read(data);
requestInfo=new String(data,0,len);
System.out.println(requestInfo);
} catch (IOException e) {
e.printStackTrace();
}
method=requestInfo.substring(0,requestInfo.indexOf("/")).trim();
String firstLine=requestInfo.substring(0,requestInfo.indexOf(CRLF)).trim();
String path=firstLine.substring(firstLine.indexOf("/"),firstLine.indexOf("HTTP/")).trim();
if(method.equalsIgnoreCase("post")){
this.url=firstLine.substring(firstLine.indexOf("/"),firstLine.indexOf("HTTP/"));
content=requestInfo.substring(requestInfo.lastIndexOf(CRLF));
}else if(method.equalsIgnoreCase("get")){
if(firstLine.contains("?")){
String[] strings=path.split("\\?");
this.url=strings[0];
content=strings[1];
}else{
this.url=path;
}
}
//将参数放进Map中
if(content==null||content.equals("")){
return ;
}
fillMap(content);
}
private void fillMap(String content){
StringTokenizer tokenizer=new StringTokenizer(content,"&");
while (tokenizer.hasMoreTokens()){
String keyValue=tokenizer.nextToken();
String[] keyandValue=keyValue.split("=");
if(keyandValue.length==1){
keyandValue=Arrays.copyOf(keyandValue,2);
}
String key=keyandValue[0].trim();
String value=(null==keyandValue[1])?null:decode(keyandValue[1],"UTF-8");
if(!contentMap.containsKey(key)){
contentMap.put(key,new ArrayList<>());
}
List<String> values=contentMap.get(key);
values.add(value);
}
}
public String[] getValues(String name){
List<String> values=contentMap.get(name);
if(values==null){
return null;
}else{
return values.toArray(new String[0]);
}
}
public String getValue(String name){
String[] values=getValues(name);
if(values==null){
return null;
}else{
return values[0];
}
}
public String decode(String info,String code){
try {
return java.net.URLDecoder.decode(info,code);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
import rui.server.httpserver02.servlet.Servlet;
import java.net.Socket;
/**
* 多线程分发器
*/
public class Dispatcher implements Runnable {
private Request request;
private Response response;
private Socket client;
private int code=200;
public Dispatcher(Socket client) {
this.client=client;
request=new Request(client);
response=new Response(client);
}
@Override
public void run() {
Servlet servlet= null;
try {
servlet = WebApp.getServlet(request.getUrl());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
if(servlet==null){
this.code=500;
}
try {
servlet.opration(request, response);
} catch (Exception e) {
code=404;
}
response.sendToClient(code);
}
}
import rui.server.httpserver02.Request;
import rui.server.httpserver02.Response;
/**
* 处理请求
*/
public abstract class Servlet {
public void opration(Request request, Response response) throws Exception{
this.doGet(request,response);
this.doPost(request,response);
}
protected abstract void doGet(Request request,Response response) throws Exception;
protected abstract void doPost(Request request,Response response) throws Exception;
}
import rui.server.httpserver02.Request;
import rui.server.httpserver02.Response;
public class LoginServlet extends Servlet {
@Override
public void doGet(Request request, Response response) throws Exception{
}
public boolean login(String name,String pwd){
return name.equals("张瑞")&&pwd.equals("123456");
}
@Override
public void doPost(Request request, Response response) throws Exception{
String name=request.getValue("uname");
String pwd=request.getValue("pwd");
if(login(name,pwd)){
response.println("登陆成功");
}else{
response.println("登陆失败");
}
}
}
import java.util.*;
public class ServletContext {
private Map<String,String> servlet;
private Map<String,String> mapping;
public ServletContext() {
servlet=new HashMap<>();
mapping=new HashMap<>();
}
public Map<String, String> getMapping() {
return mapping;
}
public void setMapping(Map<String, String> mapping) {
this.mapping = mapping;
}
public Map<String, String> getServlet() {
return servlet;
}
public void setServlet(Map<String, String> servlet) {
this.servlet = servlet;
}
}
import rui.server.httpserver02.servlet.Servlet;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.util.*;
public class WebApp {
private static ServletContext servletContext;
static{
servletContext=new ServletContext();
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser =null;
try {
parser=factory.newSAXParser();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
Handler handler=new Handler();
try {
parser.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("rui/server/httpserver02/xml/web.xml"),handler);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Map<String,String> mapping=servletContext.getMapping();
for (Mapping map:handler.getMappingList()
) {
for (String urls:map.getUrl()
) {
mapping.put(urls,map.getName());
}
}
Map<String,String> servletMap=servletContext.getServlet();
for (Entity ser:handler.getServletList()
) {
servletMap.put(ser.getName(),ser.getCla());
}
}
public static Servlet getServlet(String url) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if(url==null||(url=url.trim()).equals("")){
return null;
}
String name=servletContext.getServlet().get(servletContext.getMapping().get(url));
return (Servlet)Class.forName(name).newInstance();
}
}
public class Entity {
private String name;
private String cla;//servlet位置
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCla() {
return cla;
}
public void setCla(String cla) {
this.cla = cla;
}
}
import java.util.ArrayList;
import java.util.List;
public class Mapping {
private String name;
private List<String> url;
public Mapping() {
url=new ArrayList<>();
}
public List<String> getUrl() {
return url;
}
public void setUrl(List<String> url) {
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
public class Handler extends DefaultHandler {
private List<Entity> servletList;
private List<Mapping> mappingList;
private Entity entity;
private Mapping mapping;
private String tag;
private boolean isMap=false;
@Override
public void startDocument() throws SAXException {
super.startDocument();
servletList=new ArrayList<>();
mappingList=new ArrayList<>();
entity=new Entity();
mapping=new Mapping();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if(qName!=null){
tag=qName;
if(qName.equals("servlet")){
isMap=false;
}else if(qName.equals("mapping")){
isMap=true;
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String info=new String(ch,start,length).trim();
if(isMap){
if(tag!=null&&tag.equals("name")){
mapping.setName(info);
}else if(tag!=null&&tag.equals("url-pattern")){
mapping.getUrl().add(info);
}
}else{
if(tag!=null&&tag.equals("servlet-name")){
entity.setName(info);
}else if(tag!=null&&tag.equals("servlet-class")){
entity.setCla(info);
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if(qName!=null&&qName.equals("servlet")){
servletList.add(entity);
}else if(qName!=null&&qName.equals("mapping")){
mappingList.add(mapping);
}
tag=null;
}
public List<Entity> getServletList() {
return servletList;
}
public void setServletList(List<Entity> servletList) {
this.servletList = servletList;
}
public List<Mapping> getMappingList() {
return mappingList;
}
public void setMappingList(List<Mapping> mappingList) {
this.mappingList = mappingList;
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>rui.server.httpserver02.servlet.LoginServlet</servlet-class>
</servlet>
<mapping>
<name>login</name>
<url-pattern>/log</url-pattern>
<url-pattern>/login</url-pattern>
<url-pattern>/g</url-pattern>
</mapping>
</web-app>
html文件
<html>
<head>
<title>第一个表单</title>
</head>
<body>
<pre>
method:get/post
get:数据量小,安全性差、默认方式
post:数据量大、安全性相对高
action:请求服务器的路径
id:编号,前端区分唯一性,js中使用
name:名称、后端(服务器)区分唯一性、获取值
只要提交数据给后台,必须使用name
</pre>
<form method="post" action="http://localhost:9999/login">
用户名:<input type="text" name="uname" id="name"/>
密码:<input type="password" name="pwd" id="pass"/>
<input type="submit" value="登录"/>
</form>
</body>
</html>