KuaFu MVC 开发框架介绍夸父 Java Web MVC开发框架,提供极简快速开发。 框架要求安装教程新建一个maven项目 pom.xml中引入框架jar包 <dependency> <groupId>tech.yixiyun.framework</groupId> <artifactId>kuafu-mvc</artifactId> <version>0.0.7</version> <type>jar</type></dependency> pom.xml中还需要配置下build <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>你的jdk版本,不低于11</source> <target>你的jdk版本,不低于11</target> <encoding>UTF-8</encoding> <compilerArgument>-parameters</compilerArgument> </configuration> </plugin> </plugins> </build> 创建一个类,写一个main方法,启动项目 public class Main { public static void main(String[] args) { TomcatStarter.start(); }}
快速开始创建一个Controller类 import tech.yixiyun.framework.kuafu.controller.BaseController;import tech.yixiyun.framework.kuafu.view.View;/** * 演示Demo * @author Yixiyun * @version 1.0 * @date 2021-05-16 15:00 */public class DemoController extends BaseController { public View add(){ return json("name", "zhangsan", "age", 14); }} 重启下应用,访问 localhost:80/demo/add,就会看到浏览器显示一个json结构的数据了 按照正常的web项目结构,在webapp文件夹下,创建一个hello.jsp 文件 <%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Demo</title></head><body> Hello Kuafu</body></html> 到DemoController中写一个新方法 public View hello() { return jsp("hello"); } 重新下应用,访问 localhost:80/demo/hello,就会发现页面被打开了 框架会自动识别Controller组件,识别的依据就是类上或父类身上是否有@Controller注解。识别为Controller组件后,框架会继续分析它的方法,只要方法是public修饰的,并且返回类型是View的,框架就会自动生成路由映射。 路由对应的url生成规则是: - 如果方法上有@Route注解,就以注解的值作为url
- 否则就以 “/基础路径 / 方法名” 作为url。基础路径由@Controller注解决定,BaseController类上有一个默认的@Controller("(a)(!Controller)") (这是一个特殊语法,更多说明请查看@Controller注解的注释),代表类名去掉"Controller"单词后,剩下字符串的第一个字符小写。所以DemoController因为继承了BaseController,它的基础路径就是 "demo"。它的 add方法映射的路由url 就是 "/demo/add",浏览器访问“/demo/add”就会由这个方法处理
在刚写的hello方法上加一个@Route("/") @Route("/")public View hello() { return jsp("hello");} 现在重启下应用,访问 localhost:80/,就会发现,hello页面被打开了 (注意webapp目录下不要存在index.jsp、index.html等欢迎页) 在 DemoController 类上加一个 @Controller("abc") @Controller("abc")public class DemoController extends BaseController { ...} 访问 localhost:80/abc/add,就会发现页面显示json数据了 BaseController 提供了很多方便的的方法,例如 - json(key,value, key,value...) 生成一个json结果的响应,json结果根据传入的键值对生成。
- json(data) 由传入的一个对象生成json响应
- jsonSuccess(data) 生成一个{state: SUCCESS, data: data}结构的json响应
- jsonFail(msg) 生成一个 {state: ERROR, msg: msg}结构的json响应
- jsp(path) 跳到一个jsp页面,只需要传入jsp在webapp文件夹中的相对路径,可以忽略 .jsp后缀
- dispatch(path) 转向到一个地址
- redirect(path) 重定向到一个地址
- text(content) 返回一个普通文本响应
- ftl(path) 跳到一个freemarker页面
- setAttr(key,value) 向request中绑定数据
- image(byte[]) 返回一个图片
- download(filename, byte[]) 返回一个文件下载流
- getRequest() 获取请求对象
- getResponse() 获取响应对象
- getSession() 获取session对象
写一个Service 业务类 /** * 演示Service * @author Yixiyun * @version 1.0 * @date 2021-05-15 13:22 */public class DemoService extends BaseService { public void add() { LOGGER.info("执行了add方法"); }} 任何类身上有@Service注解,或者父类身上有@Service注解,就会被识别为Service组件。 注意这里我们使用了LOGGER 日志工具类,它基于log4j2实现,做了优化,无需每个类声明一个静态变量,都用它提供的静态方法记录即可。在框架的默认配置中,它只显示info以上级别的信息,并且输出记录到控制台以及日志文件中。后面会讲到如何修改配置 在DemoController中注入DemoService实例 /** * 演示Demo * @author Yixiyun * @version 1.0 * @date 2021-05-16 15:00 @Controller("abc")*/public class DemoController extends BaseController { private DemoService demoService; public View add() { //在这里调用一下demoService的方法 demoService.add(); return json("name", "zhangsan", "age", 14); } ...} 重新在浏览器访问下 demo/add,就会发现控制台打印了日志 只要是框架组件,就会自动识别为Bean,并自动注入,并默认以单例模式实例化。 如果其他类想被纳入Bean管理,只需要类身上加上@Bean注解,注解可以控制实例化方式和是否懒加载。之后就可以通过BeanContext获取实例了。它也会被其他Bean类自动执行依赖注入。 接下来开始熟悉配置相关的,我们首先尝试修改一下tomcat的启动端口 在resources文件夹下新建一个名为 app-config.json 的文件 然后在文件中,按照 json 的写法写上 { "system": { "server": { "port":8080 } }} 重启应用,就会发现控制台提示 ******** ^^^ 应用启动成功 ^^^ 启动地址:http://localhost:8080/ ********
对于一个项目来说,一般会有两个配置文件,一个是生产环境的,一个是开发环境的。刚才那个 app-config.json 正常来说对应的就是生产环境配置文件,当然你也可以两个环境下都用它。那么如果你想为开发环境另弄一个配置文件怎么办呢?只需要新建一个 app-config-dev.json 配置文件就行了,项目打包时,注意把它移除。一旦框架检测到有 app-config-dev.json,就会优先加载它,忽略 app-config.json.接下来你我们尝试配置一个开发环境的配置文件,在这个配置里,我们干两个事,一个是tomcat端口改为9090,另一个是将日志的记录级别改为DEBUG,并且让日志不输出到文件,只在控制台打印。 { "system": { "server": { "port":8080 }, "run": { "logger": { "configuration": { "loggers": { "logger": [{ "name": "kuafuLogger", "level": "debug", "additivity": "false", "AppenderRef": [ {"ref": "dev_console"} ] }] } } } } }} 你可能会觉得这个日志的配置怎么这么麻烦,这个是log4j2 日志框架官方提供的 json 配置方式,框架本身提供的预配置 其实已经不需要怎么改了,如果就是有特别需要,请自行查阅 log4j2 官方文档进行自定义配置,但一定要注意 ** logger的name 一定不要改名字,除非你不想用框架提供的LOGGER工具类 ** 回到配置文件上,你可能会有疑问,配置为什么要这么写,规则是什么?其实很简单,框架提供了一个预配置 default-config.json 文件,你只需要按照预配置的 json结构,在你的配置文件中去重写你想改变的配置项即可。框架会用 你的配置去覆盖 预配置。下面是default-config.json 的内容 { "system": { //server相关配置 "server": { "port": 80, "contextPath": "/", "connectionTimeout": "60000", //接收到请求后,等待处理的超时时间 "listen": "*", //如果服务器有多个网卡,而应用只需要监听某一个网卡的请求,就在这里配置上网卡的hostname或者ip。*代表服务器所有网卡 "compress": "off", //是否对文本进行压缩,三个值可用,on、off、force(强制) "protocol": "HTTP/1.1", //暂时支持 HTTP/1.1 、AJP/1.3两种协议 HTTP/2目前未看到明显性能提升,且要求较多 "errorPages": { //错误页面,一般只对嵌入式服务器有效 "500": "/500.ftl", //发生500时显示的页面 "404": "/404.ftl" //发生404时显示的页面 } }, //启动阶段 "boot": { "tomcat": { //针对Tomcat内嵌服务器的启动阶段的一些配置 "scanJars": false, //tomcat启动时是否扫描所有jar包,用于TLD和web-fragment扫描,这会增加启动时间 "uriEncoding": "UTF-8", "minThread": 10, //tomcat处理请求的最少线程数 "maxThread": 200, //tomcat处理请求的并发线程数,超过的请求会被放入等待队列中 "maxWaitCount": 100 //最多可等待的请求数,超过后会拒绝请求 }, "preHandler": "" //前置处理器,在启动工作开始前执行的工作 }, //运行阶段 "run": { //开发模式还是生产模式 "mode": "dev", //是否启用热加载,需要配合jrebel使用 "hotdeploy": false, //是否启用应用监控,用于实时查看服务器和应用的运行状态 "monitor": { "enable": true }, //请求相关 "request": { //是否支持跨域 "cors": true, //可以请求的资源路径 "resources": { //只有匹配这些规则的请求,才会被框架处理,否则交由Servlet容器处理,语法同Filter的url-pattern语法 "include": ["/*"], //在include的基础上,匹配这些规则的请求,将跳过拦截器处理,直接请求。语法同Filter的url-pattern语法 "exclude": ["*.ico"] }, "session": { "manager": "tech.yixiyun.framework.kuafu.controller.session.ServletSessionManager" //用于获取Session实例的类,需要实现ISessionManager接口 }, "upload": { "singleMaxSize": 51200, //上传的单文件最大大小,单位K,默认50M "totalMaxSize": 51200, //上传时单次请求最大大小,单位K,默认50M "savePath": "/upload/{date:yyyyMMdd}/{uuid}.{suffix}", //上传文件的默认保存位置,以webroot位置为基准 "notAllowSuffix": [ //不允许上传的文件类型 //不允许上传的文件类型 ".exe", ".bat", ".sh", ".dll", ".jsp", ".php", ".jar", ".class", ".js", ".asp", ".jspx", ".html", ".htm", ".shtml", ".ftl", ".py" ] } }, //模板相关 "template": { "freemarker": { //freemarker模板, "config": { //配置项参考文档:https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setSetting-java.lang.String-java.lang.String- "ContentType": "text/html; charset=UTF-8", "TemplatePath": "[/,classpath:templates/]", "locale": "zh_CN", "template_exception_handler": "rethrow", "date_format": "yyyy-MM-dd", "time_format": "HH:mm", "datetime_format": "yyyy-MM-dd HH:mm", "template_update_delay": "2000",//单位毫秒,默认5000,开发环境设置低一点,生产环境建议设高 "default_encoding": "UTF-8", "number_format": "0.###", "incompatible_improvements": "2.3.30" } } }, //响应相关 "response": { }, //数据库相关 "db": { //事务相关 "transaction": { //自动开启事务的方法名前缀 "autoOpenPrefix": ["add","modify","del","update","do","save", "create", "alter", "insert"], //默认的事务隔离级别,参考TransactionLevel枚举类中的定义 "defaultLevel": "REPEATABLE_READ", //事务执行超时警告,一旦一个事务执行时间超过设定的毫秒值,就打印警告语句 "timeoutWarning": 1000 } }, //日志相关 "logger": { "default": "kuafuLogger", //默认使用的记录器 "configuration": { //配置参考log4j官网,链接http://logging.apache.org/log4j/2.x/manual/configuration.html#JSON "status": "error", "name": "kuafu", "appenders": { "appender": [ { "type": "Console", "name": "console", "PatternLayout": { "pattern": "%-d{MM-dd HH:mm:ss} [%p]-[%C{1}.%M()]: %m %n" } }, { //开发环境用的打印,可以显示颜色 "type": "Console", "name": "dev_console", "PatternLayout": { "pattern": "%-d{MM-dd HH:mm:ss} [%highlight{%-5level}{INFO=Magenta, TRACE=White, DEBUG=Blue}]-[%highlight{%C{1}.%M()}{INFO=Magenta, TRACE=White, DEBUG=Blue}]: %highlight{%m%n}{INFO=Magenta, TRACE=White, DEBUG=Blue}" } }, { "type": "RollingFile", "name": "file", "fileName": "logs/run.log", //日志文件保存路径 "filePattern" : "logs/%d{MM-dd}_%i.log.gz", //分割后的命名规则 "PatternLayout": { "pattern": "%-d{MM-dd HH:mm:ss} [%p]-[%C{1}.%M()]: %m %n" }, "Policies": { "CronTriggeringPolicy": { "schedule": "0 0 0 * * ? *", //日志每天零点分割一次 "evaluateOnStartup": true }, "SizeBasedTriggeringPolicy": { "size": "60M" } //单个日志文件超过60M也分割一次 }, "DefaultRolloverStrategy": { "max": 10 //所有的日志文件最多保留10个 } } ] }, "loggers": { "logger": [{ "name": "kuafuLogger", "level": "info", "additivity": "false", "AppenderRef": [ //默认会向这两个地方写入,上线后,可以不向console写入 { "ref": "console" }, { "ref": "file" } ] }], "root": { "level": "info", "AppenderRef": { "ref": "console" } } } } } }, "stop": { //系统停止运行阶段 } }} 你应该会注意到,框架依赖的配置都写在了 system 配置项下,为了和你的项目相关的配置区分开,极力建议你,不要把你的 项目相关的配置写在 system 下,而应该另外建一个 键,例如 app 或者 project { "system": { //这里都是框架依赖的配置项 }, "app": { //这里写与你项目相关的配置,例如数据库配置、缓存配置等等 }} 为了方便你从配置文件中读取配置,这里提供了一个AppConfig工具类,它可以根据 key (大部分配置项的key路径我们都在ConfigKey中定义了) 从 所有生效的配置文件中提取配置数据,并转成对应结构,例如 List<String> prefixs = AppConfig.getAsStringList("system.run.db.autoOpenPrefix");Integer port = AppConfig.getAsInt("system.server.port");HashMap<String, String> errorMap = AppConfig.getAsStringMap(ConfigKey.SERVER_ERRORPAGES); 接下来我们创建一个实体类 package tech.yixiyun.demo.user;import tech.yixiyun.framework.kuafu.domain.BaseDomain;import java.util.Date;/** * 用户实体类 * * @author Yixiyun * @version 1.0 * @date 2021-05-17 14:20 */public class User extends BaseDomain { //唯一标识 private Integer id; //姓名 private String name; //爱好 private String favors[]; //性别,true代表男,false代表女 private Boolean gender; //出生年月日 private java.sql.Date birthday; //记录的创建时间 private Date createTime; //getter setter 这里我就不写了,你一定要写上} 创建完,我们来看一下Controller方法如何自动解析和转换请求参数。回到 hello.jsp 中,我们构建一个表单。 <%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Demo</title> <style> form { display: flex; flex-direction: column; } </style></head><body><form action="/demo/add" method="post"> <label > 姓名: <input type="text" name="user.name" /> </label>
|
请发表评论