芜湖网站开发公司,优化网站的软件下载,网站备案拍照幕布,网页游戏排行榜前十知乎文章目录目标最终效果展示基本步骤1. 解析控制器类#xff1a;2. 解析处理函数#xff1a;3. 解析处理函数变量名#xff1a;4. 监听TCP连接#xff1a;5. 实现路由函数#xff1a;知识点总结目标
与SpringMvc定义Controller类似效果
最终效果展示
主类
package org.e…
文章目录目标最终效果展示基本步骤1. 解析控制器类2. 解析处理函数3. 解析处理函数变量名4. 监听TCP连接5. 实现路由函数知识点总结目标
与SpringMvc定义Controller类似效果
最终效果展示
主类
package org.example;import com.zcj.Accepter;
import com.zcj.annotation.SummerApplication;import java.io.IOException;//标注控制器类
SummerApplication(org.example.MainController)
public class App
{public static void main( String[] args ) throws IOException {Accepter accepter new Accepter();accepter.run(App.class);}
}
控制器类
package org.example;import com.zcj.annotation.Controller;
import com.zcj.annotation.Param;
import com.zcj.entity.Response;public class MainController {//标注处理的路径Controller(/hello)public Response hello(Param(name) String name){return new Response(200, Response.HTML, h1Hello, name /h1);}
}
浏览器访问
基本步骤
1. 解析控制器类
利用反射解析SummerApplication注解所包含的类获得该类中的处理函数
2. 解析处理函数
获取控制器类中包含Controller的方法建立处理函数映射表
3. 解析处理函数变量名
获取处理函数中包含Param的参数建立处理函数变量名表用于获取请求中的参数
/*** 解析控制器类中的处理函数* param clazz 控制器类的Class* throws ClassNotFoundException* throws IllegalAccessException* throws InstantiationException*/private void analysisController(Class clazz) throws ClassNotFoundException, IllegalAccessException, InstantiationException {System.out.println(解析控制器类.....);if (!clazz.isAnnotationPresent(SummerApplication.class)) {System.out.println(ERROR: 未指定控制器类);return;}SummerApplication summerApplication (SummerApplication) clazz.getAnnotation(SummerApplication.class);String classPack summerApplication.value();// Class.forName 可以得到Class对象并且如果这个类没有被加载过它将会初始化这个类。Class controllerClazz Class.forName(classPack);controllers (T) controllerClazz.newInstance();System.out.println(控制器类 controllerClazz);System.out.println(\n************************************************************************************************************************* \n* 路径\t\t|参数\t\t\t\t| 处理函数);//反射解析控制器类Method[] methods controllerClazz.getMethods();for (Method method : methods) {if (!method.isAnnotationPresent(Controller.class)) continue;Controller annotation method.getAnnotation(Controller.class);//将函数加入映射表controllerMap.put(annotation.value(), method);Parameter[] parameterList method.getParameters();ListString paramNameList null;if (parameterList.length 0) {//获取参数变量名paramNameList new ArrayList();for (Parameter param : parameterList) {//判断是否出现 Paramif (!param.isAnnotationPresent(Param.class)) continue;Param paramAnnotation param.getAnnotation(Param.class);paramNameList.add(paramAnnotation.value());}//处理函数变量名映射表paramNameMap.put(annotation.value(), paramNameList);}System.out.println(* annotation.value() | paramNameList | method);}System.out.println(*************************************************************************************************************************\n);System.out.println(解析控制器类完成);}4. 监听TCP连接
获取请求的方法POSTGET请求的路径请求参数等
/*** 启动连接监听* param clazz 启动类*/public void run(Class clazz) {//解析控制器类try {analysisController(clazz);} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {System.out.println(ERROR: 控制器类不存在, 请检查 SummerApplication 注解的类名);return;}//启动监听连接System.out.println(\n\n等待远程连接端口号为 serverSocket.getLocalPort() \n\n\n);while (true) {try {Socket client serverSocket.accept();synchronized (System.out) {System.out.println(\n连接的远程主机地址 client.getRemoteSocketAddress() \n\n);}executorService.submit(() - {//处理请求handlerRequest(client);});} catch (IOException ioException) {System.out.println(ioException);//关闭线程池executorService.shutdown();}}}请求解析函数
/*** 此函数用于解析请求并分配请求到相应的处理函数* param client 连接请求的Socket*/private void handlerRequest(Socket client) {try (InputStream input client.getInputStream()) {try (OutputStream output client.getOutputStream()) {try (PrintWriter writer new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) {try (BufferedReader reader new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {//请求头String requestHeader;int contentLength 0;//请求的类型String requestType null;//请求的路径String requestPath null;//请求参数String requestParams null;//参数类型String contentType null;while ((requestHeader reader.readLine()) ! null !requestHeader.isEmpty()) {synchronized (System.out) {System.out.println(requestHeader);}//获得请求的类型路径if (requestHeader.startsWith(POST) || requestHeader.startsWith(GET)) {String[] line requestHeader.split( );requestType line[0];int end line[1].indexOf(?);if (end -1) requestPath line[1];else requestPath line[1].substring(0, end);}//获得参数类型if (requestHeader.startsWith(Content-Type)) {String[] line requestHeader.split(: );contentType line[1];}//获得Get参数if (requestHeader.startsWith(GET)) {int begin requestHeader.indexOf(?) 1;if (begin 0) {requestParams ;} else {int end requestHeader.indexOf(HTTP/) - 1;//GET的参数requestParams requestHeader.substring(begin, end);}}//获取POST请求内容长度if (requestHeader.startsWith(Content-Length)) {int begin requestHeader.indexOf(Content-Lengh:) Content-Length:.length() 1;String postParamterLength requestHeader.substring(begin).trim();contentLength Integer.valueOf(postParamterLength);}}//获取POST请求参数字符串StringBuffer sb new StringBuffer();if (contentLength 0) {for (int i 0; i contentLength; i) {sb.append((char) reader.read());}requestParams sb.toString();}//将字符串转UTF-8requestParams URLDecoder.decode(requestParams, UTF-8);System.out.println(requestParams);synchronized (System.out) {System.out.println(请求类型: requestType);System.out.println(请求路径: requestPath);System.out.println(请求参数类型: contentType);System.out.println(请求参数: requestParams);}//发送回复Response resp null;if (requestType.equals(POST) !contentType.equals(application/x-www-form-urlencoded)) {//只接受 application/x-www-form-urlencoded 的参数resp new Response(400, Response.HTML, h1400h4POST请求的参数格式必须为 application/x-www-form-urlencoded/h4/h1);} else {//将请求分配到相应的处理函数resp dispatch(requestPath, requestParams);}writer.write(resp.toString());writer.flush();client.close();synchronized (System.out) {System.out.println(\n\nWARING: client.getRemoteSocketAddress() is disconnected.\n\n);}}}} catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {client.close();System.out.println(ERROR: 分配请求失败);e.printStackTrace();}} catch (IOException e) {try {client.close();} catch (IOException ignored) {}synchronized (System.out) {System.out.println(\n\nWARING: client.getRemoteSocketAddress() is disconnected.\n\n);}}}
5. 实现路由函数
利用处理函数变量名表获取参数并将参数转为处理函数所需类型利用处理函数映射表将请求转发到对应的处理函数返回结果
/*** param requestPath 请求的路径* param requestParams 请求的参数字符串* return Response http回复类* throws NoSuchMethodException* throws IllegalAccessException* throws InvocationTargetException* throws InstantiationException*/private Response dispatch(String requestPath, String requestParams) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Response resp null;if (!controllerMap.containsKey(requestPath)) {//处理函数不存在return new Response(404, Response.HTML, h1404h4请求的资源不存在/h4/h1);}//调用处理函数Method method controllerMap.get(requestPath);//获取方法的参数类型Class?[] paramterTypes method.getParameterTypes();if (paramterTypes.length 0) {//不需要参数//invoke()第一个参数为调用方法的实例return (Response) controllerMap.get(requestPath).invoke(controllers);}//检验参数//解析参数字符传LinkedHashMapString, String paramMap Params.toMap(requestParams);if (paramMap null) {//没有所需参数return new Response(400, Response.HTML, h1参数错误,请检查/h1);}//获得方法的参数变量名表ListString paramNameList paramNameMap.get(requestPath);//方法的参数Object[] params new Object[paramterTypes.length];for (int i 0; paramMap ! null i paramterTypes.length; i) {//参数的类型Class paramType paramterTypes[i];if (allowType.contains(paramType) !paramMap.containsKey(paramNameList.get(i))) {//参数缺漏return new Response(400, Response.HTML, h1 style\color:red;\参数错误 缺少 paramNameList.get(i) [ paramterTypes[i].getName() ]/h1);}//将String 转为 所需的类型只支持基本类型或自定义类不包括集合String param paramMap.get(paramNameList.get(i));//将基本类型转为包装类型if (paramType.equals(int.class)) {paramType Integer.class;} else if (paramType.equals(boolean.class)) {paramType Boolean.class;}if (paramType.equals(String.class)) {params[i] param;} else if (paramType.equals(Integer.class) || paramType.equals(Boolean.class)) {//将参数转为所需类型Object instance paramType.getConstructor(String.class).newInstance(param);params[i] instance;} else {//自定义类Object o Params.toObject(requestParams, paramType);params[i] o;}}//调用控制器return (Response) controllerMap.get(requestPath).invoke(controllers, params);}知识点总结
将字符串转UTF-8的方法
String utf8Str URLDecoder.decode(str, UTF-8);向反射获取的函数中传入任意数量且不同类型的参数的方法 前提知识JAVA中的引用类型都继承于Object通过向上转型可以用Object类型引用各种引用类型 第一步将基本类型转为包装类型 第二步将所有参数放入Object数组中 第三步调用相应的函数
//...转换步骤省略,可参照 基本步骤的5. dispatch函数
//len为参数的数量
Object[] parmas new Object[len]
//....放入参数到 params 数组
method.invoke(instance, params)