2015-11-12 8 views
1

Я довольно новичок в Spring. Я использовал его раньше, чтобы создать REST API, и теперь я использую его снова для этой же цели.Spring RestController, взаимодействующий с другими классами Java

В дополнение к размещению службы REST эта программа также многократно открывает файл, сканирует шаблоны и поддерживает структуру того, что он находит.

Прямо сейчас мы начинаем этот поток управления здесь.

@SpringBootApplication 
@EnableWebSecurity 
public class Application { 

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

В RestController мы хотим иметь ссылку на этот объект синтаксического анализа, поэтому мы можем использовать его в методах запроса HTTP.

@RestController 
public class RestController { 

    @Autowire 
    SSHParser parser; 

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

Я думаю, что я понимаю, что мы могли бы сделать что-то вроде выше, но это создает новый экземпляр SSHParser когда то, что нам действительно нужно, это экземпляр parser от метода main.

Это что-то, что мы не собираемся делать с весной? Можно ли вызвать конструктор для остального контроллера самостоятельно, чтобы передать ссылку таким образом?

ответ

2

You должен создать объект SSHParser в виде Spring-компонента, чтобы можно было вставлять @Autowired аннотацию. Измените класс приложений на что-то вроде этого:

@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; 
    } 

} 

Этот код делает то же самое, что ваш делает, но кроме того, она позволяет повторно использовать созданный экземпляр в других объектов, управляемых с помощью Spring контейнера. По умолчанию Spring создает компонент в одноэлементной области, поэтому у вас будет только один экземпляр SSHParser.

0

Для того, чтобы иметь возможность autowire его, вам нужно будет настроить его как Spring бина:

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

Класс @Configuration и имя метода можно назвать то, что вам нравится

+1

'@ SpringBootApplication' - это оболочка для' @ Configuration' и других аннотаций, поэтому нет необходимости создавать другой класс конфигурации –

+0

@ Daniel Olszewski: Ah OK. Не знал этого, но видел ваше решение, которое указывает на это. Это, конечно, короче. – morsor

0

В данный момент вы также вводите свой SSHParser в контроллер. Если вы хотите иметь один экземпляр SSHParser, то вы должны рассмотреть возможность использования 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; 
    } 
} 

Тогда в контроллере просто вызвать метод GetInstance, чтобы получить один уникальный экземпляр. Если вы не можете изменить класс SSHPArser, вы можете настроить обертку или Factory.

+0

Это также делает ваш код невозможным для тестирования, так как он мешает вам удалять или издеваться над ссылкой на SSHParser. –

+0

. Сравните с Spring injection, это правда.Но вы все равно можете использовать Frameworks для тестирования статического метода как [PowerMock] (http://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito). Это еще одна структура для использования, может быть раздражающей, но есть решение =) Но в любом случае я предпочитаю ваше решение (которое мне было неизвестно). – RPresle

0

Вам не нужно самостоятельно запускать SShParser в основном методе. Потяните его с весны, используя 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(); 
    } 
} 

пружина создаст только один экземпляр SSHParser боба пользы оно со всеми услугами, которые требуют этого.

Смежные вопросы