老师,您好,我在这里遇到了问题
问题描述:在进行Reseponse封装后,服务器能启动起来,但在html文档里面输入内容后登录服务器空指针异常。
相关代码
Response
package cn.bjsxt.server;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import com.bjsxt.util.IOCloseUtil;
public class Response {/*响应*/
private StringBuilder headInfo;//响应头
private StringBuilder content;//响应内容
private int length;//响应内容的长度
//流
private BufferedWriter bw;
//两个常量,换行和空格
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格
//构造方法
public Response(){
headInfo = new StringBuilder();
content = new StringBuilder();
}
//带参构造方法
public Response(OutputStream os){
this();//调用本类的无参构造方法
try {
bw=new BufferedWriter(new OutputStreamWriter(os,"utf-8"));//初始化输出流
} catch (UnsupportedEncodingException e) {
headInfo=null;
}
}
//构造正文部分
public Response print(String info){
content.append(info);
try {
length+=info.getBytes("uft-8").length;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this;
}
public Response println(String info){
content.append(info).append(CRLF);
try {
length+=(info+CRLF).getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this;
}
//构造响应头
private void createHeadInfo(int code){
headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
switch(code){
case 200:
headInfo.append("OK");
break;
case 500:
headInfo.append("SERVER ERROR");
break;
default:
headInfo.append("NOT FOUND");
break;
}
headInfo.append(CRLF);
headInfo.append("Content-Type:text/html;charset=utf-8").append(CRLF);
headInfo.append("Content-Length:"+length).append(CRLF);
headInfo.append(CRLF);
}
/**
* 推送到客户级的浏览器
* */
public void pushToClient(int code){
if(headInfo==null){
code=500;
}
try{
//调用笨了中的构造响应头
this.createHeadInfo(code);
bw.write(headInfo.toString());
bw.write(content.toString());
bw.flush();
this.close();
}catch(IOException e){
e.printStackTrace();
}
}
public void close(){
IOCloseUtil.closeAll(bw);
}
}
Server
package cn.bjsxt.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import com.bjsxt.servlet.Servlet;
import com.bjsxt.util.IOCloseUtil;
public class Server {//服务器,启动和停止服务
private ServerSocket server;
public static void main(String[] args){
Server server = new Server();//创建服务器对象
server.start();
}
public void start(int port){
try {
server = new ServerSocket(port);
this.receive();//调用接收请求信息的方法
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start(){
this.start(8888);
}
private void receive() {
try {
//(1)监听
Socket client = server.accept();
//封装请求信息
Request req = new Request(client.getInputStream());
/* StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1").append(" ").append(200).append(" ").append("OK").append("\r\n");//响应头
sb.append("Content-Type:text/html;charset=utf-8").append("\r\n");//内容文本,编码格式
//内容
String str="<html><head><title>响应结果</title></head><body>成功</body></html>";
sb.append("Content-Length:"+str.getBytes("utf-8").length).append("\r\n");
sb.append("\r\n");
sb.append(str);
//通过输出流发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"utf-8"));
bw.write(sb.toString());
bw.flush();
bw.close();*/
/**
* 做出响应
* */
Response rep=new Response(client.getOutputStream());
Servlet servlet=WebApp.getServlet(req.getUrl());
int code=200;
if(servlet==null){
code=404;
}
try {
servlet.service(req,rep);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rep.pushToClient(code);
IOCloseUtil.closeAll(client);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stop(){
}
}
Request
package cn.bjsxt.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Request {/*请求*/
private InputStream is;//输入流
private String requestInfo;//请求字符串,请求方式,请求路径,参数,协议,协议版本,请求正文。。。
private String method;//请求的方式
private String url;//请求的url
public String getUrl() {
return url;
}
//输入框的name为key,值为value
/*
* key: username value:bjsxt
* key: pwd value:123
* key: hobby value:read,ball
* */
private Map<String,List<String>> parametermapValues;//参数
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格
//构造方法,初始化属性
public Request(){
parametermapValues=new HashMap<String,List<String>>();
method="";
url="";
requestInfo="";
}
public Request(InputStream is){
this();//调用本类无参的构造方法
this.is=is;
try {
byte[] buf=new byte[20480];
int len=this.is.read(buf);
requestInfo=new String(buf,0,len);
} catch (IOException e) {
return;
}
//调用本类中的分解请求信息的方法
this.parseRequestInfo();
}
//分解请求信息的方法
/**
* 请求路径
* 请求方式
* 请求参数
* */
private void parseRequestInfo(){
String paraString="";//用于储存请求参数
//获取请求参数的第一行
String firstLine=requestInfo.substring(0,requestInfo.indexOf(CRLF)).trim();//从0,到第一行换行
//分解出请求方式
int index=firstLine.indexOf("/");
this.method=firstLine.substring(0,index).trim();//获去0到第一个“/”的数据
//分解url ,get可能包含参数,也有可能不包含参数post
String urlString = firstLine.substring(index,firstLine.indexOf("HTTP/")).trim();
//判断请求方式是GET还是POST
if("get".equalsIgnoreCase(this.method)){//包含请求参数
if(urlString.contains("?")){//?之前是路径,之后是参数
String [] urlArray=urlString.split("\\?");//使用?分离路径与参数
this.url=urlArray[1];
paraString=urlArray[1];
}else{ //post不包含请求参数
this.url=urlString;
}
}else{//post不包含请求参数
this.url=urlString;
paraString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();//获取最后一行
}
if(paraString.equals("")){
return;
}
//请求参数
//System.out.println(paraString);
//调用本类中分解请求参数的方法
this.parseParam(paraString);
}
//根据表单元素的name获取多个值
public String [] getParamterValues(String name){
//根据key获取value
List<String> values=parametermapValues.get(name);
if(values==null){
return null;
}else{
return values.toArray(new String [0]);
}
}
//根据表单元素获的name获取单个值
public String getParameter(String name){
//调用本类中根据name获取多个值的方法
String [] values=getParamterValues(name);
if((values==null)){
return null;
}else{
return values[0];
}
}
/*public void show(){
System.out.println(this.url);
System.out.println(this.method);
}*/
//username=bjsxt&pwd=123&hobby=ball&hobby=paint
/**
* username=bjsxt
* pwd123
* hobby=ball
*
* username=
* */
private void parseParam(String prarString){
String [] token = prarString.split("&");
for(int i=0;i<token.length;i++){
String keyValues=token[i];
String [] keyValue=keyValues.split("=");//username bjsxt pwd 123
if(keyValue.length==1){ //username=
keyValue=Arrays.copyOf(keyValue, 2);
keyValue[1]=null;
}
//将表单元素的name与name对应的值储存到Map集合
String key=keyValue[0].trim();
String value=keyValue[1]==null?null:decode(keyValue[1].trim(),"utf-8");
//放到集合中储存
if(!parametermapValues.containsKey(key)){//如果键不存在,去创建
parametermapValues.put(key, new ArrayList<String>());
}//如果键存在,将值添加进来
List<String> values=parametermapValues.get(key);
values.add(value);
}
}
public static void main(String[] args){
Request req = new Request();
//调用分解参数的方法
req.parseParam("username=%E5%8C%97%E4%BA%AC%E5%B0%9A%E5%AD%A6%E5%A0%82&pwd=123&hobby=ball&hobby=paint");
Map<String,List<String>> map=req.parametermapValues;
Set<String>key=map.keySet();
for (String string : key) {
System.out.println(string+"\t"+map.get(string));
}
}
//处理中文,因为浏览器对中文进行了编码,进行解码
private String decode(String value,String code){
try {
return URLDecoder.decode(value,code);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
运行图

代码包
http_server4.rar