Spring集成和用户界面

时间:2018-10-29 09:56:58

标签: java spring-mvc spring-integration

我有一个用户界面,可以在其中添加或删除保留在postgres DB中的FTP服务器(添加端口和用户名..etc),我的应用程序将使用Spring MVC和Spring Integration读取数据库中的连接对于动态FTP(我正在使用委派会话工厂和旋转建议),应用在运行时正在运行,并读取了数据库中可用的连接,因此将传输我指定的FTP目录中的可用连接。我的问题是,如果我使用该界面删除或添加新服务器,则除非停止并再次运行它,否则该应用程序不会采用保留在数据库中的新连接,我想使其在运行时正常运行。并删除要自动处理的服务器。 这是我用于设置集成流程的conf类,我不确定是否有任何注释可以使此工作正常进行。有人可以指导吗? 让我知道是否需要更多信息

    @Configuration
@Component
@EnableIntegration
public class FTIntegration {

    public static final String TIMEZONE_UTC = "UTC";
    public static final String TIMESTAMP_FORMAT_OF_FILES = "yyyyMMddHHmmssSSS";
    public static final String TEMPORARY_FILE_SUFFIX = ".part";
    public static final int POLLER_FIXED_PERIOD_DELAY = 5000;
    public static final int MAX_MESSAGES_PER_POLL = 100;


    private static final Logger LOG = LoggerFactory.getLogger(FTIntegration.class);
    private static final String CHANNEL_INTERMEDIATE_STAGE = "intermediateChannel";

     @Autowired
    private IntegrationFlowContext flowContext;

    /* pulling the server config from postgres DB*/

    private final BranchRepository branchRepository;

    @Value("${app.temp-dir}")
    private String localTempPath;

    public FTIntegration(BranchRepository branchRepository) {
        this.branchRepository = branchRepository;
    }

    @Bean
    public Branch myBranch(){
        return new Branch();
    }

    /**
     * The default poller with 5s, 100 messages, RotatingServerAdvice and transaction.
     *
     * @return default poller.
     */
    @Bean(name = PollerMetadata.DEFAULT_POLLER)
    public PollerMetadata poller(){
        return Pollers
                .fixedDelay(POLLER_FIXED_PERIOD_DELAY)
                .maxMessagesPerPoll(MAX_MESSAGES_PER_POLL)
                .transactional()
                .get();
    }

    /**
     * The direct channel for the flow.
     *
     * @return MessageChannel
     */
    @Bean
    public MessageChannel stockIntermediateChannel() {
        return new DirectChannel();
    }

    /**
     * Get the files from a remote directory. Add a timestamp to the filename
     * and write them to a local temporary folder.
     *
     * @return IntegrationFlow
     */

    public IntegrationFlow fileInboundFlowFromFTPServer(Branch myBranch){

        final FtpInboundChannelAdapterSpec sourceSpecFtp = Ftp.inboundAdapter(createNewFtpSessionFactory(myBranch))
                .preserveTimestamp(true)
                .patternFilter("*.csv")
                .deleteRemoteFiles(true)
                .maxFetchSize(MAX_MESSAGES_PER_POLL)
                .remoteDirectory(myBranch.getFolderPath())
                .localDirectory(new File(localTempPath))
                .temporaryFileSuffix(TEMPORARY_FILE_SUFFIX)
                .localFilenameExpression(new FunctionExpression<String>(s -> {
                    final int fileTypeSepPos = s.lastIndexOf('.');
                    return DateTimeFormatter
                            .ofPattern(TIMESTAMP_FORMAT_OF_FILES)
                            .withZone(ZoneId.of(TIMEZONE_UTC))
                            .format(Instant.now())
                            + "_"
                            + s.substring(0,fileTypeSepPos)
                            + s.substring(fileTypeSepPos);
                }));

        // Poller definition
        final Consumer<SourcePollingChannelAdapterSpec> stockInboundPoller = endpointConfigurer -> endpointConfigurer
                .id("stockInboundPoller")
                .autoStartup(true)
                .poller(poller());

        IntegrationFlow flow = IntegrationFlows
                .from(sourceSpecFtp, stockInboundPoller)
                .transform(File.class, p ->{
                    // log step
                    LOG.info("flow=stockInboundFlowFromAFT, message=incoming file: " + p);
                    return p;
                })
                .channel(CHANNEL_INTERMEDIATE_STAGE)
                .get();


       // this.flowContext.registration(flow).id(myBranch.getId().toString()).register().toString();
        //this.flowContext.registration(flow).id("fileInb").register();
        return flow;
    }

   @Bean
    public IntegrationFlow stockIntermediateStageChannel() {
        IntegrationFlow flow = IntegrationFlows
                .from(CHANNEL_INTERMEDIATE_STAGE)
                .transform(p -> {
                    //log step
                    LOG.info("flow=stockIntermediateStageChannel, message=rename file: " + p);
                    return p;
                })
                //TODO
                .channel(new NullChannel())
                .get();
        return flow;

    }

    public DefaultFtpSessionFactory createNewFtpSessionFactory(Branch branch){
        final DefaultFtpSessionFactory factory = new DefaultFtpSessionFactory();
        factory.setHost(branch.getHost());
        factory.setUsername(branch.getUsern());
        factory.setPort(branch.getFtpPort());
        factory.setPassword(branch.getPassword());
        return factory;
    }
}

这是删除服务器的控制器部分。

@Controller
public class BranchController {

    private BranchService branchService;

    private BranchToBranchForm branchToBranchForm;

    //@Autowired
    private Branch branch;

    @Autowired
    private FTIntegration ftIntegration;


    private static final Logger LOG = LoggerFactory.getLogger(FTIntegration.class);
    private static final String CHANNEL_INTERMEDIATE_STAGE = "intermediateChannel";


    @Autowired
    private IntegrationFlowContext flowContext;

    @Autowired
    public void setBranchService(BranchService branchService) {
        this.branchService = branchService;
    }

    @Autowired
    public void setBranchToBranchForm(BranchToBranchForm branchToBranchForm) {
        this.branchToBranchForm = branchToBranchForm;
    }

    @RequestMapping( "/")
    public String branch(){return "redirect:/branch/list";}

    @RequestMapping({"/branch/list","/branch"})
    public String listBranches(Model model){
        model.addAttribute("branches",branchService.listAll());
        return "branch/list";
    }

    @RequestMapping("/branch/showbranch/{id}")
    public String getBranch (@PathVariable String id, Model model){
       model.addAttribute("branch", branchService.getById(Long.valueOf(id)));
       //addFlowFtp(id);
       addFlowftp(id);
        return "/branch/showbranch";

    }

    @RequestMapping("/branch/edit/{id}")
    public String edit(@PathVariable String id, Model model){
        Branch branch = branchService.getById(Long.valueOf(id));
        BranchForm branchForm = branchToBranchForm.convert(branch);
        model.addAttribute("branchForm",branchForm);
        return "branch/branchform";

    }

    @RequestMapping("/branch/new")
    public String newBranch(Model model){
        model.addAttribute("branchForm", new BranchForm());
         return "branch/branchform";
    }

       @RequestMapping(value = "/branch", method = RequestMethod.POST)
    public String saveOrUpdateBranch(@Valid BranchForm branchForm, BindingResult bindingResult){

        if(bindingResult.hasErrors()){
            return "branch/branchform";
        }

        Branch savedBranch = branchService.saveOrUpdateBranchForm(branchForm);
        return "redirect:/branch/showbranch/" + savedBranch.getId();
    }

    @RequestMapping("/branch/delete/{id}")
    private String delete(@PathVariable String id){
        branchService.delete(Long.valueOf(id));
        flowContext.remove(id);
        return "redirect:/branch/list";
    }

    private void addFlowftp(String name) {
        branch = branchService.getById(Long.valueOf(name));
        System.out.println(branch.getBranchCode());

        IntegrationFlow flow = ftIntegration.fileInboundFlowFromFTPServer(branch);

        this.flowContext.registration(flow).id(name).register();
    }

1 个答案:

答案 0 :(得分:0)

请参见Dynamic and runtime Integration Flows

您可以使用此处介绍的技术在运行时添加/删除集成流。

编辑

这里是一个例子:

@SpringBootApplication
@RestController
public class So53042903Application {

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

    @Autowired
    private IntegrationFlowContext flowContext;

    @RequestMapping(path = "/add/{name}", method = RequestMethod.GET)
    public String add(@PathVariable String name) {
        addFlow(name);
        System.out.println("added " + name);
        return "added " + name;
    }

    @RequestMapping(path = "/remove/{name}", method = RequestMethod.GET)
    public String remove(@PathVariable String name) {
        this.flowContext.remove(name);
        System.out.println("removed " + name);
        return "removed " + name;
    }

    private void addFlow(String name) {
        IntegrationFlow flow = IntegrationFlows.from(() -> "processing: " + name, e -> e
                    .poller(Pollers.fixedDelay(3_000)))
                .log(Level.INFO, "foo", "payload")
                .get();
        this.flowContext.registration(flow).id(name).register();
    }

}

added foo
2018-10-31 10:22:58.998  INFO 1768 --- [ask-scheduler-1] foo                                      : processing: foo
2018-10-31 10:23:02.001  INFO 1768 --- [ask-scheduler-1] foo                                      : processing: foo
2018-10-31 10:23:05.002  INFO 1768 --- [ask-scheduler-2] foo                                      : processing: foo
2018-10-31 10:23:07.312  INFO 1768 --- [nio-8080-exec-2] o.s.i.endpoint.EventDrivenConsumer       : Adding {bridge} as a subscriber to the 'bar.channel#1' channel
2018-10-31 10:23:07.312  INFO 1768 --- [nio-8080-exec-2] o.s.integration.channel.DirectChannel    : Channel 'application.bar.channel#1' has 1 subscriber(s).
2018-10-31 10:23:07.312  INFO 1768 --- [nio-8080-exec-2] o.s.i.endpoint.EventDrivenConsumer       : started bar.org.springframework.integration.config.ConsumerEndpointFactoryBean#0
2018-10-31 10:23:07.312  INFO 1768 --- [nio-8080-exec-2] o.s.i.e.SourcePollingChannelAdapter      : started bar.org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0
added bar
2018-10-31 10:23:07.312  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: bar
2018-10-31 10:23:08.008  INFO 1768 --- [ask-scheduler-1] foo                                      : processing: foo
2018-10-31 10:23:10.316  INFO 1768 --- [ask-scheduler-2] foo                                      : processing: bar
2018-10-31 10:23:11.009  INFO 1768 --- [ask-scheduler-4] foo                                      : processing: foo
2018-10-31 10:23:13.318  INFO 1768 --- [ask-scheduler-5] foo                                      : processing: bar
2018-10-31 10:23:14.011  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: foo
2018-10-31 10:23:16.322  INFO 1768 --- [ask-scheduler-6] foo                                      : processing: bar
2018-10-31 10:23:16.614  INFO 1768 --- [nio-8080-exec-4] o.s.i.endpoint.EventDrivenConsumer       : Adding {bridge} as a subscriber to the 'baz.channel#1' channel
2018-10-31 10:23:16.614  INFO 1768 --- [nio-8080-exec-4] o.s.integration.channel.DirectChannel    : Channel 'application.baz.channel#1' has 1 subscriber(s).
2018-10-31 10:23:16.614  INFO 1768 --- [nio-8080-exec-4] o.s.i.endpoint.EventDrivenConsumer       : started baz.org.springframework.integration.config.ConsumerEndpointFactoryBean#0
2018-10-31 10:23:16.614  INFO 1768 --- [nio-8080-exec-4] o.s.i.e.SourcePollingChannelAdapter      : started baz.org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0
added baz
2018-10-31 10:23:16.614  INFO 1768 --- [ask-scheduler-7] foo                                      : processing: baz
2018-10-31 10:23:17.012  INFO 1768 --- [ask-scheduler-1] foo                                      : processing: foo
2018-10-31 10:23:19.323  INFO 1768 --- [ask-scheduler-2] foo                                      : processing: bar
2018-10-31 10:23:19.615  INFO 1768 --- [ask-scheduler-8] foo                                      : processing: baz
2018-10-31 10:23:20.014  INFO 1768 --- [ask-scheduler-4] foo                                      : processing: foo
2018-10-31 10:23:22.324  INFO 1768 --- [ask-scheduler-9] foo                                      : processing: bar
2018-10-31 10:23:22.622  INFO 1768 --- [ask-scheduler-5] foo                                      : processing: baz
2018-10-31 10:23:23.015  INFO 1768 --- [sk-scheduler-10] foo                                      : processing: foo
2018-10-31 10:23:25.326  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: bar
2018-10-31 10:23:25.623  INFO 1768 --- [ask-scheduler-6] foo                                      : processing: baz
2018-10-31 10:23:26.020  INFO 1768 --- [ask-scheduler-7] foo                                      : processing: foo
2018-10-31 10:23:27.966  INFO 1768 --- [nio-8080-exec-6] o.s.i.e.SourcePollingChannelAdapter      : stopped bar.org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0
2018-10-31 10:23:27.966  INFO 1768 --- [nio-8080-exec-6] o.s.i.endpoint.EventDrivenConsumer       : Removing {bridge} as a subscriber to the 'bar.channel#1' channel
2018-10-31 10:23:27.966  INFO 1768 --- [nio-8080-exec-6] o.s.integration.channel.DirectChannel    : Channel 'application.bar.channel#1' has 0 subscriber(s).
2018-10-31 10:23:27.966  INFO 1768 --- [nio-8080-exec-6] o.s.i.endpoint.EventDrivenConsumer       : stopped bar.org.springframework.integration.config.ConsumerEndpointFactoryBean#0
removed bar
2018-10-31 10:23:28.624  INFO 1768 --- [ask-scheduler-1] foo                                      : processing: baz
2018-10-31 10:23:29.025  INFO 1768 --- [ask-scheduler-8] foo                                      : processing: foo
2018-10-31 10:23:31.625  INFO 1768 --- [ask-scheduler-4] foo                                      : processing: baz
2018-10-31 10:23:32.026  INFO 1768 --- [ask-scheduler-9] foo                                      : processing: foo
2018-10-31 10:23:34.626  INFO 1768 --- [ask-scheduler-5] foo                                      : processing: baz
2018-10-31 10:23:35.027  INFO 1768 --- [sk-scheduler-10] foo                                      : processing: foo
2018-10-31 10:23:35.931  INFO 1768 --- [nio-8080-exec-7] o.s.i.e.SourcePollingChannelAdapter      : stopped baz.org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0
2018-10-31 10:23:35.931  INFO 1768 --- [nio-8080-exec-7] o.s.i.endpoint.EventDrivenConsumer       : Removing {bridge} as a subscriber to the 'baz.channel#1' channel
2018-10-31 10:23:35.931  INFO 1768 --- [nio-8080-exec-7] o.s.integration.channel.DirectChannel    : Channel 'application.baz.channel#1' has 0 subscriber(s).
2018-10-31 10:23:35.932  INFO 1768 --- [nio-8080-exec-7] o.s.i.endpoint.EventDrivenConsumer       : stopped baz.org.springframework.integration.config.ConsumerEndpointFactoryBean#0
removed baz
2018-10-31 10:23:38.032  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: foo
2018-10-31 10:23:41.036  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: foo
2018-10-31 10:23:44.037  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: foo
2018-10-31 10:23:47.041  INFO 1768 --- [ask-scheduler-3] foo                                      : processing: foo
2018-10-31 10:23:47.736  INFO 1768 --- [nio-8080-exec-9] o.s.i.e.SourcePollingChannelAdapter      : stopped foo.org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0
2018-10-31 10:23:47.736  INFO 1768 --- [nio-8080-exec-9] o.s.i.endpoint.EventDrivenConsumer       : Removing {bridge} as a subscriber to the 'foo.channel#1' channel
2018-10-31 10:23:47.736  INFO 1768 --- [nio-8080-exec-9] o.s.integration.channel.DirectChannel    : Channel 'application.foo.channel#1' has 0 subscriber(s).
2018-10-31 10:23:47.736  INFO 1768 --- [nio-8080-exec-9] o.s.i.endpoint.EventDrivenConsumer       : stopped foo.org.springframework.integration.config.ConsumerEndpointFactoryBean#0
removed foo
2018-10-31 10:23:51.349  INFO 1768 --- [on(2)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2018-10-31 10:23:51.350  INFO 1768 --- [on(2)-127.0.0.1] o.s.i.endpoint.EventDrivenConsumer       : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2018-10-31 10:23:51.350  INFO 1768 --- [on(2)-127.0.0.1] o.s.i.channel.PublishSubscribeChannel    : Channel 'application.errorChannel' has 0 subscriber(s).
2018-10-31 10:23:51.351  INFO 1768 --- [on(2)-127.0.0.1] o.s.i.endpoint.EventDrivenConsumer       : stopped _org.springframework.integration.errorLogger
2018-10-31 10:23:51.351  INFO 1768 --- [on(2)-127.0.0.1] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'
2018-10-31 10:23:51.352  INFO 1768 --- [on(2)-127.0.0.1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'