为什么我在使用@Value Annotations时收到Null Exception?

时间:2021-09-24 11:46:45

I switched from getting values by loading up the properties file and retrieve them to using @Value annotations. Right now I am able to print the values that I set. When I run my application I see the value, But when I open up localhost:8080 I receive a null exception.

我通过加载属性文件从获取值切换到使用@Value注释检索它们。现在我能够打印我设置的值。当我运行我的应用程序时,我看到了值,但是当我打开localhost:8080时,我收到一个null异常。

IndexController

@Controller
public class IndexController {
     @RequestMapping(value = "/", method = RequestMethod.GET)
     public ModelAndView getdata() throws IOException {
        AppPortList apL = new AppPortList();
        List<AppPortModel> apList = apL.getAppPortList();   
        Collections.sort(apList);

ModelAndView model = new ModelAndView("index");
    model.addObject("showap", apList);

    return model;
}

Properties file

APP_SERVERS=Server1@!Server1212@!Server12daa21@!Server21334
APP_SERVER_List=1020@!3011@!8080@!2020

//much more servers than this.

//比这更多的服务器。

Class that is having errors

有错误的类

@Component
public class AppPortList {      

 @Value("#{'${APP_SERVERS}'.split('@!')}")
    private String[] apServerArray;
 @Value("#{'${APP_SERVER_List}'.split('@!')}")
    private String[] appServerPortsList;

@PostConstruct
public List<AppPortModel> getAppPortList() {
    try {
        System.out.println(apServerArray.length + "@@@@");
            for (int z = 0; z < apServerArray.length; z++) {                
                String apServer = apServerArray[z];
                String[] portListArray=appServerPortsList;
}catch {//stuff}

Console Output

16@@@@@

When I open local host I receive a null exception on Line 80. Which is my for Statement. "for (int z = 0; z < apServerArray.length; z++)" is coming up null.

当我打开本地主机时,我在第80行收到一个空例外。这是我的声明。 “for(int z = 0; z ;>

Running local Host Error

运行本地主机错误

  java.lang.NullPointerException: null
at com.spring.web.util.AppPortList.getAppPortList(AppPortList.java:82) ~[classes/:na]
    at com.spring.web.controller.IndexController.getdata(IndexController.java:61) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91]

Attempt 2

So I commented my for statment out and used System.out.println(apServerArray + "@@@@");

所以我评论了我的陈述并使用了System.out.println(apServerArray +“@@@@”);

Output 2

 [Ljava.lang.String;@328b8745@@@@@

and when I ran my localhost I get null. So why does my console reads it when I run it then when I open localhost it becomes null?

当我运行我的localhost时,我得到null。那么为什么我的控制台在运行它时会读取它然后当我打开localhost时它会变为空?

  null@@@@@

1 个解决方案

#1


1  

You're seeing two things here:

你在这里看到两件事:

You annotated AppPortList with @Component, so when you start your application, your beans are created by the Spring container and the @PostConstruct is called. When a bean is created by Spring, it also injects values for the @Value annotations, so that's why you see the correct output in the System.out.println() inside your @PostConstruct.

您使用@Component注释了AppPortList,因此当您启动应用程序时,您的bean由Spring容器创建并调用@PostConstruct。当一个bean由Spring创建时,它也会为@Value注释注入值,这就是为什么你在@PostConstruct里面的System.out.println()中看到了正确的输出。

However, in your controller you are using new AppPortList(). In this case you created the beans by yourself and you're not using the bean offered by the Spring container. In this case, the @Value annotation is not picked up, so the output is null.

但是,在您的控制器中,您正在使用新的AppPortList()。在这种情况下,您自己创建了bean,并且您没有使用Spring容器提供的bean。在这种情况下,不会拾取@Value注释,因此输出为null。

The solution is simple, rather than using the new keyword, you have to use dependency injection. When you use dependency injection, the Spring container will look for an instance of the bean (which is has thanks to the @Component annotation) and it will inject it where you need it.

解决方案很简单,而不是使用new关键字,您必须使用依赖注入。当您使用依赖注入时,Spring容器将查找该bean的实例(这要归功于@Component注释),它将在您需要的地方注入它。

In your case you need it in your IndexController, so you'll have to change it a bit:

在你的情况下,你需要在IndexController中,所以你必须稍微改变它:

@Controller
public class IndexController {
    @Autowired
    private AppPortList apL; // Create this field with @Autowired annotation

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView getdata() throws IOException {
        // Remove new AppPortList() and use field in stead
        List<AppPortModel> apList = apL.getAppPortList();   
        // ...
}

#1


1  

You're seeing two things here:

你在这里看到两件事:

You annotated AppPortList with @Component, so when you start your application, your beans are created by the Spring container and the @PostConstruct is called. When a bean is created by Spring, it also injects values for the @Value annotations, so that's why you see the correct output in the System.out.println() inside your @PostConstruct.

您使用@Component注释了AppPortList,因此当您启动应用程序时,您的bean由Spring容器创建并调用@PostConstruct。当一个bean由Spring创建时,它也会为@Value注释注入值,这就是为什么你在@PostConstruct里面的System.out.println()中看到了正确的输出。

However, in your controller you are using new AppPortList(). In this case you created the beans by yourself and you're not using the bean offered by the Spring container. In this case, the @Value annotation is not picked up, so the output is null.

但是,在您的控制器中,您正在使用新的AppPortList()。在这种情况下,您自己创建了bean,并且您没有使用Spring容器提供的bean。在这种情况下,不会拾取@Value注释,因此输出为null。

The solution is simple, rather than using the new keyword, you have to use dependency injection. When you use dependency injection, the Spring container will look for an instance of the bean (which is has thanks to the @Component annotation) and it will inject it where you need it.

解决方案很简单,而不是使用new关键字,您必须使用依赖注入。当您使用依赖注入时,Spring容器将查找该bean的实例(这要归功于@Component注释),它将在您需要的地方注入它。

In your case you need it in your IndexController, so you'll have to change it a bit:

在你的情况下,你需要在IndexController中,所以你必须稍微改变它:

@Controller
public class IndexController {
    @Autowired
    private AppPortList apL; // Create this field with @Autowired annotation

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView getdata() throws IOException {
        // Remove new AppPortList() and use field in stead
        List<AppPortModel> apList = apL.getAppPortList();   
        // ...
}