• 微头条项目实战:新增RequestHeader注解


    1、RequestHeader

    1. package com.csdn.mymvc.annotation;
    2. import java.lang.annotation.*;
    3. @Target(ElementType.PARAMETER)
    4. @Retention(RetentionPolicy.RUNTIME)
    5. @Inherited
    6. public @interface RequestHeader {
    7. }

    2、DispatcherServlet

    1. package com.csdn.mymvc.core;
    2. import com.csdn.mymvc.annotation.RequestBody;
    3. import com.csdn.mymvc.annotation.RequestHeader;
    4. import com.csdn.mymvc.util.RequestUtil;
    5. import com.csdn.mymvc.util.ResponseUtil;
    6. import jakarta.servlet.RequestDispatcher;
    7. import jakarta.servlet.ServletContext;
    8. import jakarta.servlet.ServletException;
    9. import jakarta.servlet.annotation.WebServlet;
    10. import jakarta.servlet.http.HttpServlet;
    11. import jakarta.servlet.http.HttpServletRequest;
    12. import jakarta.servlet.http.HttpServletResponse;
    13. import com.csdn.headline.common.Result;
    14. import java.io.IOException;
    15. import java.lang.annotation.Annotation;
    16. import java.lang.reflect.InvocationTargetException;
    17. import java.lang.reflect.Method;
    18. import java.lang.reflect.Parameter;
    19. import java.util.Arrays;
    20. import java.util.Map;
    21. @WebServlet("/*")
    22. public class DispatcherServlet extends HttpServlet {
    23. private final String BEAN_FACTORY = "beanFactory" ;
    24. private final String CONTROLLER_BEAN_MAP = "controllerBeanMap" ;
    25. @Override
    26. protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    27. String[] staticResourceSuffixes={".html",".jsp",".jpg",".png",".gif",".css",".js",".ico"};
    28. //index.html
    29. String uri = request.getRequestURI();
    30. if(Arrays.stream(staticResourceSuffixes).anyMatch(uri::endsWith)){
    31. RequestDispatcher defaultDispatcher = request.getServletContext().getNamedDispatcher("default");
    32. defaultDispatcher.forward(request,response);
    33. }else{
    34. // uri: /fruit/index
    35. String[] arr = uri.split("/") ;
    36. if(arr==null || arr.length!=3){
    37. throw new RuntimeException(uri+"非法!");
    38. }
    39. // [, fruit, index]
    40. String requestMapping = "/"+arr[1] ; // /fruit
    41. String methodMapping = "/"+arr[2]; // /index
    42. ServletContext application = getServletContext();
    43. ControllerDefinition controllerDefinition = ((Map)application.getAttribute(CONTROLLER_BEAN_MAP)).get(requestMapping);
    44. if(controllerDefinition==null){
    45. throw new RuntimeException(requestMapping+"对应的controller组件不存在!");
    46. }
    47. //获取请求方式,例如:get或者post
    48. String requestMethodStr = request.getMethod().toLowerCase();
    49. //get_/index
    50. Method method = controllerDefinition.getMethodMappingMap().get(requestMethodStr+"_"+methodMapping) ;
    51. Object controllerBean = controllerDefinition.getControllerBean();
    52. try {
    53. //第1步:参数处理
    54. //获取method方法上的参数
    55. Parameter[] parameters = method.getParameters();
    56. Object[] parameterValues = new Object[parameters.length];
    57. for(int i = 0 ; i< parameters.length;i++){
    58. Parameter parameter = parameters[i];
    59. //获取参数名称
    60. //JDK8之前,通过反射获取到参数对象(Parameter对象)
    61. //然后通过parameter.getName()方法是得不到形参的名称的,返回的是arg0,arg1,arg2....
    62. //JDK8开始,反射技术得到的Class中可以包含方法形参的名称,不过需要做一个额外的设置:java compiler 中添加一个参数:-parameters
    63. String paramName = parameter.getName();
    64. Object parameterValue = null ;
    65. //获取当前这个参数上的所有注解
    66. Annotation[] annotations = parameter.getDeclaredAnnotations();
    67. if (Arrays.stream(annotations).anyMatch(annotation -> annotation instanceof RequestBody)) {
    68. parameterValue = RequestUtil.readObject(request,parameter.getType());
    69. } else if (Arrays.stream(annotations).anyMatch(annotation -> annotation instanceof RequestHeader)) {
    70. parameterValue = request.getHeader(paramName);
    71. } else{
    72. String paramValueStr = request.getParameter(paramName);
    73. if(paramValueStr!=null){
    74. //获取参数的类型,例如: java.lang.Integer,java.lang.String
    75. String parameterTypeName = parameter.getType().getName();
    76. parameterValue = switch (parameterTypeName){
    77. case "java.lang.String"->paramValueStr;
    78. case "java.lang.Integer"->Integer.parseInt(paramValueStr);
    79. default -> null;
    80. };
    81. }
    82. }
    83. parameterValues[i]=parameterValue;
    84. }
    85. //第2步:方法调用
    86. //调用controllerBean对象中的method方法
    87. method.setAccessible(true);
    88. //第3步:结果集处理
    89. Object returnObj = method.invoke(controllerBean,parameterValues);
    90. if(returnObj!=null && returnObj instanceof Result){
    91. Result result = (Result) returnObj ;
    92. ResponseUtil.print(response,result);
    93. }
    94. } catch (IllegalAccessException e) {
    95. e.printStackTrace();
    96. throw new RuntimeException(e);
    97. } catch (InvocationTargetException e) {
    98. e.printStackTrace();
    99. throw new RuntimeException(e);
    100. }
    101. }
    102. }
    103. }

  • 相关阅读:
    Canvas 获取文本宽度使用ctx.measureText
    广义表基础知识
    Servlet小项目 | 基于纯Servlet手写一个单表的CRUD操作
    猿创征文|Linux 好用工具,助你事半功倍
    【线程池】面试被问到线程池参数如何配置时该如何回答
    数字孪生技术在智慧城市应用的推进建议
    一起看 I/O | 用 Health Connect 连通应用间的健康数据
    深度学习推荐系统(八)AFM模型及其在Criteo数据集上的应用
    手机地磁传感器与常见问题
    8中间件-Redis、MQ---基本
  • 原文地址:https://blog.csdn.net/m0_65152767/article/details/134335244