创建HttpContext
声明响应的状态码,状态码的描述信息(状态码匹配描述信息)
封装成map的结构
在静态代码块中设置map的值
package context;
import java.util.HashMap;
import java.util.Map;
/**
* 这个类用来封装http协议的相关信息
*
*/
public class HttpContext {
//1声明响应的状态码 ,状态码描述信息
//常量是全局共享的要public
public static final int CODE_OK=200;
public static final int CODE_ERROR=500;
public static final int CODE_NOTFOUND=404;
//状态码的描述信息
public static final String DESC_NOTFOUND="Not Found";
public static final String DESC_ERROR="Internal Server Error";
public static final String DESC_OK="OK";
//封装成map的结构
//key存状态码,value存描述
public static Map map=new HashMap();
//静态代码块中设置map的值
static{
init();
}
private static void init() {
map.put(CODE_OK, DESC_OK);
map.put(CODE_ERROR, DESC_ERROR);
map.put(CODE_NOTFOUND, DESC_NOTFOUND);
}
}
改造HttpResponse类
package http;
import java.io.OutputStream;
import java.io.PrintStream;
import context.HttpContext;
/**
* 这个类用来封装响应信息
*/
public class HttpResponse {
// 声明4个响应参数,get set
// HTTP/1.1 200 OK
// Content-Type
// Content-Length
private String protocol;// 协议名版本号
private int status;// 状态码 404 500 403 400
private String contentType;// 响应类型
private int contentLength;// 响应长度
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public int getContentLength() {
return contentLength;
}
public void setContentLength(int contentLength) {
this.contentLength = contentLength;
}
// 在构造函数中传入OutputStream对象
private OutputStream out;
public HttpResponse(OutputStream out) {
this.out = out;
}
// 改造getOut方法,并给参数赋值
// 保证响应头只被发送一次
boolean isSend;// 默认是false
public OutputStream getOut() {
if (!isSend) {// 拼接响应头的过程
PrintStream ps = new PrintStream(out);// ps有换行的功能
// 拼接状态行
ps.println(protocol + " " + status + " "+HttpContext.map.get(status));
// 响应类型
ps.println("Content-Type:" + contentType);
// 响应长度
ps.println("Content-Length:" + contentLength);
// 空白行
ps.println();
isSend=true;//改变发送状态
}
return out;
}
public void setOut(OutputStream out) {
this.out = out;
}
}
改造ClientHandler类
package core;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import context.HttpContext;
import context.ServerContext;
import http.HttpRequest;
import http.HttpResponse;
import util.JDBCUtils;
/**
* 这个类用来完成WebServer类的优化,提取代码
*
*/
public class ClientHandler implements Runnable {
// 创建代表客户端的Socket对象
private Socket socket;
// 在构造函数中传入Socket对象并保存在类中
public ClientHandler(Socket socket) {
this.socket = socket;// this.socket获取等号左边的成员变量
}
// 重写run方法
public void run() {
// 创建PrintStream对象
try {
//利用请求对象完成请求过程
HttpRequest request=new HttpRequest(socket.getInputStream());
if(request.getUri()!=null&&request.getUri().length()>0){
//利用响应对象完成响应过程
HttpResponse response=new HttpResponse(socket.getOutputStream());
//判断用户是否要完成登录或者注册的功能
if(request.getUri().startsWith("/LoginUser")||request.getUri().startsWith("/RegistUser"))
{
//利用service方法完成登录或者注册的过程
service(request,response);
return;
}
response.setProtocol(ServerContext.protocol);
File file=new File(ServerContext.webRoot+request.getUri());
response.setContentType(getContentTypeByFile(file));
//判断访问的文件是否存在
if(!file.exists())
{
//跳转到WebContent/404.html
file=new File(ServerContext.webRoot+"/"+ServerContext.notFoundPage);
//设置404状态码
response.setStatus(HttpContext.CODE_NOTFOUND);
}else{
response.setStatus(HttpContext.CODE_OK);
}
response.setContentLength((int)file.length());
// 数据响应:响应网页文件 带缓存的读入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
byte[] bs = new byte[(int) file.length()];
System.out.println("==============");
bis.read(bs);
// 响应
response.getOut().write(bs);
response.getOut().flush();
bis.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//这个方法完成注册或者登录,操作数据库的功能 jdbc技术
private void service(HttpRequest request, HttpResponse response) {
//完成注册,用jdbc向数据库表插入记录
if(request.getUri().startsWith("/RegistUser"))
{
Connection conn=null;
PreparedStatement ps=null;
try {
//1注册驱动 2获得数据库连接
conn=JDBCUtils.getConnection();
//3获取传输器
String sql="insert into user values (null,?,?)";
ps = conn.prepareStatement(sql);
//4执行sql
//设置参数
String name=request.getParemeter("username");
String pwd=request.getParemeter("password");
ps.setString(1, name);
ps.setString(2, pwd);
System.out.println(name+" "+pwd);
//5遍历结果集
int rows = ps.executeUpdate();
System.out.println(rows+"be affected");
//给浏览器响应注册成功页面
response.setProtocol(ServerContext.protocol);//响应的协议和版本号
response.setStatus(HttpContext.CODE_OK);
//响应注册成功页面文件
File file=new File(ServerContext.webRoot+"/reg_success.html");
response.setContentType(getContentTypeByFile(file));
response.setContentLength((int)file.length());//响应长度
//读文件写文件
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
byte[] b=new byte[(int) file.length()];
bis.read(b);
response.getOut().write(b);
response.getOut().flush();
bis.close();
socket.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//6释放资源
JDBCUtils.close(null, ps, conn);
}
}
}
//根据访问文件的后缀名作为key,去map中找value
private String getContentTypeByFile(File file) {
//fileName=index.html
String fileName = file.getName();
//根据文件名获取文件的后缀名
String ext = fileName.substring(fileName.lastIndexOf(".")+1);//从.后的位置开始截取
//拿着后缀名作为key,去map中找value
//{html,text/html jpg,image/jpeg}
String val = ServerContext.typeMap.get(ext);
return val;
}
}
原ServerContext
package context;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 这个类用来提取服务器相关参数
*/
public class ServerContext {
// 1.声明四个变量
public static int port;// 服务器的端口号
public static int maxSize;// 最大线程数
public static String protocol;// 协议名和版本号
public static String webRoot;// 服务器资源存放的根目录
public static String notFoundPage;//声明404页面
//typemapping的值
//map--map
public static Map typeMap=new HashMap();
// 2.在静态代码块中完成初始化变量
static {
init();
}
// 读取配置文件,给变量赋值
private static void init() {
try {
// 读取配置文件的核心对象
SAXReader reader = new SAXReader();
// 读取指定位置的文件
Document doc = reader.read("config/server.xml");
// 获取根节点
Element server = doc.getRootElement();
// 根据根节点获取根节点下的子节点
Element service = server.element("service");
Element connect = service.element("connect");
// 获取port属性
port = Integer.valueOf(connect.attributeValue("port"));
// 获取maxSize属性
maxSize = Integer.valueOf(connect.attributeValue("maxSize"));
// 获取protocol属性
protocol = connect.attributeValue("protocol");
// 获取webRoot值
webRoot = service.elementText("webRoot");
//给404页面赋值
notFoundPage=service.elementText("not-found-page");
@SuppressWarnings("unchecked")
List list = server.element("typemappings").elements();
for (Element element : list) {
String key=element.attributeValue("ext");
String value=element.attributeValue("type");
//把key和value存入typeMap
typeMap.put(key, value);
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
原WebServer
package core;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import context.ServerContext;
/**
* 这个类用来代表服务器端的程序
*/
public class WebServer {
// 1.声明ServerSocket,代表服务器
private ServerSocket server;
//声明线程池对象
private ExecutorService pool;
// 2.在构造函数初始化ServerSocket对象
public WebServer() {
try {
server = new ServerSocket(ServerContext.port);
//在构造函数中初始化线程池
pool=Executors.newFixedThreadPool(ServerContext.maxSize);//固定大小的线程池
} catch (IOException e) {
e.printStackTrace();
}
}
// 3.创建start方法,用来接收请求,处理业务,响应
public void start() {
// 用来接收请求
try {
while (true) {
// 返回客户端
Socket socket = server.accept();
//改造start方法
pool.execute(new ClientHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 创建mian方法启动服务器
public static void main(String[] args) {
WebServer server = new WebServer();
server.start();
}
}
原HttpRequest
package http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
/**
* 这个类用来封装请求信息
*/
public class HttpRequest {
// 声明三个请求参数 GET /index.html HTTP/1.1
private String method;// 请求方式
private String uri;// 请求资源的路径
private String protocol;// 请求遵循的协议名,版本号
// 声明map,存放用户输入的用户名和密码
private Map map = new HashMap();
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
// 在构造函数中初始化请求参数
public HttpRequest(InputStream in) {
// 获取请求流
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
// 获取请求行
try {
String line = reader.readLine();
// GET /index.html HTTP/1.1
if (line != null && line.length() >= 0) {
// 按空格切分字符串
String[] datas = line.split(" ");
method = datas[0];
uri = datas[1];
// 设置网站的默认主页
if (uri.equals("/")) {
uri = "/index.html";
}
// 获取用户在浏览器上输入的值
// 目的是把数据拿到,放入数据库中
// uri:/RegistUser?username=123&password=123
if (uri != null && uri.contains("?")) {
// 按照?切割
// xiaochuan =username=123&password=123
String xiaochuan = uri.split("\\?")[1];
// 按照&切割
// [username=123,password=123]
String[] strs = xiaochuan.split("&");
// 遍历数组
for (String string : strs) {
String key = string.split("=")[0];
String value = string.split("=")[1];
System.out.println("key"+key+"value"+value);
// 封装成map{username,123 password,123}
map.put(key, value);
}
}
protocol = datas[2];
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 提供公共的方法,根据key查询value
// 查询username输入的值
public String getParemeter(String key) {
return map.get(key);
}
}
JDBCUtils
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
/**
* 这个类用来完成JDBC工具类的开发
*/
public class JDBCUtils {
//私有化构造函数,(无法创建对象)防止外界直接创建对象
private JDBCUtils(){};
//提供静态方法getConnection,用来对外提供数据库连接对象java.sql.Connection
public static Connection getConnection(){
//1.注册驱动
Connection conn=null;
try {
//读取属性文件的数据getBundle("jdbc")-jdbc是文件名
ResourceBundle rb=ResourceBundle.getBundle("jdbc");
String driverClass=rb.getString("driverClass").trim();
Class.forName(driverClass);
//2.获取数据库连接
String url=rb.getString("jdbcUrl").trim();
String userName=rb.getString("user").trim();
String passWord=rb.getString("password").trim();
conn=DriverManager.getConnection(url,userName,passWord);
return conn;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//提供静态的close方法,用来释放资源
public static void close(ResultSet rs,Statement st,Connection conn){
if(rs!=null)
{
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs=null;//手动置空,等待垃圾回收
}
}
if(st!=null)
{
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
st=null;
}
}
if(conn!=null)
{
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs=null;
}
}
}
}
404
抱歉!页面无法访问....
Active页
这是active页!
- 激活
- 购买
索引页
这是主页
你好!
登陆成功页
恭喜
登录成功!
回到首页
索引页
这是主页
你好!
登录页面
注册成功页
恭喜
注册成功
索引页
注册
你好!