Jetty embedded development and spring integration quartz (memory mode)

1 Depend on jar package

2 jetty embedded development

2.1 jetty service startup class

package com.primal.server;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Author whh
 * Date 2023/10/12/ 21:58
 * <p></p>
 */
public class ServerImpl {<!-- -->

    public static void main(String[] args) throws Exception {<!-- -->

        Server server = new Server(8888);


        //servlet service
        ServletHandler servletHandler = new ServletHandler(){<!-- -->{<!-- -->

            addServletWithMapping(new ServletHolder(new HttpServlet() {<!-- -->
                @Override
                protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<!-- -->
                    resp.setContentType("text/html; charset=utf-8");
                    resp.setStatus(HttpServletResponse.SC_OK);
                    PrintWriter out = resp.getWriter();
                    out.println("<h1>" + "hello" + "</h1>");
                }

                @Override
                protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<!-- -->
                    super.doPost(req, resp);
                }
            }),"/hello");
        }};

        //File service
        ResourceHandler resourceHandler = new ResourceHandler() {<!-- -->{<!-- -->
            setDirectoriesListed(true);
            setWelcomeFiles(new String[]{<!-- -->"index.html"});
            setResourceBase(".");
        }};


        HandlerList handlers = new HandlerList();
        handlers.setHandlers(new Handler[] {<!-- --> resourceHandler, servletHandler });
        server.setHandler(handlers);

        server.start();
        server.join();
    }
}

jetty file server effect

Jetty embedded servlet service effect

3 spring integration quartz

3.1 quartz.properties configuration file

# Scheduler instance name
org.quartz.scheduler.instanceName = quartz-scheduler-ram
# Scheduled task information storage method: memory
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#Number of scheduled task threads
org.quartz.threadPool.threadCount = 3

3.2 spring configuration file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Inform spring about the packages to be scanned when creating the container. The tags required for configuration are not in the constraints of beans, but a label named
    context namespace and constraints -->
    <context:component-scan base-package="com"/>
</beans>

3.3 quartz configuration

package com.primal.quartz.config;

import org.quartz.Trigger;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**
 * Author whh
 * Date 2023/10/11/ 21:44
 * <p></p>
 */
@ImportResource(value = {<!-- -->
//Add the task trigger to the spring container
        "classpath:configJobs/*ApplicationContext.xml"
})
@Configuration
public class QuartzConfig {<!-- -->


    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(AutowireCapableBeanFactory capableBeanFactory,ApplicationContext ctx){<!-- -->
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
        schedulerFactoryBean.setJobFactory(new AdaptableJobFactory(){<!-- -->
            @Override
            protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {<!-- -->
                Object jobInstance = super.createJobInstance(bundle);
                capableBeanFactory.autowireBean(jobInstance);
                return jobInstance;
            }
        });

        //Set trigger
        schedulerFactoryBean.setTriggers(ctx.getBeansOfType(CronTriggerFactoryBean.class).values().stream().map(CronTriggerFactoryBean::getObject).toArray(Trigger[]::new));
        schedulerFactoryBean.setAutoStartup(true);
        return schedulerFactoryBean;
    }
}

3.3 Job parent class is used to enhance subclasses

package com.primal.quartz.support;

import com.primal.util.AsyncManager;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * Author whh
 * Date 2023/10/11/ 19:56
 * <p></p>
 */
public abstract class JobSupport implements Job {<!-- -->

//Used for subclasses to implement specific task requirements
    public abstract void doExecute(JobExecutionContext jobExecutionContext);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {<!-- -->
        doExecute(jobExecutionContext);
        //Asynchronous logging
        AsyncManager.me().setDelay(1).submit(() -> {<!-- -->
            System.out.println("Log:" + Thread.currentThread().getName());
        });
    }
}

3.4 Asynchronous thread pool tool class

package com.primal.util;

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Author whh
 * Date 2023/10/11/ 19:59
 * <p></p>
 */
public class AsyncManager {<!-- -->

    //Delay execution time
    private long delay = 10;

    private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10,new DefaultThreadFactory());

    private static final AsyncManager me = new AsyncManager();


    private AsyncManager(){<!-- -->}

    public static AsyncManager me(){<!-- -->
        return me;
    }


    /**
     * Submit task
     * @param task
     */
    public void submit(Runnable task){<!-- -->
        this.executor.schedule(task,delay, TimeUnit.SECONDS);
    }


    /**
     * Set task delay execution time in seconds
     * @param delay
     * @return
     */
    public AsyncManager setDelay(long delay) {<!-- -->
        this.delay = delay;
        return this;
    }

    /**
     * Stop the thread pool
     */
    public void shutdown(){<!-- -->
        this.executor.shutdown();
    }


    /**
     * Thread pool factory
     */
    private static class DefaultThreadFactory implements ThreadFactory{<!-- -->
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {<!-- -->
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                    poolNumber.getAndIncrement() +
                    "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {<!-- -->
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

}

3.5 Business job subclass

package com.primal.job;

import com.primal.bean.Person;
import com.primal.quartz.support.JobSupport;
import org.quartz.JobExecutionContext;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;

public class TestJob extends JobSupport {<!-- -->
    @Autowired
    Person person;

    @Autowired
    Scheduler scheduler;

    @Override
    public void doExecute(JobExecutionContext jobExecutionContext) {<!-- -->

        System.out.println("Hello world..." + person);

        System.out.println("TestJob:" + scheduler);

        System.out.println("TestJob:" + Thread.currentThread().getName());
    }
}

3.6 xml configuration file corresponding to business job subclass

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Custom job tasks-->
    <bean id="TestJob" class="com.primal.job.TestJob"/>
    <!--Job tasks are managed in the JobDetailFactoryBean class-->
    <bean id="TestJobName" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="description" value="TestJob test"/>
        <property name="group" value="TestJobGroup"/>
        <property name="jobClass" value="com.primal.job.TestJob"/>
        <property name="durability" value="true"/>
        <property name="jobDataAsMap">
            <map>
                <entry key="JobName" value="TestJob"/>
                <entry key="RepeatTime" value="0"/>
                <entry key="RepeatInterval" value="10"/>
            </map>
        </property>
    </bean>
<!--Configure JobDetailFactoryBean into CronTriggerFactoryBean and specify cron expression-->
    <bean id="TestJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="TestJobName"/>
        <property name="cronExpression" value="*/3 * * * * ?"/>
        <!--Whether to make up for a missed run 0, 1 yes 2 no-->
        <property name="misfireInstruction" value="2"/>
    </bean>
   
</beans>