手写DispatcherServlet中央控制器,获取参数的名字parameter.getName(),获取的名字是arg0,arg1,arg2....导致接收不到前端传过来的token,登录已过期。

            手写DispatcherServlet中央控制器,获取参数的名字parameter.getName(),获取的名字是arg0,arg1,arg2......,导致接收不到前端传过来的token。登录的时候一直显示登录已过期,当时不知道是没有接收到token,一直认为是中央控制器的代码问题,写这篇博客,想记录这个时刻,自己成长的过程,自己解决的问题会让自己明白这个过程的经过,分析代码的经过,debug无数次,最终找到问题所在,也是这次经历,让我明白debug的重要性,分析代码的利器,好,下面开始总结怎么解决这个问题。

1、第一个解决思路

是在idea设置中配置-parameters,但是很不幸,我的问题没有得到解决,因为我第一次就是这么配置的,所以我在检查代码的时候,一直认为和这个参数的名字arg0没有关系,当时觉的应该不是因为这个,其实问题还是因为参数的名字的影响,只不过这个配置对于我的代码没有效果,哈哈哈哈。

2、第二个解决思路 

因为我当时在Maven环境下总结这些知识的,所以可以在pom.xml文件中,配置这个-parameters,在pom.xml中配置build,配置完这个我的问题才得以解决,第一个解决思路,对于我的代码没有效果。

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <source>17</source>
          <target>17</target>
          <compilerArgs>
            <arg>-parameters</arg>
          </compilerArgs>
        </configuration>
      </plugin>
    </plugins>
  </build>

3、第三个解决思路 

如果您使用的是Gradle,则可以在build.gradle文件中添加以下配置:

compileJava {
    options.compilerArgs += "-parameters"
}

4、第四个解决思路 

如果您使用的是命令行编译器,则可以使用以下命令:

javac -parameters MyClass.java

请注意,这个选项仅适用于方法参数,而不适用于局部变量或字段名称。如果您需要获取局部变量或字段名称,可以使用Java字节码库,如ASM或ByteBuddy 

parameter.getName()获取到的参数名字为形参的名称,如果没有指定形参名称,则默认为arg0arg1arg2等。要解决这个问题,有以下几种方法:

  1. 在接口方法中指定参数名称

可以使用@WebParam(name = "paramName")注解在接口方法中指定参数名称,例如:

@WebMethod
int add(@WebParam(name = "a") int num1, @WebParam(name = "b") int num2);

这样在调用parameter.getName()时,就会返回指定的参数名称。

  1. 使用反射获取方法参数名

通过使用Java 8引入的反射API中的Parameter.getName()方法获取参数名称。需要使用Java 8或更高版本,并且需要在编译时开启-parameters选项,例如:

javac -parameters MyClass.java

然后使用反射获取参数名称,例如:

Method method = MyClass.class.getMethod("add", int.class, int.class);
Parameter[] parameters = method.getParameters();
String paramName = parameters[0].getName(); // 获取第一个参数的名称

  1. 使用第三方库

可以使用一些第三方库来获取方法参数名,例如Spring Framework中的org.springframework.core.LocalVariableTableParameterNameDiscoverer类,或者Google Guava库中的com.google.common.reflect.Parameter类。这些库可以在运行时获取方法参数名称,并且不需要在编译时开启-parameters选项。

一般来说,如果 parameter.getName() 返回的参数名为 arg0arg1 等,是因为编译器不知道参数的具体名称,因此它们被命名为 arg0arg1 等。这个问题可以通过在编译时使用 -parameters 选项来解决。这个选项会告诉编译器在编译时保留参数名称,而不是将它们命名为 arg0arg1 等。例如,使用 javac -parameters MyClass.java,其中 MyClass.java 是包含您的类和方法的源代码文件。

如果您无法在编译时使用 -parameters 选项,您可以尝试使用反射来获取参数名称。使用反射需要用到 Java 8 引入的 Parameter.getName() 方法。如果您的运行时环境是 Java 8 之前的版本,您可以使用第三方库,如 Javassist 或 ASM 来实现相同的功能。需要注意的是,使用反射或第三方库来获取参数名称可能会导致性能问题,并且可能会造成代码可读性和维护性问题。

您可以尝试使用getParameterTypes()方法来获取参数类型,然后根据类型来确定参数名。例如:

Method method = ... // 获取方法对象
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
    Parameter parameter = parameters[i];
    String parameterName = parameter.getName();
    if (parameter.getType() == int.class) {
        parameterName = "intValue";
    } else if (parameter.getType() == String.class) {
        parameterName = "stringValue";
    }
    System.out.println("Parameter " + i + " name: " + parameterName);
}

在这个例子中,我们通过判断参数类型来确定参数名。当然,你也可以使用其他规则来确定参数名。

在使用getParameter方法获取参数名时,若参数名未指定,则会默认赋值为arg0arg1arg2...等,可以通过以下两种方式解决:

  1. 指定参数名

在接口定义时,需要指定每个参数的名称,例如:

public interface UserService {
    void addUser(@RequestParam("name") String name, @RequestParam("age") int age);
}

这样,在调用getParameter方法时,就可以得到具体的参数名。

  1. 使用Spring AOP

使用Spring AOP可以实现方法级别的拦截,可以在方法调用前获取方法参数,并通过ParameterNameDiscoverer获取参数名,例如:

@Component
@Aspect
public class LogAspect {
    @Autowired
    private ParameterNameDiscoverer parameterNameDiscoverer;

    @Before("execution(* com.example.UserService.addUser(..))")
    public void beforeAddUser(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
        Object[] args = joinPoint.getArgs();

        for (int i = 0; i < args.length; i++) {
            System.out.println(parameterNames[i] + " = " + args[i]);
        }
    }
}

这样,在调用addUser方法时,就可以通过AOP拦截,在方法调用前获取参数名。

参数名称为arg0、arg1等是因为Java默认使用参数名称来引用参数。如果没有在编译时使用特定的标志,则编译器会将参数名称设置为arg0,arg1等。解决此问题的方法之一是在编译时使用 -parameters 标志。这将告诉编译器将参数名称编译到字节码中。例如,在使用Maven构建项目时,可以在pom.xml文件中添加以下插件配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <compilerArgs>
                    <arg>-parameters</arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

这将强制编译器将参数名称编译到字节码中,从而可以在运行时访问它们。

如果您使用的是JAX-WS或JAX-RPC等旧的Web服务框架,则可能会遇到此问题。这是由于这些框架使用参数的位置而不是参数的名称来识别参数。

要解决此问题,您可以使用更现代的Web服务框架,例如JAX-RS或Spring Web Services,它们支持使用参数名称而不是位置来识别参数。您还可以尝试使用一些库(例如Apache Axis)来启用参数名称支持。

如果您无法更改Web服务框架或使用库,则可以通过在Web服务方法上添加注释来手动指定参数名称。例如,在JAX-WS中,您可以使用@WebParam注释来指定参数名称,如下所示:

public String myWebServiceMethod(@WebParam(name = "myParameter") String myParameter) {
    // ...
}

这将使参数名称为“myParameter”,而不是默认名称“arg0”。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值