首先定义一个注解类,用这个注解类来注解后面要写的servlet类,以便于获取所有的servlet
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Servlet {
/**
* url值
*
* @return
*/
String value();
}
在初始化netty服务端的时候将所有的被servlet注解的类存起来
import org.reflections.Reflections;
// https://mvnrepository.com/artifact/org.reflections/reflections
// compile group: 'org.reflections', name: 'reflections', version: '0.9.11'
/**
* 获取指定包下被注解的类
*
* @param packageName 包全名,如果有多个用","隔开
* @param clasz 注解类class
* @return 包下所有被clasz注解的类
*/
@SuppressWarnings("unchecked")
private Set<Class<?>> getRequestMappingMethod(String packageName, Class clasz) {
String[] pname = packageName.split(",");
Set<Class<?>> classesList = new LinkedHashSet<>();//所有标注了指定注解的class
Reflections reflections;
for (int i = 0; i < pname.length; i++) {
reflections = new Reflections(packageName);
classesList.addAll(reflections.getTypesAnnotatedWith(clasz));
}
return classesList;
}
/**
* 获取被UrlAddress注释的类集合,保存url和具体的servlet类
*
* @param packageName 包全名,如果有多个用","隔开
* @return urlValue ,ObjectServlet
*/
public Map<String, ObjectServlet> getUrlAddressMap(String packageName) {
Set<Class<?>> classesList = getRequestMappingMethod(packageName, Servlet.class);
if (classesList.isEmpty())
return null;
Map<String, ObjectServlet> list = new HashMap<>();
classesList.forEach((clasz) -> {
String value = ((Servlet) clasz.getAnnotation(Servlet.class)).value();
logger.info("load servlet uri {}", value);
try {
list.put(value, (ObjectServlet) clasz.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
});
return list;
}
定义一个servlet处理类,以后每个servlet都继承它。
public class ObjectServlet {
/**
* 处理get方法
*
* @param request
* @param ctx
*/
protected void doGet(HttpRequest request, ChannelHandlerContext ctx) {
sendNotFound(ctx);
}
/**
* 处理post方法,默认找不到
* 如需另外实现请覆盖此方法,且不要调用super
*
* @param request
* @param ctx
*/
protected void doPost(HttpRequest request, ChannelHandlerContext ctx) {
sendNotFound(ctx);
}
/**
* 处理put方法,默认找不到
* 如需另外实现请覆盖此方法,且不要调用super
*
* @param request
* @param ctx
*/
protected void doPut(HttpRequest request, ChannelHandlerContext ctx) {
sendNotFound(ctx);
}
/**
* 处理delete方法,默认找不到
* 如需另外实现请覆盖此方法,且不要调用super
*
* @param request
* @param ctx
*/
protected void doDelete(HttpRequest request, ChannelHandlerContext ctx) {
sendNotFound(ctx);
}
/**
* 根据不同http请求处理不同类型请求
*
* @param request
* @param ctx
*/
public void process(HttpRequest request, ChannelHandlerContext ctx) throws Exception {
//http方法类型
HttpMethod method = request.method();
if (method == HttpMethod.GET)
doGet(request, ctx);
else if (method == HttpMethod.POST)
doPost(request, ctx);
else if (method == HttpMethod.PUT)
doPut(request, ctx);
else if (method == HttpMethod.DELETE)
doDelete(request, ctx);
}
}
比如一个新的servlet
@Servlet("/oop/v1/std/del")
public class Del extends ObjectServlet {
然后在handler里来使用这些地址和servlet
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (!(msg instanceof HttpRequest))
return;
HttpRequest httpRequest = (HttpRequest) msg;
String uri = httpRequest.uri();
//uri = test?a=3&b=4 ==> uri = /test
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri);
uri = queryStringDecoder.path();
//根据请求uri获取处理请求的类
Map<String, ObjectServlet> urlAddressMap = ServletManneger.getUrlAddressMap();
//处理请求
if (urlAddressMap.containsKey(uri)) {
ObjectServlet servlet = urlAddressMap.get(uri);
servlet.process(httpRequest, ctx);
ReferenceCountUtil.release(msg);//释放msg,没有往下走的话这个msg需要自己释放
return;
}
//没有的话..
ResponceErrorUtils.sendNotFound(ctx);//没有对应的uri返回404
//释放msg
ReferenceCountUtil.release(msg);//释放msg
}
附上几个获取参数的工具
/**
* 获取地址栏参数
*
* @param req
* @return
*/
protected Map<String, String> getUriParams(HttpRequest req) {
Map<String, String> requestParams = new HashMap<>();
// 处理get请求
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(req.uri());
Map<String, List<String>> parame = queryStringDecoder.parameters();
Iterator<Map.Entry<String, List<String>>> iterator = parame.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<String>> next = iterator.next();
requestParams.put(next.getKey(), next.getValue().get(0));
}
return requestParams;
}
/**
* 获取body里参数
*
* @param req
* @return
*/
protected Map<String, String> getBodyParams(HttpRequest req) {
Map<String, String> requestParams = new HashMap<>();
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(
new DefaultHttpDataFactory(false), req);
List<InterfaceHttpData> postData = decoder.getBodyHttpDatas(); //
for (InterfaceHttpData data : postData) {
if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
MemoryAttribute attribute = (MemoryAttribute) data;
requestParams.put(attribute.getName(), attribute.getValue());
}
}
return requestParams;
}
/**
* 获取body里的数据并转成json
*
* @param request
* @return
*/
protected JsonObject getJsonBody(HttpRequest request) {
FullHttpRequest req = (FullHttpRequest) request;
ByteBuf content = req.content();
byte[] contentBytes = new byte[content.readableBytes()];
content.readBytes(contentBytes);
String string = new String(contentBytes);
return new JsonParser().parse(string).getAsJsonObject();
}