Apache Mina:一个简单的http的服务器并响应json数据的Demo

11 篇文章 0 订阅

当前版本:jdk1.8

1. 声明

当前内容主要为使用Apache Mina实现一个简单的http服务器,并完成默认json数据的响应,当前内容参考:apache mina源码

主要pom依赖

<dependency>
	<groupId>org.apache.mina</groupId>
	<artifactId>mina-core</artifactId>
	<version>2.1.5</version>
</dependency>
<dependency>
	<groupId>org.apache.mina</groupId>
	<artifactId>mina-http</artifactId>
	<version>2.1.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-transport-serial -->
<dependency>
	<groupId>org.apache.mina</groupId>
	<artifactId>mina-transport-serial</artifactId>
	<version>2.1.5</version>
</dependency>

2. Demo实现

一个简单的服务器Server

public class HttpServer {
	public static void main(String[] args) {

		IoAcceptor acceptor = new NioSocketAcceptor();
		LoggingFilter loggingFilter = new LoggingFilter();
		loggingFilter.setMessageReceivedLogLevel(LogLevel.DEBUG);
		acceptor.getFilterChain().addLast("log", loggingFilter);
		acceptor.getFilterChain().addLast("httpServerCodec", new HttpServerCodec());
		acceptor.setHandler(new HttpServerHandler());
		try {
			acceptor.bind(new InetSocketAddress("localhost", 8081));
			System.out.println("start http server....");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
}

httpServer对应的处理Handler

import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.http.DateUtil;
import org.apache.mina.http.api.DefaultHttpResponse;
import org.apache.mina.http.api.HttpEndOfContent;
import org.apache.mina.http.api.HttpMethod;
import org.apache.mina.http.api.HttpRequest;
import org.apache.mina.http.api.HttpStatus;
import org.apache.mina.http.api.HttpVersion;

public class HttpServerHandler extends IoHandlerAdapter {
	private static final CharsetEncoder ENCODER = StandardCharsets.UTF_8.newEncoder();

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		// TODO Auto-generated method stub
		super.sessionIdle(session, status);
		System.out.println("idle ==>" + status);
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		// TODO Auto-generated method stub
		super.exceptionCaught(session, cause);
		session.closeNow();
	}

	List<ByteBuffer> requestBody;

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub
		// super.messageSent(session, message);
		System.out.println("message sent");
	}

	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub
		// super.messageReceived(session, message);
		// 当前的message就是HttpRequest的实现类
		if (message == null) {
			return;
		}
		HttpRequest httpRequest = null;
		if (message instanceof HttpRequest) {
			httpRequest = (HttpRequest) message;
			// 获取请求路径
			String requestPath = httpRequest.getRequestPath();
			// 获取请求类型
			HttpMethod method = httpRequest.getMethod();
			// 获取请求参数
			String queryString = httpRequest.getQueryString();
			/*
			 * Map<String, String> headers = httpRequest.getHeaders();
			 * Iterator<Entry<String, String>> iterator = headers.entrySet().iterator();
			 * while (iterator.hasNext()) { Entry<String, String> next = iterator.next();
			 * System.out.println(next.getKey() + ":" + next.getValue()); }
			 */

			System.out.println("url:" + requestPath);
			System.out.println("method:" + method);
			System.out.println("queryString:" + queryString);
			System.out.println("httpRequest");
		} else if (message instanceof ByteBuffer) {
			// 接受post请求的消息体
			requestBody.add((ByteBuffer) message);
			System.out.println("byteBuffer");
		} else if (message instanceof HttpEndOfContent) {
			// we received all the post content, send the crap back
			sendResponse(session);
			System.out.println("httpEndOfContent");
		}

	}

	// 发送json结果到前台
	public void sendResponse(IoSession session) {
		System.out.println("send response....");
		// 写出默认响应
		writeDefaultResponse(session);
		String jsonResult = "{\"status\":\"ok\"}";
		// 写出body
		writeJsonBody(jsonResult, session);
		// 写出结束
		session.write(new HttpEndOfContent());
		session.close(false);

	}

	private Map<String, String> createHeaders() {
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Server", "Apache MINA Server");
		headers.put("Date", DateUtil.getCurrentAsString());
		headers.put("Connection", "keep-alive");
		headers.put("Content-Language", "zh-CN");
		headers.put("Content-Type", "application/json; charset=utf-8");
		return headers;
	}

	private void writeDefaultResponse(IoSession session) {
		Map<String, String> headers = createHeaders();
		DefaultHttpResponse defaultHttpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SUCCESS_OK,
				headers);
		session.write(defaultHttpResponse);
	}

	private void writeJsonBody(String json, IoSession session) {
		IoBuffer buf = IoBuffer.allocate(json.length()).setAutoExpand(true);
		try {
			buf.putString(json, ENCODER);
			buf.flip();
			session.write(buf);
		} catch (CharacterCodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

这里的HttpServerCodec具有解码和加码类
在这里插入图片描述

3. 测试结果

首先启动当前的server:该server默认在8081端口
在这里插入图片描述
访问当前的http://localhost:8081/login得到响应结果如下:
在这里插入图片描述
测试成功!

4. 主要易错的地方

在这里插入图片描述

这里主要出现的问题是如何响应http客户端的问题(找到Encoder即可解决问题),响应数据是要encoder的,server接受数据是decoder

由于是http请求所以可以定位到HttpServerEncoder

在这里插入图片描述

所以实际响应为(这个也对应请求中的部分):

  1. 首先发送httpResonse主要写出响应状态、http的版本、headers等并写出一个换行
  2. 如果有ByteBuffer就会写出(对应http响应中的body)
  3. 最后写出一个HttpEndOfContent表示http的响应内容结束

注意写出的数据必须使用IoBuffer 作为写出的body(直接使用ByteBuffer好像没有作用

IoBuffer buf = IoBuffer.allocate(json.length()).setAutoExpand(true);
buf.putString(json, ENCODER);
buf.flip();

自此一个完整的http请求响应就完成了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值