java http nio_计算机网络(13)-----java nio手动实现简单的http服务器

java nio手动实现简单的http服务器

需求分析

最近在学习HTTP协议,还是希望动手去做一做,所以就自己实现了一个http服务器,主要功能是将http请求封装httpRequest,通过解析web.xml,用不同的handler处理不同的uri,然后再将封装好的httpResponse还原成http响应返回浏览器。

代码已经成功上传至  GitHub

如果对你学习JavaNIO有帮助的话,记得给个star哦!

代码

使用java nio实现监听,完成服务器监听线程

packagecom.cszjo.com.http.server;importjava.io.ByteArrayOutputStream;importjava.io.IOException;importjava.net.InetSocketAddress;importjava.net.ServerSocket;importjava.nio.ByteBuffer;importjava.nio.channels.SelectionKey;importjava.nio.channels.Selector;importjava.nio.channels.ServerSocketChannel;importjava.nio.channels.SocketChannel;importjava.util.Iterator;importjava.util.Set;importorg.apache.log4j.Logger;importcom.cszjo.com.http.handler.HttpHandler;importcom.cszjo.com.http.utils.XMLUtil;/*** @Title: Server.java

* @Description: 打开服务

*@author: Han

* @date: 2016年7月12日 下午7:22:47*/

public class Server implementsRunnable {private boolean interrupted = false;private Logger logger = Logger.getLogger(Server.class);public Server(booleaninterrupted) {this.interrupted =interrupted;

}

@Overridepublic voidrun() {try{//打开一个选择器

Selector selector =Selector.open();//打开ServerSocketChannel通道

ServerSocketChannel serverSocketChannel =ServerSocketChannel.open();//得到ServerSocket对象

ServerSocket serverSocket =serverSocketChannel.socket();//ServerSocketChannel通道监听server.xml中设置的端口

String portStr = XMLUtil.getRootElement("server.xml").element("port").getText();

serverSocket.setReuseAddress(true);try{

serverSocket.bind(newInetSocketAddress(Integer.parseInt(portStr)));

}catch(Exception e) {

logger.error("绑定端口失败,请检查server.xml中是否设置了port属性");return;

}

logger.info("成功绑定端口" +portStr);//将通道设置为非阻塞模式

serverSocketChannel.configureBlocking(false);//将serverSocketChannel注册给选择器,并绑定ACCEPT事件

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

logger.info("服务器启动成功");while(!interrupted) {//查询就绪的通道数量

int readyChannels =selector.select();//没有就绪的则继续进行循环

if(readyChannels == 0)continue;//获得就绪的selectionKey的set集合

Set keys =selector.selectedKeys();//获得set集合的迭代器

Iterator iterator =keys.iterator();while(iterator.hasNext()) {

SelectionKey key=iterator.next();if(key.isAcceptable()) {//该key有ACCEPT事件//将监听得到的channel强转为ServerSocketChannel

ServerSocketChannel server =(ServerSocketChannel) key.channel();//得到接收到的SocketChannel

SocketChannel socketChannel =server.accept();if(socketChannel != null) {

logger.info("收到了来自" +((InetSocketAddress)socketChannel.getRemoteAddress()).getHostString()+ "的请求");//将socketChannel设置为阻塞模式

socketChannel.configureBlocking(false);//将socketChannel注册到选择器

socketChannel.register(selector, SelectionKey.OP_READ);

}

}else if(key.isReadable()) {//该key有Read事件

SocketChannel socketChannel =(SocketChannel) key.channel();

String requestHeader= "";//拿出通道中的Http头请求

try{

requestHeader=receive(socketChannel);

}catch(Exception e) {

logger.error("读取socketChannel出错");return;

}//启动线程处理该请求,if条件判断一下,防止心跳包

if(requestHeader.length() > 0) {

logger.info("该请求的头格式为\r\n" +requestHeader);

logger.info("启动了子线程..");new Thread(newHttpHandler(requestHeader, key)).start();

}

}else if(key.isWritable()) {//该key有Write事件

logger.info("有流写出!");

SocketChannel socketChannel=(SocketChannel) key.channel();

socketChannel.shutdownInput();

socketChannel.close();

}//从key集合中删除key,这一步很重要,就是因为没写这句,Selector.select()方法一直返回的是0//原因分析可能是不从集合中删除,就不会回到I/O就绪事件中

iterator.remove();

}

}

}catch(IOException e) {

e.printStackTrace();

}catch(Exception e) {

e.printStackTrace();

}

}private String receive(SocketChannel socketChannel) throwsException {//声明一个1024大小的缓冲区

ByteBuffer buffer = ByteBuffer.allocate(1024);byte[] bytes = null;int size = 0;//定义一个字节数组输出流

ByteArrayOutputStream baos = newByteArrayOutputStream();//将socketChannel中的数据写入到buffer中,此时的buffer为写模式,size为写了多少个字节

while ((size = socketChannel.read(buffer)) > 0) {//将写模式改为读模式//The limit is set to the current position and then the position is set to zero.//将limit设置为之前的position,而将position置为0,更多java nio的知识会写成博客的

buffer.flip();

bytes= new byte[size];//将Buffer写入到字节数组中

buffer.get(bytes);//将字节数组写入到字节缓冲流中

baos.write(bytes);//清空缓冲区

buffer.clear();

}//将流转回字节数组

bytes =baos.toByteArray();return newString(bytes);

}

}

实现MapHandler,解析web.xml,完成uri到对应handler的映射,该handler使用单例完成

packagecom.cszjo.com.http.handler;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importorg.apache.log4j.Logger;importorg.dom4j.Element;importcom.cszjo.com.http.utils.XMLUtil;/*** @Title: HandlerMap.java

* @Description: HandlerMap(单例) 访问路径--->相应解决类

*@author: Han

* @date: 2016年7月15日 下午4:52:29*/

public classMapHandler {//访问路径对应控制类

private static Map handlerMap = new HashMap<>();private static MapHandler instance = null;//将构造器私有化

privateMapHandler(){}//得到HandlerMap对象实例

public staticMapHandler getContextMapInstance() {if(instance == null) {synchronized (MapHandler.class) {if(instance == null) {

instance= newMapHandler();//得到web.xml的根路径

Element rootElement = XMLUtil.getRootElement("web.xml");//得到handler的集合

List handlers =XMLUtil.getElements(rootElement);for(Element element : handlers) {

Element urlPattenEle= XMLUtil.getElement(element, "url-patten");//得到urlPatten(uri)

String urlPatten =XMLUtil.getElementText(urlPattenEle);

Element handlerClazzEle= XMLUtil.getElement(element, "handler-class");//得到handler 的class文件路径

String clazzPath =XMLUtil.getElementText(handlerClazzEle);

Class> clazz = null;try{//通过反射得到handler实例化对象,然后以键值对的形式存储

clazz =Class.forName(clazzPath);

Handler handler=(Handler)clazz.newInstance();

instance.getHandlerMap().put(urlPatten, handler);

Logger.getLogger(MapHandler.class).info("成功添加Handler " +clazzPath);

}catch(ClassNotFoundException e) {

e.printStackTrace();

}catch(InstantiationException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}

}

}

}

}returninstance;

}public MapgetHandlerMap() {returnhandlerMap;

}

}

web.xml

com.cszjo.com.http.handler.impl.LogionHandler

/login

httpHandler,处理一次http请求,通过uri启动不同的handler进行处理

packagecom.cszjo.com.http.handler;importjava.nio.channels.SelectionKey;importorg.apache.log4j.Logger;importcom.cszjo.com.http.context.Context;importcom.cszjo.com.http.context.impl.HttpContext;importcom.cszjo.com.http.handler.impl.NotFoundHandler;/*** @Title: HandlerHttp.java

* @Description: 处理一次Http请求

*@author: Han

* @date: 2016年7月15日 下午7:07:21*/

public class HttpHandler implementsRunnable {//就绪的I/O键

privateSelectionKey key;//上下文

private Context context = newHttpContext();//http请求字符串

privateString requestHeader;//针对uri选择不同的处理器

privateHandler handler;private Logger logger = Logger.getLogger(HttpHandler.class);publicHttpHandler(String requestHeader, SelectionKey key) {this.key =key;this.requestHeader =requestHeader;

}

@Overridepublic voidrun() {//初始化上下文

context.setContext(requestHeader, key);//得到uri

String uri =context.getRequest().getUri();

logger.info("得到了uri " +uri);//得到MapHandler集合(uri-->handler)

handler =MapHandler.getContextMapInstance().getHandlerMap().get(uri);//找不到对应的handler

if(handler == null) {//404Handler进行处理

handler = newNotFoundHandler();

}//初始化handler并执行

handler.init(context);

}

}

Context上下文抽象类设计

packagecom.cszjo.com.http.context;importjava.nio.channels.SelectionKey;/*** @Title: Context.java

* @Description: Http上下文抽象类

*@author: Han

* @date: 2016年7月16日 下午2:19:06*/

public abstract classContext {protectedRequest request;protectedResponse response;/*** 设置当前连接的上下文

*@param:@return*@return: Context

* @Autor: Han*/

public abstract voidsetContext(String requestHeader, SelectionKey key);/*** 得到Request

*@param:@return*@return: Request

* @Autor: Han*/

publicRequest getRequest() {returnrequest;

}/*** 得到Response

*@param:@return*@return: Response

* @Autor: Han*/

publicResponse getResponse() {returnresponse;

}

}

HttpContext的实现

packagecom.cszjo.com.http.context.impl;importjava.nio.channels.SelectionKey;importcom.cszjo.com.http.context.Context;importcom.cszjo.com.http.context.Request;importcom.cszjo.com.http.context.Response;/*** @Title: HttpContext.java

* @Description: HttpContext http上下文

*@author: Han

* @date: 2016年7月16日 下午2:20:00*/

public class HttpContext extendsContext {privateRequest request;privateResponse response;

@Overridepublic voidsetContext(String requestHeader, SelectionKey key) {//初始化request

request = newHttpRequest(requestHeader);//初始化response

response = newHttpResponse(key);

setRequest();

setResponse();

}private voidsetRequest() {super.request = this.request;

}private voidsetResponse() {super.response = this.response;

}

}

Request接口设计

packagecom.cszjo.com.http.context;importjava.util.Map;importjava.util.Set;/*** @Title: Request.java

* @Description: 接口设计:Request接口

*@author: Han

* @date: 2016年7月15日 下午9:21:45*/

public interfaceRequest {public static final String POST = "POST";public static final String GET = "GET";/*** 得到参数

*@param:@return*@return: Map

* @Autor: Han*/

public MapgetAttribute();/*** 得到请求方式

*@param:@return*@return: String

* @Autor: Han*/

publicString getMethod();/*** 得到URI

*@param:@return*@return: String

* @Autor: Han*/

publicString getUri();/*** 版本协议

*@param:@return*@return: String

* @Autor: Han*/

publicString getProtocol();/*** 得到请求头Map

*@param:@return*@return: String

* @Autor: Han*/

public MapgetHeaders();/*** 得到请求头参数集合

*@param:@return*@return: String

* @Autor: Han*/

public SetgetHeaderNames();/*** 根据请求头名得到对应的请求头

*@param:@return*@return: String

* @Autor: Han*/

publicObject getHeader(String key);

}

HttpRequest实现

packagecom.cszjo.com.http.context.impl;importjava.util.HashMap;importjava.util.Map;importjava.util.Set;importcom.cszjo.com.http.context.Request;/*** @Title: HttpRequest.java

* @Description: HTTP请求(还有很多方法可以写的)

*@author: Han

* @date: 2016年7月15日 下午9:16:45*/

public class HttpRequest implementsRequest {//参数

private Map attribute = new HashMap<>();//请求头(Request Header)

private Map headers = new HashMap<>();//请求方法

privateString method;//uri

privateString uri;//协议版本

privateString protocol;publicHttpRequest(String httpHeader) {

init(httpHeader);

}private voidinit(String httpHeader) {//将请求分行

String[] headers = httpHeader.split("\r\n");//设置请求方式

initMethod(headers[0]);//设置URI

initURI(headers[0]);//设置版本协议

initProtocol(headers[0]);//设置请求头

initRequestHeaders(headers);

}/*** 设置请求方法

*@param:@paramstr

*@return: void

* @Autor: Han*/

private voidinitMethod(String str) {

method= str.substring(0, str.indexOf(" "));

}/*** 设置request参数

*@param:@paramattr

*@return: void

* @Autor: Han*/

private voidinitAttribute(String attr) {

String[] attrs= attr.split("&");for(String string : attrs) {

String key= string.substring(0, string.indexOf("="));

String value= string.substring(string.indexOf("=") + 1);

attribute.put(key, value);

}

}/*** 设置uri

*@param:@paramstr

*@return: void

* @Autor: Han*/

private voidinitURI(String str) {

uri= str.substring(str.indexOf(" ") + 1, str.indexOf(" ", str.indexOf(" ") + 1));//如果是get方法,则后面跟着参数 /index?a=1&b=2

if(method.toUpperCase().equals("GET")) {//有问号表示后面跟有参数

if(uri.contains("?")) {

String attr= uri.substring(uri.indexOf("?") + 1, uri.length());

uri= uri.substring(0, uri.indexOf("?"));

initAttribute(attr);

}

}

}/*** 初始化请求头

*@param:@paramstrs

*@return: void

* @Autor: Han*/

private voidinitRequestHeaders(String[] strs) {//去掉第一行

for(int i = 1; i < strs.length; i++) {

String key= strs[i].substring(0, strs[i].indexOf(":"));

String value= strs[i].substring(strs[i].indexOf(":") + 1);

headers.put(key, value);

}

}/*** 设置协议版本

*@param:@paramstr

*@return: void

* @Autor: Han*/

private voidinitProtocol(String str) {

protocol= str.substring(str.lastIndexOf(" ") + 1, str.length());

}

@Overridepublic MapgetAttribute() {returnattribute;

}

@OverridepublicString getMethod() {returnmethod;

}

@OverridepublicString getUri() {returnuri;

}

@OverridepublicString getProtocol() {returnprotocol;

}

@Overridepublic MapgetHeaders() {returnheaders;

}

@Overridepublic SetgetHeaderNames() {returnheaders.keySet();

}

@OverridepublicObject getHeader(String key) {returnheaders.get(key);

}

}

Response接口设计

packagecom.cszjo.com.http.context;importjava.nio.channels.SelectionKey;importcom.cszjo.com.http.utils.XMLUtil;/*** @Title: Response.java

* @Description: 接口设计:response接口

*@author: Han

* @date: 2016年7月16日 下午2:19:25*/

public interfaceResponse {//服务器名字

public static final String SERVER_NAME = XMLUtil.getRootElement("server.xml").element("serverName").getText();publicString getContentType();public intgetStatuCode();publicString getStatuCodeStr();publicString getHtmlFile();public voidsetHtmlFile(String htmlFile);publicSelectionKey getKey();public voidsetContentType(String contentType);public void setStatuCode(intstatuCode);public voidsetStatuCodeStr(String statuCodeStr);

}

httpResponse实现

packagecom.cszjo.com.http.context.impl;importjava.nio.channels.SelectionKey;importcom.cszjo.com.http.context.Response;/*** @Title: HttpResponse.java

* @Description: http响应

*@author: Han

* @date: 2016年7月16日 下午2:20:41*/

public class HttpResponse implementsResponse {privateSelectionKey key;//内容类型 defalut 为text/html

private String contentType = "text/html";//响应码 defalut 为200

private int StatuCode = 200;private String statuCodeStr = "OK";private String htmlFile = "";publicHttpResponse(SelectionKey key) {this.key =key;

}

@OverridepublicString getContentType() {returncontentType;

}

@Overridepublic intgetStatuCode() {returnStatuCode;

}

@OverridepublicSelectionKey getKey() {returnkey;

}

@OverridepublicString getStatuCodeStr() {returnstatuCodeStr;

}

@OverridepublicString getHtmlFile() {returnhtmlFile;

}

@Overridepublic voidsetHtmlFile(String htmlFile) {this.htmlFile =htmlFile;

}

@Overridepublic voidsetContentType(String contentType) {this.contentType =contentType;

}

@Overridepublic void setStatuCode(intstatuCode) {

StatuCode=statuCode;

}

@Overridepublic voidsetStatuCodeStr(String statuCodeStr) {this.statuCodeStr =statuCodeStr;

}

}

处理器Handler的接口设计

packagecom.cszjo.com.http.handler;importcom.cszjo.com.http.context.Context;/*** @Title: Handler.java

* @Description: 接口设计:处理器Handler接口

*@author: Han

* @date: 2016年7月12日 下午7:12:37*/

public interfaceHandler {/*** 初始化handler

*@param:@paramcontext

*@return: void

* @Autor: Han*/

public voidinit(Context context);/*** handler service(service应该不是这样做的... - -!)

*@param:@paramcontext

*@return: void

* @Autor: Han*/

public voidservice(Context context);/*** Get形式执行该方法

*@param:@paramcontext

*@return: void

* @Autor: Han*/

public voiddoGet(Context context);/*** POST形式执行该方法

*@param:@paramcontext

*@return: void

* @Autor: Han*/

public voiddoPost(Context context);/*** 销毁Handler(并没有销毁... - -!)

*@param:@paramcontext

*@return: void

* @Autor: Han*/

public voiddestory(Context context);

}

因为doGet或者doPost只会执行一个,所以中间在写一个抽象类,具体的handler只需要重写该抽象类的方法既可

packagecom.cszjo.com.http.handler.abs;importcom.cszjo.com.http.context.Context;importcom.cszjo.com.http.context.Request;importcom.cszjo.com.http.handler.Handler;importcom.cszjo.com.http.handler.ResponseHandler;/*** @Title: AbstractHandler.java

* @Description: Handler抽象类

*@author: Han

* @date: 2016年7月16日 下午2:11:57*/

public class AbstractHandler implementsHandler {protectedContext context;

@Overridepublic voidinit(Context context) {this.context =context;this.service(context);

}

@Overridepublic voidservice(Context context) {//通过请求方式选择具体解决方法

String method =context.getRequest().getMethod();if(method.equals(Request.GET)) {this.doGet(context);

}else if(method.equals(Request.POST)) {this.doPost(context);

}

sendResponse(context);

}

@Overridepublic voiddoGet(Context context) {

}

@Overridepublic voiddoPost(Context context) {

}

@Overridepublic voiddestory(Context context) {

context= null;

}/*** 通过上下文,返回封装response响应

*@param:@paramcontext

*@return: void

* @Autor: Han*/

private voidsendResponse(Context context) {newResponseHandler().write(context);

}

}

Login Handler的实现

packagecom.cszjo.com.http.handler.impl;importorg.apache.log4j.Logger;importcom.cszjo.com.http.context.Context;importcom.cszjo.com.http.handler.abs.AbstractHandler;/*** @Title: LogionHandler.java

* @Description: 解决login业务逻辑

*@author: Han

* @date: 2016年7月16日 下午2:08:18*/

public class LogionHandler extendsAbstractHandler{private Logger logger = Logger.getLogger(LogionHandler.class);

@Overridepublic voiddoGet(Context context) {

logger.info("进入了handler--->LoginHandler");

context.getResponse().setHtmlFile("login.html");

}

}

未找到请求的URI,所以返回404,该处理器处理404错误

packagecom.cszjo.com.http.handler.impl;importorg.apache.log4j.Logger;importcom.cszjo.com.http.context.Context;importcom.cszjo.com.http.context.Response;importcom.cszjo.com.http.handler.abs.AbstractHandler;/*** @Title: NotFoundHandler.java

* @Description: 解决404NotFound响应

*@author: Han

* @date: 2016年7月16日 下午2:08:44*/

public class NotFoundHandler extendsAbstractHandler {private Logger logger = Logger.getLogger(NotFoundHandler.class);privateResponse response;

@Overridepublic voiddoGet(Context context) {

logger.info("进入了404Handler");

response=context.getResponse();

response.setStatuCode(404);

response.setStatuCodeStr("Not Found");

response.setHtmlFile("404.html");

}

}

封装完http请求,下一步就需要还原response响应了

packagecom.cszjo.com.http.handler;importjava.io.BufferedReader;importjava.io.File;importjava.io.FileNotFoundException;importjava.io.FileReader;importjava.io.IOException;importjava.nio.ByteBuffer;importjava.nio.channels.SelectionKey;importjava.nio.channels.Selector;importjava.nio.channels.SocketChannel;importjava.util.Date;importorg.apache.log4j.Logger;importcom.cszjo.com.http.context.Context;importcom.cszjo.com.http.context.Request;importcom.cszjo.com.http.context.Response;/*** @Title: ResponseHandler.java

* @Description: 封装response响应

*@author: Han

* @date: 2016年7月16日 下午2:09:45*/

public classResponseHandler {privateRequest request;privateResponse response;privateString protocol;private intstatuCode;privateString statuCodeStr;privateByteBuffer buffer;privateString serverName;privateString contentType;privateSocketChannel channel;privateSelector selector;privateSelectionKey key;private Logger logger = Logger.getLogger(ResponseHandler.class);privateBufferedReader reader;privateString htmlFile;public voidwrite(Context context) {//从context中得到相应的参数

request =context.getRequest();

response=context.getResponse();

buffer= ByteBuffer.allocate(1024);

protocol=request.getProtocol();

statuCode=response.getStatuCode();

statuCodeStr=response.getStatuCodeStr();

serverName=Response.SERVER_NAME;

contentType=response.getContentType();

key=response.getKey();

selector=key.selector();

channel=(SocketChannel)key.channel();

htmlFile=response.getHtmlFile();//得到响应正文内容

String html =setHtml(context);

StringBuilder sb= newStringBuilder();//状态行

sb.append(protocol + " " + statuCode + " " + statuCodeStr + "\r\n");//响应头

sb.append("Server: " + serverName + "\r\n");

sb.append("Content-Type: " + contentType + "\r\n");

sb.append("Date: " + new Date() + "\r\n");if(reader != null) {

sb.append("Content-Length: " + html.getBytes().length + "\r\n");

}//响应内容

sb.append("\r\n");

sb.append(html);

buffer.put(sb.toString().getBytes());//从写模式,切换到读模式

buffer.flip();try{

logger.info("生成相应\r\n" +sb.toString());

channel.register(selector, SelectionKey.OP_WRITE);

channel.write(buffer);

}catch(IOException e) {

e.printStackTrace();

}

}privateString setHtml(Context context) {

StringBuilder html= null;if(htmlFile != null && htmlFile.length() > 0) {

html= newStringBuilder();try{

reader= new BufferedReader(new FileReader(newFile(htmlFile)));

String htmlStr;

htmlStr=reader.readLine();while(htmlStr != null) {

html.append(htmlStr+ "\r\n");

htmlStr=reader.readLine();

}

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}

}returnhtml.toString();

}

}

程序启动入口

packagecom.cszjo.com.http.server;/*** @Title: Solution.java

* @Description: 启动Web服务器入口

*@author: Han

* @date: 2016年7月12日 下午7:11:15*/

public classSolution {//启动方法

public static voidmain(String[] args) {new Thread(new Server(false)).start();

}

}

XMLUtils

packagecom.cszjo.com.http.utils;importjava.io.File;importjava.util.List;importorg.apache.log4j.Logger;importorg.dom4j.Document;importorg.dom4j.DocumentException;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;/*** @Title: XMLUtil.java

* @Description: 解决XML读取问题

*@author: Han

* @date: 2016年7月15日 下午4:55:28*/

public classXMLUtil {private static Logger logger = Logger.getLogger(XMLUtil.class);private static SAXReader reader = newSAXReader();/*** 得到根节点

*@param:@paramxmlPath

*@param:@return*@return: Element

* @Autor: Han*/

public staticElement getRootElement(String xmlPath) {

Document document= null;;try{

document= reader.read(newFile(xmlPath));

}catch(DocumentException e) {

logger.error("找不到指定的xml文件的路径" + xmlPath + "!");return null;

}returndocument.getRootElement();

}/*** 得到该节点下的子节点集合

*@param:@paramelement

*@param:@return*@return: List

* @Autor: Han*/@SuppressWarnings("unchecked")public static ListgetElements(Element element) {returnelement.elements();

}/*** 得到该节点下指定的节点

*@param:@paramname

*@param:@return*@return: Element

* @Autor: Han*/

public staticElement getElement(Element element, String name) {

Element childElement=element.element(name);if(childElement == null) {

logger.error(element.getName()+ "节点下没有子节点" +name);return null;

}returnchildElement;

}/*** 得到该节点的内容

*@param:@paramelement

*@param:@return*@return: String

* @Autor: Han*/

public staticString getElementText(Element element) {returnelement.getText();

}

}

该项目需要用到的两个包:log4j,dom4j

其余配置文件和静态文件

log4j.properties

### \u8BBE\u7F6E###

log4j.rootLogger = debug,stdout,D,E

### \u8F93\u51FA\u4FE1\u606F\u5230\u63A7\u5236\u62AC ###

log4j.appender.stdout = org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target = System.out

log4j.appender.stdout.layout = org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### \u8F93\u51FADEBUG \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###

log4j.appender.D = org.apache.log4j.DailyRollingFileAppender

log4j.appender.D.File = E://logs/log.log

log4j.appender.D.Append = true

log4j.appender.D.Threshold = DEBUG

log4j.appender.D.layout = org.apache.log4j.PatternLayout

log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

### \u8F93\u51FAERROR \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###

log4j.appender.E = org.apache.log4j.DailyRollingFileAppender

log4j.appender.E.File =E://logs/error.log

log4j.appender.E.Append = true

log4j.appender.E.Threshold = ERROR

log4j.appender.E.layout = org.apache.log4j.PatternLayout

log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

server.xml

8089

Han`s Server

UTF-8

login.html

han登录
密码:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值