jfinal项目重构为springboot项目
eclipse插件安装
我们选择的插件是 Spring Tools 4 - for Spring Boot (aka Spring Tool Suite 4) 4.1.2.RELEASE
maven下载安装与eclipse配置
我采用的是 maven 3.6
configConstant/PropKit -> application.properties
例如,区分开发环境与正式环境
1 2 3 4 5 6 7
| spring.profiles.active=dev -- spring.profiles.active=pro -- debug=true
-- application.properties -- application-dev.properties -- application-pro.properties
|
常量配置
1 2 3 4 5 6
| #application.properties spring.redis.host= spring.redis.name= spring.redis.password= spring.redis.database= spring.redis.port=
|
java中取的配置文件的值
1 2 3 4 5 6 7 8 9 10
| @Value("${spring.redis.host}") private String redisHost; @Value("${spring.redis.name}") private String redisName; @Value("${spring.redis.password}") private String redisPassword; @Value("${spring.redis.port}") private String redisPort; @Value("${spring.redis.database}") private String redisDatabase;
|
路由配置 configRoute -> requestmapping
jfinal中的:
1 2 3
| public void configRoute(Routes me) { me.add("/hello", HelloController.class); }
|
修改为:
1 2 3 4 5 6 7 8 9 10 11 12
|
@RestController @RequestMapping("hello") public class HelloController extends ControllerExt{
@RequestMapping("addvote") public Object addvote(){ }
|
插件配置 configPlugin -> @Configuration
例如,如何使用jfinal的ActiveRecordPlugin插件操作数据库,原本jfinal的代码:
(其中包括Redis插件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
public void configPlugin(Plugins me) { DruidPlugin druidPlugin = createDruidPlugin(); me.add(druidPlugin);
ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin); me.add(arp); _MappingKit.mapping(arp);
DruidPlugin druidPlugin_database1 = createDruidPlugin_database1(); wallFilter = new WallFilter(); wallFilter.setDbType("mysql"); druidPlugin_mall.addFilter(wallFilter); druidPlugin_mall.addFilter(new StatFilter()); me.add(druidPlugin_mall); ActiveRecordPlugin arp_database1 = new ActiveRecordPlugin("database1",druidPlugin_mall); me.add(arp_mall); RedisPlugin RedisPlugin; if (PropKit.getBoolean("devMode", true)) RedisPlugin = new RedisPlugin(PropKit.get("redisname"), PropKit.get("redisserverip"), Integer.parseInt(PropKit.get("redisport")), 0, PropKit.get("redispw"), 2); else RedisPlugin = new RedisPlugin(PropKit.get("redisname"), PropKit.get("redisserverip"), Integer.parseInt(PropKit.get("redisport")), 0, PropKit.get("redispw"), 1);
me.add(RedisPlugin);
QuartzPlugin QuartzPlugin = new QuartzPlugin(); me.add(QuartzPlugin);
QuartzDynamicPlugin QuartzDynamicPlugin = new QuartzDynamicPlugin(); me.add(QuartzDynamicPlugin); }
|
在springboot中修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| @Bean public ActiveRecordPlugin initActiveRecordPlugin() {
druidPlugin = new DruidPlugin(url, username, password); WallFilter wallFilter = new WallFilter(); wallFilter.setDbType("mysql"); druidPlugin.addFilter(wallFilter); druidPlugin.start();
arp = new ActiveRecordPlugin(druidPlugin); arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED); _MappingKit.mapping(arp); arp.setShowSql(false);
arp.getEngine().setSourceFactory(new ClassPathSourceFactory()); arp.start();
redisPlugin = new RedisPlugin(redisName, redisHost, Integer.parseInt(redisPort), 0, redisPassword, Integer.parseInt(redisDatabase)); redisPlugin.start();
qdp = new QuartzDynamicPlugin(); qdp.start();
return arp; }
|
全局拦截器 configInterceptor -> WebMvcConfigurationSupport
涉及中文乱码问题
jfinal中的:
1 2 3 4 5 6 7 8
|
public void configInterceptor(Interceptors me) { me.add(new EncodingInterceptor()); me.add(new ExceptionInterceptor()); me.add(new AuthInterceptor()); }
|
Springboot中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| @Configuration public class InterceptorConfig extends WebMvcConfigurationSupport{
@Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new TestInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/error"); registry.addInterceptor(new AuthInterceptor()) .excludePathPatterns("/error"); super.addInterceptors(registry); }
@Bean public HttpMessageConverter<String> responseBodyConverter() { StringHttpMessageConverter converter = new StringHttpMessageConverter( Charset.forName("UTF-8")); return converter; }
@Override public void configureMessageConverters( List<HttpMessageConverter<?>> converters) { converters.add(responseBodyConverter());
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes); fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); converters.add(fastJsonHttpMessageConverter);
super.configureMessageConverters(converters);
}
@Override public void configureContentNegotiation( ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); } }
|
configHandler -> ResponseEntityExceptionHandler/ResponseBodyAdvice
涉及到格式化输出,统一的异常处理。
jfinal中:
1 2 3 4 5
|
public void configHandler(Handlers me) { }
|
springboot中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| @RestControllerAdvice public class GlobalResponseHandler extends ResponseEntityExceptionHandler implements ResponseBodyAdvice<Object> {
@Value("${spring.profiles.active}") private String active;
@Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return true; }
@Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { return body; }
@ResponseStatus(HttpStatus.OK) @ExceptionHandler(MyException.class) public <T> GlobalResponse<T> handleException(HttpServletRequest request, MyException e) { return GlobalResponse.fail(e.getMessage()); }
}
@ResponseStatus(HttpStatus.OK) @ExceptionHandler(Exception.class) @ResponseBody public <T> GlobalResponse<T> handleException(HttpServletRequest request, Exception e) { return GlobalResponse.fail("Error para"); }
}
|
事件监听
例如jfinal中有onStart()、onStop()系统启动完成之后以及系统关闭之前分别回调这两个方法,springboot中支持更好, 并且springboot支持自定义事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| @Configuration public class ApplicationEventListener implements ApplicationListener<ApplicationEvent>{
@Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationEnvironmentPreparedEvent) { System.out.println("初始化环境变量"); } else if (event instanceof ApplicationPreparedEvent) { System.out.println("初始化完成"); } else if (event instanceof ContextRefreshedEvent) { System.out.println("应用刷新"); } else if (event instanceof ApplicationReadyEvent) { System.out.println("应用已启动完成"); } else if (event instanceof ContextStartedEvent) { System.out.println("应用启动,需要在代码动态添加监听器才可捕获 "); } else if (event instanceof ContextStoppedEvent) { System.out.println("应用停止"); System.out.println("关闭数据库与redis连接"); ActiveRecordPluginConfig.qdp.stop(); ActiveRecordPluginConfig.arp.stop(); ActiveRecordPluginConfig.druidPlugin.stop(); ActiveRecordPluginConfig.redisPlugin.stop(); } else if (event instanceof ContextClosedEvent) { System.out.println("应用关闭"); System.out.println("关闭数据库与redis连接"); ActiveRecordPluginConfig.qdp.stop(); ActiveRecordPluginConfig.arp.stop(); ActiveRecordPluginConfig.druidPlugin.stop(); ActiveRecordPluginConfig.redisPlugin.stop(); } else { System.out.println("应用的其他操作"); } } }
|
Controller 变更
注解@RestController/@Controller表示此类为Controller
RequestMapping注解标识访问路径和方法等
1 2 3 4 5 6 7 8 9 10 11 12
| @RestController @RequestMapping("hello") public class HelloController extends ControllerExt{
@RequestMapping("sayhi") public Object sayhi(String para){ return "hello" }
|
日志配置
springboot默认的是logback,若替换为jfinal使用的logkit需要:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion>
</exclusions> </dependency>
... <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>slf4j-api</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>slf4j-nop</groupId> <artifactId>slf4j-nop</artifactId> <version>1.7.21</version> <scope>provided</scope> </dependency>
|
事务处理 @Before(Tx.class)
//自定义注解
参考链接 JFinal ActiveRecordPlugin插件事物交给Spring管理
热部署配置方法
pom.xml配置热部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ...
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
...
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build>
...
|
@Bean
- Spring容器管理的Java对象称之为Bean。
- 依赖注入其主要的作用,可以说就是维护Spring容器创建的Bean之间的依赖关系,简单来说就是一个bean(假定名为A)持有另一个Bean(假定名为B)的引用作为成员变量b,则由Spring容器自动将B赋值给A的成员变量b
定时任务
根据检索与尝试结果,springboot自带的定时任务功能可以较好的支持固定不变的定时任务,例如固定执行频率,固定执行频率+初次延迟,cron表达式
1 2 3 4 5
| @Scheduled(fixedRate = 1000) @Scheduled(fixedDelay = 1000) @Scheduled(fixedRate = 1000, initialDelay = 5000) @Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")
|
因此,动态定时任务需要结合Quartz插件。资料:csdn博客