Spring @Scheduled выполнение задания в два раза больше ожидаемого количества раз - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь периодически выполнять какую-то работу в приложении Spring MVC.Основываясь на обучающих материалах онлайн, я настроил запланированное задание следующим образом:

Вот AppInitializer (у меня нет настроек в XML):

public class AppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();  
        rootContext.register(JPAConfiguration.class);

        servletContext.addListener(new ContextLoaderListener(rootContext));

        AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
        dispatcherServlet.register(MvcConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

    }
}

Вот файл конфигурации:

@Configuration
@EnableScheduling
@EnableTransactionManagement
@ComponentScan(basePackages = {"com.prime.tutorials"})
@EnableJpaRepositories(basePackages = {"com.prime.tutorials.model", "com.prime.tutorials.repository"})
public class JPAConfiguration {

    @Value("${jdbcURL}")
    private transient String jdbcURL;

    @Value("${dbPassword}")
    private transient String dbPassword;

    /* The usual stuff here, let me know if you want me post that as well */


}

Это класс, обрабатывающий запланированное задание:

@Service
public class ScheduledJobService {

    @Autowired
    private PrimeRepository primeRepository

    @Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds:10000}")
    public void run() {
        System.out.println("Current time is :: " + Calendar.getInstance().getTime());
    }

}

Как видите, фиксированная задержка установлена ​​на 10 секунд, но моя работа выполняется каждые 5 секунд.Я не могу понять, почему это происходит.Ранее я просматривал вопросы, связанные с этой темой, но не смог найти подходящего решения.

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

Аналогичный вопрос Этот вопрос, представленный выше, кажется точной копией того, что я спрашиваю, но ОП не опубликовал свою конфигурацию или настройку.Большинство ответов предполагают двойную инициализацию компонентов, что, я не уверен, имеет место в моем приложении.

Current time is :: Sun Jun 10 22:53:16 EDT 2018
Current time is :: Sun Jun 10 22:53:22 EDT 2018
Current time is :: Sun Jun 10 22:53:26 EDT 2018
Current time is :: Sun Jun 10 22:53:32 EDT 2018
Current time is :: Sun Jun 10 22:53:36 EDT 2018

EDIT-1

Основываясь на предложении Дженнифер, я вижу, что два экземпляра вызывают метод run.

РЕДАКТИРОВАТЬ-2

Догадка М.Дейнума была абсолютно верной, мой MvcConfig.java был аннотирован @ComponentScan, который дважды запустил задание по расписанию.Но после удаления этой аннотации из MvcConfig.java мои конечные точки перестали работать.Что мне здесь не хватает ..

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Проблема в том, что у вас, вероятно, одинаковое сканирование компонентов как в JPAConfiguration, так и в MvcConfig.В результате вы в основном загружаете приложение целиком дважды (поэтому, если вы не хотите иметь проблемы с памятью, странные проблемы с транзакциями и т. Д., Это лучший способ).

Вам нужно, чтобы ваш ContextLoaderListener (корневой контекст) загружал все, кроме связанных с веб-компонентами компонентов, а DispatcherServlet должен загружать только связанные с веб-компонентами (представления, контроллеры, советы и т. Д.).

@ComponentScan имеет свойства, с помощью которых вы можете управлять этим.В JPAConfiguration добавьте excludeFilters, в MvcConfig отключите значения по умолчанию и добавьте includeFilters.

Ваш @ComponentScan для JPAConfiguration должен содержать следующее:

@ComponentScan(
        basePackages = {"com.prime.tutorials"},
        excludeFilters = {
            @ComponentScan.Filter( { Controller.class, ControllerAdvice.class })
})

Ваш MvcConfig вы должны использовать то же самое, но вместо includeFilters и отключить фильтры по умолчанию,

@ComponentScan(
        basePackages = {"com.prime.tutorials"},
        useDefaultFilters = false,
        includeFilters = {
            @ComponentScan.Filter( { Controller.class, ControllerAdvice.class })
})

Вы не хотите делать разные базовые пакеты, так как это было бы довольно громоздко.Также ИМХО не следует использовать техническое разделение как способ создания пакетов (см. Также https://softwareengineering.stackexchange.com/questions/258196/java-application-structure-horizontal-vs-vertical-split/258197#258197).

0 голосов
/ 11 июня 2018

Обычно это происходит, когда вы создаете более одного экземпляра класса Scheduled (ScheduledJobService).Распространенной причиной является то, что контекст Spring создается более одного раза.

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

public void run() {
   System.out.println(this + " Current time is :: " + Calendar.getInstance().getTime());
}

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

Чтобы убедиться, что это не значение свойства, попробуйте без жестко закодированного значения 10000.

@Scheduled(fixedDelay = 10000)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...