java based spring configuration
The java configuration uses java classes , as follows:
@Configuration @EnableAutoConfiguration @ComponentScan(basePackages = {"com.cherrypicks.hsbcpayme.cs.controller", "com.cherrypicks.hsbcpayme.service", "com.cherrypicks.hsbcpayme.dao"}) public class WebConfig extends WebMvcConfigurerAdapter { // dispatcher Servlet, the servlet that intercepts the request to dispatch the request @Bean public DispatcherServlet dispatcherServlet() { return new DispatcherServlet(); } // filter @Bean public FilterRegistrationBean characterEncodingFilter(@Value("${character.encoding}") final String characterEncoding) { final CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding(characterEncoding); characterEncodingFilter.setForceEncoding(true); final FilterRegistrationBean reg = new FilterRegistrationBean(); reg.setFilter(characterEncodingFilter); reg.addUrlPatterns("/*"); return reg; } @Bean public FilterRegistrationBean corsFilter(@Value("*") final String allowedOrigins, @Value("false") final String allowCredentials) { return new FilterRegistrationBean(new CorsFilter(allowedOrigins, allowCredentials)); } @Bean public FilterRegistrationBean restfulFilter() { final FilterRegistrationBean reg = new FilterRegistrationBean(); reg.setFilter(new RESTfulFilter()); reg.addUrlPatterns("/*"); return reg; } // interceptor @Bean public SessionInterceptor sessionInterceptor() { return new SessionInterceptor(); } @Bean public IpRangeInterceptor ipRangeInterceptor() { return new IpRangeInterceptor(); } @Bean public PermissionCheckInterceptor permissionCheckInterceptor() { return new PermissionCheckInterceptor(); } @Override public void addInterceptors(final InterceptorRegistry registry) { // check userId & accessToken registry.addInterceptor(sessionInterceptor()) .addPathPatterns("/*") .excludePathPatterns("/login") .excludePathPatterns("/pageNotFound") .excludePathPatterns("/error") .excludePathPatterns("/checkEmail") .excludePathPatterns("/healthcheck"); registry.addInterceptor(ipRangeInterceptor()) .addPathPatterns("/*") .excludePathPatterns("/pageNotFound") .excludePathPatterns("/error"); registry.addInterceptor(permissionCheckInterceptor()) .addPathPatterns("/*") .excludePathPatterns("/login") .excludePathPatterns("/logout") .excludePathPatterns("/pageNotFound") .excludePathPatterns("/error"); } }
@Configuration: declared as configuration
@EnableAutoConfiguration: Automatically loads all beans needed by the application - this depends on what Spring Boot looks for in the classpath.
@Bean: the bean to load
@ComponentScan(basePackages = {"com.cherrypicks.hsbcpayme.cs.controller",
"com.cherrypicks.hsbcpayme.service",
"com.cherrypicks.hsbcpayme.dao"})
Declare from which packages the class was scanned and assembled to the bean
When loading a bean, you can set the dispatcher servlet, filter, and interceptor according to the implementation class of the class.
java database link configuration
@Configuration @EnableTransactionManagement public class DataSourceConfig { @Value("${spring.datasource.driverClassName}") private String driverClassName; @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.username}") private String userName; @Value("${spring.datasource.pwd}") private String password; @Value("${srping.datasource.initialSize}") private Integer initialSize; @Value("${spring.datasource.maxActive}") private Integer maxActive; @Autowired private EncryptionService encryptionService; // system data source @Bean @Primary public DataSource dataSource() throws Exception { return tomcatPoolingDataSource(); } @Bean public JdbcTemplate jdbcTemplate() throws Exception { return new JdbcTemplate(dataSource()); } private DataSource tomcatPoolingDataSource() throws Exception { final org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(); dataSource.setDriverClassName(driverClassName); dataSource.setUrl(url); dataSource.setUsername(userName); dataSource.setPassword(encryptionService.cherrypicksDecryption(password)); dataSource.setInitialSize(initialSize); // The number of initial connections created when the connection pool starts (default value is 0) dataSource.setMaxActive(maxActive); // The maximum number of simultaneous connections in the connection pool dataSource.setMaxIdle(5); // The maximum number of idle connections in the connection pool, the excess idle connections will be released, if set to a negative number, it means unlimited dataSource.setMinIdle(0); // The minimum number of idle connections in the connection pool, below this number a new connection will be created dataSource.setMaxWait(60000); // Maximum waiting time. When there is no available connection, the connection pool will wait for the maximum time for connection release. If the time limit is exceeded, an exception will be thrown. If -1 is set, it means infinite waiting dataSource.setRemoveAbandonedTimeout(180); // When the time limit is exceeded, useless (abandoned) connections are recycled dataSource.setRemoveAbandoned(true); // Whether to recycle useless connections (abandoned) after removeAbandonedTimeout is exceeded dataSource.setTestOnBorrow(true); dataSource.setTestOnReturn (true); dataSource.setTestWhileIdle(true); dataSource.setValidationQuery("SELECT 1"); dataSource.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30); // The interval for checking invalid connections is set to 30 minutes return dataSource; } }
Tomcat's connection pool is used here, and it is added to JdbcTemplate after connection.
Java configuration for Scheduler
@Configuration @EnableAutoConfiguration @ComponentScan(basePackages = {"com.cherrypicks.hsbcpayme.cs.scheduler"}) public class SchedulerConfig { @Value("${check.email.cron:}") private String checkCustomerEmailCron; @Value("${user.profile.report.cron}") private String userProfileReportCron; @Autowired private DataSourceConfig dataSourceConfig; @Autowired private ResourceLoader resourceLoader; @Bean public AutowiringSpringBeanJobFactory jobFactory() { return new AutowiringSpringBeanJobFactory(); } @Bean public JobDetailFactoryBean checkCustomerEmailJob(){ final JobDetailFactoryBean factory = new JobDetailFactoryBean(); factory.setJobClass(CheckCustomerEmailScheduler.class); factory.setDurability(true); return factory; } @Bean public JobDetailFactoryBean userProfileReportJob(){ final JobDetailFactoryBean factory = new JobDetailFactoryBean(); factory.setJobClass(UserProfileReportScheduler.class); factory.setDurability(true); return factory; } @Bean public CronTriggerFactoryBean checkCustomerEmailTrigger(){ final CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean(); stFactory.setJobDetail(checkCustomerEmailJob().getObject()); stFactory.setCronExpression(checkCustomerEmailCron); stFactory.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); return stFactory; } @Bean public CronTriggerFactoryBean userProfileReportTrigger(){ final CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean(); stFactory.setJobDetail(userProfileReportJob().getObject()); stFactory.setCronExpression(userProfileReportCron); stFactory.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); return stFactory; } @Bean public SchedulerFactoryBean schedulerFactoryBean() throws Exception { final SchedulerFactoryBean scheduler = new SchedulerFactoryBean(); final Resource resource = resourceLoader.getResource("classpath:quartz.properties"); scheduler.setConfigLocation(resource); scheduler.setDataSource(dataSourceConfig.quartzDataSource()); // scheduler.setTransactionManager(dataSourceConfig.quartzTransactionManager()); // This name is persisted as SCHED_NAME in db. for local testing could change to unique name to avoid collision with dev server scheduler.setSchedulerName("csQuartzScheduler"); // Will update database cron triggers to what is in this jobs file on each deploy. Replaces all previous trigger and job data that was in the database. scheduler.setOverwriteExistingJobs(true); scheduler.setAutoStartup(true); scheduler.setJobFactory(jobFactory()); scheduler.setJobDetails(checkCustomerEmailJob().getObject(), userProfileReportJob().getObject()); scheduler.setTriggers(checkCustomerEmailTrigger().getObject(), userProfileReportTrigger().getObject()); return scheduler; } }
Notice
1. Each job should define a detail (which class to call, other details), a trigger (cycle, which detail to call, time zone)
2. When defining scheduler, remember to set dataSource, name, properties, detail, trigger
java configuration of thread pool
@Configuration public class ThreadPoolConfig { @Bean public ThreadPoolTaskExecutor taskExecutor() { final ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor(); pool.setCorePoolSize(5); pool.setMaxPoolSize(10); pool.setQueueCapacity(50); pool.setWaitForTasksToCompleteOnShutdown(true); pool.setKeepAliveSeconds(300); return pool; } }
The key is the class ThreadPoolTaskExecutor
java configuration for redis connection
@Configuration public class RedisConfig { @Value("${spring.redis.database}") private int database; @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.pwd}") private String password; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.pool.max-active}") private int poolMaxActive; @Value("${spring.redis.pool.max-wait}") private int poolMaxWait; @Value("${spring.redis.pool.max-idle}") private int poolMaxIdle; @Value("${spring.redis.pool.min-idle}") private int poolMinIdle; @Autowired private EncryptionService encryptionService; @Bean public RedisConnectionFactory jedisConnectionFactory() throws Exception { final JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal (poolMaxActive); poolConfig.setMaxIdle (poolMaxIdle); poolConfig.setMaxWaitMillis (poolMaxWait); poolConfig.setMinIdle(poolMinIdle); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnCreate (true); poolConfig.setTestWhileIdle (true); final JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig); jedisConnectionFactory.setDatabase(database); jedisConnectionFactory.setHostName(host); if (StringUtils.isNotBlank(password)) { jedisConnectionFactory.setPassword(encryptionService.cherrypicksDecryption(password)); } jedisConnectionFactory.setPort(port); jedisConnectionFactory.setTimeout(timeout); // Other configuration, can be extended again return jedisConnectionFactory; } }
java configuration of javaMailSender
@Configuration public class MailConfig { @Value("${spring.mail.host}") private String host; @Value("${spring.mail.port}") private int port; @Value("${spring.mail.properties.mail.smtp.auth}") private boolean auth; @Value("${spring.mail.properties.mail.smtp.starttls.enable}") private boolean starttlsEnable; @Value("${spring.mail.properties.mail.smtp.starttls.required}") private boolean starttlsRequired; @Value("${spring.mail.username}") private String username; @Value("${spring.mail.pwd}") private String password; @Autowired private EncryptionService encryptionService; @Bean public JavaMailSender javaMailSender() throws Exception { final JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); final Properties mailProperties = new Properties(); mailProperties.put("mail.smtp.auth", auth); mailProperties.put("mail.smtp.starttls.enable", starttlsEnable); mailProperties.put("mail.smtp.starttls.required", starttlsRequired); mailSender.setJavaMailProperties(mailProperties); mailSender.setHost(host); mailSender.setPort(port); // mailSender.setProtocol(protocol); mailSender.setUsername(username); if (StringUtils.isNotBlank(password)) { mailSender.setPassword(encryptionService.cherrypicksDecryption(password)); } mailSender.setDefaultEncoding(Constants.UTF8); return mailSender; } }