从另一个包调用的函数无法访问参数。

huangapple go评论72阅读模式
英文:

Function called from another package cannot access to parameters

问题

以下是翻译好的内容:

这是我的问题:

我有两个类:类A包含一些@Value("${param.username}")@Value("${param.password}"),我有一个使用这两个参数的函数,我使用@GetMapping(path = "/functionA")来运行函数A(这个函数是向服务器发出的用于认证的Post请求)

用户名和密码存储在application-contextual-values.properties中。

当我在浏览器上运行localhost:8080/app/functionA时,它可以工作!

我有另一个类B,在另一个包B中,我想调用第一个类A并使用functionA进行认证。但是,我遇到了一个错误:Username must not be null(用户名不能为空)。

这意味着我无法获取存储在application-contextual-values文件中的用户名和密码。

这是类A的代码:

public class A {

    @Value("${param.username}")
    private String username;

    @Value("${param.password}")
    private String password;

    @GetMapping(path = "functionA")
    public AuthentificationModel getClient() {
        HttpHeaders headers = new HttpHeaders();
        headers.setBasicAuth(this.username, this.password);
        String jwt = getJWT(); // 这个函数也在类A中
            
        // ... 这里构造参数,以便进行POST请求
            
        return token;
    }
}

AuthentificationModel只是在POST请求之后返回的内容(access_token、client_id、token_type)。

我的类B是:

import fr.ag2rlamondiale.ytb.rest.A; // 类A

public class B {
 
    private static Map<String, String> getRequestHeader() {
 
        Map<String, String> requestHeaders = new HashMap<>();
        try {
            final A objA = new A(); // 在这里创建了类A的实例
            String token = objA.getClient().getAccessToken(); // getClient()是类A中返回token的函数

            requestHeaders.put("Authorization", "Bearer " + token); 
                 

            // ... 其他添加头部的操作
        } catch (CommonException e) {
            e.printStackTrace();
        }
        return requestHeaders;
    }
}

我的application-contextual-values.properties

param.username="kljkjsdf555sdf"
param.password="xxx222xxx"

是因为我需要在类A中添加带有用户名和密码参数的构造函数吗?在我的情况下,使其正常工作的正确方法是什么?

编辑:

在类A中我添加了:@Controller

在类B中:我添加了@Autowired A objA,并去掉了new A();

但是现在,出现了一个新错误:Cannot make a static reference to the non-static field objA(无法在静态上下文中引用非静态字段objA)

这意味着类A中的元素是非静态的,而我在静态对象objA中使用了它?

英文:

Here is my problem :

I'm having two classes: class A contains some @Value(&quot;${param.username}&quot;) and @Value(&quot;${param.password}&quot;), I have a function using those 2 params, and I a use @GetMapping(path = &quot;/functionA&quot;) to run the functionA (this function is a Post request to a server to authentificate)

Username and password are on application-contextual-values.properties

When I run on browser localhost:8080/app/functionA => it works !

I have another class B, on another package B, I want to call the first class A and use the fuctionA to authentificate. => I'm having an error : Username must not be null

It means that I cannot get username and password that are stored in application-contextual-values file.

Here is my code of class A :

public class A {

    @Value(&quot;${param.username}&quot;)
    private String username;

    @Value(&quot;${param.password}&quot;)
    private String password;

    @GetMapping(path = &quot;functionA&quot;)
    public AuthentificationModel getClient() {
        HttpHeaders headers = new HttpHeaders();
        headers.setBasicAuth(this.username, this.password);
        String jwt = getJWT(); &lt;======  this function is also in this class A
        
        ...
     
        I&#39;m doing a construction of params, to send on POST 

        return token;
     }

The AuthentificationModel is just what is sent back after the POST request (access_token, client_id, token_type)

My class B is :

import fr.ag2rlamondiale.ytb.rest.A; &lt;==== class A

public class B {

   private static Map&lt;String, String&gt; getRequestHeader() {

       Map&lt;String, String&gt; requestHeaders = new HashMap&lt;&gt;();
       try{
         final A objA = new A(); &lt;===== instance of my class A here
           String token = objA.getClient().getAccessToken(); &lt;==== getClient() is the funct that returns token on class A

           requestHeaders.put(&quot;Authorization&quot;, &quot;Bearer &quot;, + token); 
             
           ... many other put for header
         } catch (CommonException e) {
		e.printStackTrace();
	}
	return requestHeaders;
}

My application-contextual-values.properties :

param.username=&quot;kljkjsdf555sdf&quot;
param.password=&quot;xxx222xxx&quot;

Is it because I'll need to add constructor on class A with params username and password ? what is the proper way to make it work in my context ?

Edit :

In class A I added : @Controller

In class B : I added @Authowired A objA and no new A();

But now, having a new error : Cannot make a static reference to the non-static field objA

Meaning that elements on class A are non-static and I'm using objA as a static object ?

答案1

得分: 0

使用依赖注入和 @Autowired 在 B 中注入您的 A 实例,不要在您的 B 类中创建 A 的新实例。

英文:

Use Dependency injection and @Autowired Your A instance in B and don't create new Instance of A in your B class.

答案2

得分: 0

Spring只能处理它管理的对象(即创建的对象),包括当然也包括使用@Value注解注释的数据的解析/注入。

当您自己从类B创建类A的实例时:

final A objA = new A();

Spring不知道必须处理这个类,实际上它甚至不知道这个类的存在,因此“value”没有被注入/设置。

通常来说,要解决这个问题,您需要重构您的代码。
目前不清楚您为什么要创建Controller类(我猜测A是一个Controller,因为它的getClient方法被@GetMapping注解标注,而这只在Controller中有意义)。

然而,您不必创建A的实例,而是注入它,并确保AB都由Spring管理。

英文:

Spring can process only the objects that it manages (read creates), including resolution / injection of data annotated with @Value of course.

When you create the instance of class A by yourself from class B:

final A objA = new A();

Spring has no idea that this class must be processed, in fact it doesn't even know that this class exists, hence the "value" in not injected/set.

In general to solve this, you need to refactor your code.
Its not clear why do you create the class of Controller (I assume that A is a controller because it's method getClient is annotated with @GetMapping which makes sense only in controllers).

However, you don't have to create an instance of A, but rather inject it and make sure that both A and B are managed by Spring

答案3

得分: 0

由于您在类B中使用A objA = new A()来创建A类的实例,Spring不会在类A中注入任何值,因为它是一个新对象。要在类A中使用属性注入,您需要使用依赖注入,并使用已经在Spring应用程序上下文中实例化的A类的bean。

我假设A类带有@Controller注解。

@Controller
public class A {

并且在类B中像下面这样使用自动装配来注入A类的实例:

public class B {

    @Autowired
    A objA;

    private static Map<String, String> getRequestHeader() {
    
        Map<String, String> requestHeaders = new HashMap<>();
        try{
            //final A objA = new A(); <===== 在此处实例化了我的A类的实例
            String token = objA.getClient().getAccessToken(); //<==== getClient()是在类A中返回令牌的函数
英文:

Since you are creating instance of A using A objA = new A() in class B, spring does not inject any value in class A as it is new object. To use property injection in class A, you need to use dependency injection and use bean of A already instantiated using spring application context.

I assume Class A is annotated with @Controller.

@Controller
public class A {

and use autowiring in class B like below to inject instance of A

public class B {

   @Autowired
   A objA;

   private static Map&lt;String, String&gt; getRequestHeader() {

       Map&lt;String, String&gt; requestHeaders = new HashMap&lt;&gt;();
       try{
         //final A objA = new A(); &lt;===== instance of my class A here
           String token = objA.getClient().getAccessToken(); &lt;==== getClient() is the funct that returns token on class A

huangapple
  • 本文由 发表于 2020年10月14日 16:46:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/64349702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定