简体   繁体   中英

Spring RestController interacting with other Java classes

I'm quite new to Spring. I've used it before to make a REST API and I'm using it again now for the same purpose.

In addition to hosting the REST service, this program also repeatedly opens a file, scans for patterns, and maintains a structure of what it finds.

Right now we're starting that control flow here.

@SpringBootApplication
@EnableWebSecurity
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
    SSHParser parser = new SSHParser();
    parser.startParserLoop();
  }
}

In the RestController we want to have a reference to that parser object so we can use it in the HTTP request methods.

@RestController
public class RestController {

  @Autowire
  SSHParser parser;

  @RequestMapping("/api/list")
  public Entry[] getList()  {
    return parser.list();
  }
}

I think I understand we could do something like the above, but this creates a new instance of SSHParser when what we really need is the instance parser from the main method.

Is this something we're just not meant to do with the Spring framework? Would it be possible to call the constructor for the rest controller ourselves to pass a reference that way?

You should create the SSHParser object as a Spring bean to make it possible to inject with the @Autowired annotation. Change your Application class to something like this:

@SpringBootApplication
@EnableWebSecurity
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Bean
  public SSHParser sshParser() {
    SSHParser parser = new SSHParser();
    parser.startParserLoop();
    return parser;
  }

}

This code does exactly the same what your does, but in addition, it allows to reuse the created instance in other objects managed by the Spring container. By default, Spring creates a bean in the singleton scope so you'll have only one instance of SSHParser.

In order to be able to autowire it, you will need to configure it as a Spring bean:

@Configuration
public class AppConfig {
    @Bean
    public SSHParser createSSHParser() {
        SSHParser parser = new SSHParser();
        parser.startParserLoop();
        return parser;
    }
}

The @Configuration class and the method name may be called what you like

At the moment you are injecting your SSHParser in the controler too. If you only want to have one instance of the SSHParser then you should consider using a singleton pattern

puclic class SSHParser {
    private static SSHParser instance;
    private SSHParser() {
    //private constructor, no one can instanciate this class
    }
    public static SSHParser getInstance() {
        if(SSHParser.instance==null) {
            SSHParser.instance = new SSHParser();
        }
        return SSHParser.instance;
    }
}

Then in your controller just call the getInstance method to get one unique instance. If you cannot modify the SSHPArser class then you can set up a wrapper or a Factory .

You don't need to instanciate the SShParser yourself in the main method. Pull it from spring using the ApplicationContext.

@SpringBootApplication
@EnableWebSecurity
public class Application {

   public static void main(String[] args) {
      ConfigurableApplicationContext context=SpringApplication.run(Application.class, args);
      SSHParser parser = (SSHParser) context.getBean(SSHParser .class);
      parser.startParserLoop();
  }
}

spring will create only one instance of the SSHParser bean an use it with all the services that require it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM