实际开发中我们经常遇到接口开发,最近遇到比较老的项目,采用的是java内置的HttpServer类实现的Restful服务。
HttpServer是JDK1.6以后内置的HTTP服务器,位置在rt.jar的com.sun.net.httpserver包下。
支持http和https协议。
主要用到HttpServer类 ,Handler接口实现类,以及HttpExchange类。我们用HttpServer调用Handler接口实现类,通过HttpExchange接受请求信息,并处理返回信息。
1.HttpServer:表示一个服务器实例,需要绑定一个IP地址和端口号。(HttpsServer是其子类,处理https请求)
// 重新绑定地址和端口
void bind(InetSocketAddress addr, int backlog)
// 获取当前绑定的地址
InetSocketAddress getAddress()
/**
* 创建监听的上下文, 请求 URI 根路径的匹配, 根据不同的 URI 根路径选择不同的 HttpHandler 处理请求,
* 路径必须以 "/" 开头。路径 "/" 表示匹配所有的请求 URI(没有其他更具体的匹配路径除外)。
*/
HttpContext createContext(String path)
HttpContext createContext(String path, HttpHandler handler)
// 移除上下文监听
void removeContext(HttpContext context)
void removeContext(String path)
// 设置请求的线程执行器, 设置为 null 表示使用默认的执行器
void setExecutor(Executor executor)
Executor getExecutor()
// 启动服务
void start()
// 最长等待指定时间后停止服务
void stop(int delay)
2.HttpContext:服务器监听器的上下文,需要配置用于匹配URI的公共路径和用来处理请求的HttpHandler
(可以创建多个 HttpContext,一个 HttpContext 对应一个 HttpHandler,不同的 URI 请求,根据添加的 HttpContext 监听器,分配到对应的 HttpHandler 处理请求)
3.HttpHandler:上下文对应的http请求处理器
4.HttpExchange:监听器回调时传入的参数,封装了http请求和响应的所有数据操作
// 获取请求的 URI, 请求链接除去协议和域名端口后的部分, 如: http://www.abc.com/aa/bb, URI 为 /aa/bb
URI getRequestURI()
// 获取请求客户端的 IP 地址
InetSocketAddress getRemoteAddress()
// 获取请求协议, 例如: HTTP/1.1
String getProtocol()
// 获取请求的方法, "GET", "POST" 等
String getRequestMethod()
// 获取所有的请求头
Headers getRequestHeaders()
// 以输入流的方式获取请求内容
InputStream getRequestBody()
// 获取响应头的 Map, 要添加头, 获取到 headers 后调用 add(key, value) 方法添加
Headers getResponseHeaders()
// 发送响应头, 并指定 响应code 和 响应内容的长度
void sendResponseHeaders(int rCode, long responseLength)
// 获取响应内容的输出流, 响应内容写到该流
OutputStream getResponseBody()
// 关闭处理器, 同时将关闭请求和响应的输入输出流(如果还没关闭)
void close()
// 获取此请求对应的上下文对象
HttpContext getHttpContext()
// 获取收到请求的本地地址
InetSocketAddress getLocalAddress()
由于Httpserver类是eclipse默认是进行禁用的状态。所以写程序时会报错。我们可以通过两种方式处理解决这个问题:
1.将jre移除项目再重新导入
右键此处,build path -》remove from build path 然后在导入到项目中,右键build path-》configure
2.
项目右键->properties->java builder path->Libraries标签,点击JRE System Library里面的Access rules项中添加 accessible为com/sun/net/httpserver/*** 保存退出。
实现代码如下:
1.创建HtttpServer 主程序
package com.test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.HttpServer;
public class ThreadHttpServer {
//启动端口8080
private static final int port=8880;
private static final String Httpcontext="/demo";
private static final int nThreads=8;
public static void main(String[] args) {
HttpServer httpServer;
try {
httpServer=HttpServer.create(new InetSocketAddress(port),0);
httpServer.createContext(Httpcontext,new HttpHandlerDemo() );
// 设置并发数
ExecutorService executor=Executors.newFixedThreadPool(nThreads);
httpServer.setExecutor(executor);
httpServer.start();
System.out.println("启动端口:"+port);
System.out.println("根节点:"+Httpcontext);
System.out.println("并发数:"+nThreads);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.实现HttpHandler接口
package com.test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URI;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
public class HttpHandlerDemo implements HttpHandler{
@Override
public void handle(HttpExchange httpExchange) throws IOException {
//请求地址
InetSocketAddress inetSocketAddress=httpExchange.getRemoteAddress();
System.out.println("请求ip地址:"+inetSocketAddress);
System.out.println("请求host:"+inetSocketAddress.getHostName());
System.out.println("请求port:"+inetSocketAddress.getPort());
//请求方式
String requestMethod=httpExchange.getRequestMethod();
System.out.println("请求方式:"+httpExchange.getRequestMethod());
//url
URI url=httpExchange.getRequestURI();
System.out.println("url:"+url);
if(requestMethod.equalsIgnoreCase("GET")){//客户端的请求是get方法
//设置服务端响应的编码格式,否则在客户端收到的可能是乱码
Headers responseHeaders = httpExchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/html;charset=utf-8");
//在这里通过httpExchange获取客户端发送过来的消息
//URI url = httpExchange.getRequestURI();
//InputStream requestBody = httpExchange.getRequestBody();
String response = "this is server";
httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.getBytes("UTF-8").length);
OutputStream responseBody = httpExchange.getResponseBody();
OutputStreamWriter writer = new OutputStreamWriter(responseBody, "UTF-8");
writer.write(response);
writer.close();
responseBody.close();
}
else {
//请求报文
InputStream inputStream=httpExchange.getRequestBody();
ByteArrayOutputStream bas=new ByteArrayOutputStream();
int i;
while((i=inputStream.read())!=-1) {
bas.write(i);
}
String requestmsg=bas.toString();
System.out.println("请求报文:"+requestmsg);
//返回报文
String resmsg="恭喜你成功了!";
httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK,resmsg.getBytes("UTF-8").length );
OutputStream outputStream=httpExchange.getResponseBody();
outputStream.write(resmsg.getBytes("UTF-8"));
outputStream.close();
System.out.println("通讯结束!");
}
}
}
3.启动主程序,然后调用就可以看见返回结果了。客户端可以自己写,也可以直接访问网页。
客户端代码如下:
package com.test.HttpClient;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Hello world!
*
*/
public class HttpClientApp
{
private static final Logger logger = LoggerFactory.getLogger(HttpClientApp.class);
public static void main( String[] args )
{
String url="http://127.0.0.1:8880/demo";
String reqStr="httpserver测试练习";
String contentType="application/json";
String charset="UTF-8";
String ss=doPost( url, reqStr, contentType, charset) ;
System.out.println("返回内容为:" +ss);
}
/**
* 执行一个HTTP POST请求,返回请求响应的HTML
*
* @param url 请求的URL地址
* @param reqStr 请求的查询参数,可以为null
* @param charset 字符集
* @return 返回请求响应的HTML
*/
public static String doPost(String url, String reqStr, String contentType, String charset) {
System.out.println("发送报文:"+reqStr);
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
try {
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
managerParams.setConnectionTimeout(30000); // 设置连接超时时间(单位毫秒)
managerParams.setSoTimeout(30000); // 设置读数据超时时间(单位毫秒)
method.setRequestEntity(new StringRequestEntity(reqStr, contentType, "utf-8"));
client.executeMethod(method);
System.out.println("返回的状态码为:" +method.getStatusCode());
if (method.getStatusCode() == HttpStatus.SC_OK) {
// return StreamUtils.copyToString(method.getResponseBodyAsStream(),Charset.forName(charset));
String resultStr= IOUtils.toString(method.getResponseBodyAsStream(),"utf-8");
System.out.println("resultStr:"+resultStr);
// return new String(resultStr.getBytes("ISO-8859-1"),"UTF-8");
return resultStr;
}
} catch (UnsupportedEncodingException e1) {
logger.error(e1.getMessage());
return "";
} catch (IOException e) {
logger.error("执行HTTP Post请求" + url + "时,发生异常!" + e.toString());
return "";
} finally {
method.releaseConnection();
}
return null;
}
/**
* 执行一个HTTP POST请求,返回请求响应的HTML
*
* @param url 请求的URL地址
* @param reqStr 请求的查询参数,可以为null
* @param charset 字符集
* @return 返回请求响应的HTML
*/
public static String doPostMuStr(String url, Part[] reqStr) {
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
try {
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
managerParams.setConnectionTimeout(30000); // 设置连接超时时间(单位毫秒)
managerParams.setSoTimeout(30000); // 设置读数据超时时间(单位毫秒)
// method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
method.setRequestEntity(new MultipartRequestEntity(reqStr, method.getParams()));
// method.setContentChunked(true);
client.executeMethod(method);
System.out.println("返回的状态码为:" +method.getStatusCode());
if (method.getStatusCode() == HttpStatus.SC_OK) {
return IOUtils.toString(method.getResponseBodyAsStream(),"utf-8");
}
} catch (UnsupportedEncodingException e1) {
logger.error(e1.getMessage());
return "";
} catch (IOException e) {
logger.error("执行HTTP Post请求" + url + "时,发生异常!" + e.toString());
return "";
} finally {
method.releaseConnection();
}
return null;
}
}
结果如下:
访问网页地址: