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

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

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的代码:

  1. public class A {
  2. @Value("${param.username}")
  3. private String username;
  4. @Value("${param.password}")
  5. private String password;
  6. @GetMapping(path = "functionA")
  7. public AuthentificationModel getClient() {
  8. HttpHeaders headers = new HttpHeaders();
  9. headers.setBasicAuth(this.username, this.password);
  10. String jwt = getJWT(); // 这个函数也在类A中
  11. // ... 这里构造参数,以便进行POST请求
  12. return token;
  13. }
  14. }

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

我的类B是:

  1. import fr.ag2rlamondiale.ytb.rest.A; // 类A
  2. public class B {
  3. private static Map<String, String> getRequestHeader() {
  4. Map<String, String> requestHeaders = new HashMap<>();
  5. try {
  6. final A objA = new A(); // 在这里创建了类A的实例
  7. String token = objA.getClient().getAccessToken(); // getClient()是类A中返回token的函数
  8. requestHeaders.put("Authorization", "Bearer " + token);
  9. // ... 其他添加头部的操作
  10. } catch (CommonException e) {
  11. e.printStackTrace();
  12. }
  13. return requestHeaders;
  14. }
  15. }

我的application-contextual-values.properties

  1. param.username="kljkjsdf555sdf"
  2. 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 :

  1. public class A {
  2. @Value(&quot;${param.username}&quot;)
  3. private String username;
  4. @Value(&quot;${param.password}&quot;)
  5. private String password;
  6. @GetMapping(path = &quot;functionA&quot;)
  7. public AuthentificationModel getClient() {
  8. HttpHeaders headers = new HttpHeaders();
  9. headers.setBasicAuth(this.username, this.password);
  10. String jwt = getJWT(); &lt;====== this function is also in this class A
  11. ...
  12. I&#39;m doing a construction of params, to send on POST
  13. return token;
  14. }

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

My class B is :

  1. import fr.ag2rlamondiale.ytb.rest.A; &lt;==== class A
  2. public class B {
  3. private static Map&lt;String, String&gt; getRequestHeader() {
  4. Map&lt;String, String&gt; requestHeaders = new HashMap&lt;&gt;();
  5. try{
  6. final A objA = new A(); &lt;===== instance of my class A here
  7. String token = objA.getClient().getAccessToken(); &lt;==== getClient() is the funct that returns token on class A
  8. requestHeaders.put(&quot;Authorization&quot;, &quot;Bearer &quot;, + token);
  9. ... many other put for header
  10. } catch (CommonException e) {
  11. e.printStackTrace();
  12. }
  13. return requestHeaders;
  14. }

My application-contextual-values.properties :

  1. param.username=&quot;kljkjsdf555sdf&quot;
  2. 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的实例时:

  1. 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:

  1. 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注解。

  1. @Controller
  2. public class A {

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

  1. public class B {
  2. @Autowired
  3. A objA;
  4. private static Map<String, String> getRequestHeader() {
  5. Map<String, String> requestHeaders = new HashMap<>();
  6. try{
  7. //final A objA = new A(); <===== 在此处实例化了我的A类的实例
  8. 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.

  1. @Controller
  2. public class A {

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

  1. public class B {
  2. @Autowired
  3. A objA;
  4. private static Map&lt;String, String&gt; getRequestHeader() {
  5. Map&lt;String, String&gt; requestHeaders = new HashMap&lt;&gt;();
  6. try{
  7. //final A objA = new A(); &lt;===== instance of my class A here
  8. 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:

确定