如何在Java中使方法参数全球化?

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

how to globalize method parameter in java?

问题

我创建了一个方法,其中有两个参数。

以下是简要描述:

public static final Logger log = LoggerFactory.getLogger(MyClass.class);

public String executeRequest(final String content, final String appId) {
     log.info("使用appID[{}]发起请求", appId);
     /*一些代码在这里*/
     .............
     .............
     return content;
}

参数 appId 仅在日志中使用。我想要将它全局化。
之所以这样做的原因是,我不想在每个方法中都放入这个参数,那么我应该如何巧妙地做呢?或者这样做是否明智?

基本上我会这样做:

public static final Logger log = LoggerFactory.getLogger(MyClass.class);
public static String applicationId;

public String executeRequest(final String content, final String appId) {
     applicationId = appId;
     log.info("使用appID[{}]发起请求", applicationId);
     /*一些代码在这里*/
     .............
     .............
     return content;
}

所以我的问题是,从架构师的角度来看,这样做可以吗?我应该这样做吗?

英文:

I've created method in which I have 2 params.

Here's short description:

public static final Logger log = LoggerFactory.getLogger(MyClass.class);

public String executeRequest(final String content, final String appId) {
     log.info("launching request with appID[{}]", appId);
     /*some code here*/
     .................
     .................
     return content;
}

The parameter appId is only used in logs. I want to globalize it.
The reason why is that I dont want to put that param in every method I make so how should I do it smartly? or is it even a good idea to do it like that?

basically I would do it like this:

public static final Logger log = LoggerFactory.getLogger(MyClass.class);

public static String applicationId;

public String executeRequest(final String content, final String appId) {

     applicationId = appId;

     log.info("launching request with appID[{}]", applicationId);
     /*some code here*/
     .................
     .................
     return content;
}

So my question would be. From the architect point of view is it ok to do it like this? Should I even do it like that?

答案1

得分: 1

根据我对你问题的理解:

  • 每次调用 executeRequest(final String content, final String appId) 都会带有自己的 appId,我猜这个 appId 在某种程度上可以标识调用者。
  • 可能会有多个请求并行运行,每个在独立的线程中。
  • 在记录日志时,你希望日志中包含导致该请求的 appId
  • 你不想将这个 appId 传递到每个可能进行日志记录的方法中。
  • executeRequest(final String content, final String appId) 没有递归调用,至少没有 appId 与初始值不同的递归调用。

我同意,在这种情况下,将 appId 添加到许多方法签名中是没有意义的,因为它只用于日志记录,与常规处理无关。

那么我会使用 ThreadLocal<String>

public static final Logger log = LoggerFactory.getLogger(MyClass.class);

public static final ThreadLocal<String> appIdHolder = new ThreadLocal<>();

public String executeRequest(final String content, final String appId) {
    appIdHolder.set(appId);
    log.info("launching request with appID[{}]", appIdHolder.get());
    /*一些代码在这里*/
    .............
    .............
    return content;
}

ThreadLocal 给你一种全局变量的感觉,额外的特性是它为每个线程保存一个值。如果有多个请求并行运行,它们不会干扰彼此,因为它们运行在不同的线程上,所以它们会有各自的值。

如果你没有 executeRequest() 的递归调用,你可以考虑在方法体末尾添加 appIdHolder.remove() 来释放线程特定的资源,如果你认为有必要的话。但是不要在递归调用中这样做,因为那样的话某个嵌套调用会清除这个变量,剩下的代码将缺少有效的 appIdThreadLocal 不支持类似栈的值推送和弹出。

英文:

As far as I understand your problem:

  • Every invocation of executeRequest(final String content, final String appId) brings its own appId, I guess it somehow identifies the caller.
  • There can be multiple requests running in parallel, in individual threads.
  • When logging, you want the log to contain this appId that caused the request.
  • You don't want to pass this appId down the complete call stack to every method where logging might occur.
  • There are no recursive calls of executeRequest(final String content, final String appId), at least none where the appId differs from the initial one.

I agree that in such a case the appId is not worth being added to lots of method signatures, as it's only used for logging and has nothing to do with the regular processing.

Then I'd use a ThreadLocal&lt;String&gt;.

public static final Logger log = LoggerFactory.getLogger(MyClass.class);

public static final ThreadLocal&lt;String&gt; appIdHolder = new ThreadLocal&lt;&gt;();

public String executeRequest(final String content, final String appId) {
     appIdHolder.set(appId);
     log.info(&quot;launching request with appID[{}]&quot;, appIdHolder.get());
     /*some code here*/
     .................
     .................
     return content;
}

ThreadLocal gives you a kind of global variable, with the additional feature that it holds one value per thread. If multiple requests are running in parallel, they won't interfere, as they run on different threads, and so they get individual values.

If you don't have recursive calls of executeRequest(), you might consider adding appIdHolder.remove() at the end of the method body to free the thread-specific resource if you think that's necessary. But don't do it with recursive calls, because then some nested call would clear the variable, and the remaining code would lack a valid appId. ThreadLocal does not support stack-like pushing and popping of values.

答案2

得分: 0

自从你提到值在不同进程中可以改变,你只需要使用属性:

public class Constants {

   public static final String APP_ID = System.getProperty("APP_ID");

}

并且像这样运行你的 JAR 文件:java -jar myjar.jar -DAPP_ID=some value。同时,Eclipse 和 IDEA 也允许你通过 -D 传递参数。

英文:

Since you tell that value can change for different process you just use properties

public class Constants {

   public static final String APP_ID = System.getProperty(&quot;APP_ID&quot;);

}

and run you jar like java -jar myjar.jar -DAPP_ID=some value. Also Eclipse & IDEA allows you to pass parameters via -D as well

huangapple
  • 本文由 发表于 2020年9月23日 18:54:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64026390.html
匿名

发表评论

匿名网友

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

确定