-
Notifications
You must be signed in to change notification settings - Fork 28
YMP框架快速搭建手册
本手册将阐述如下内容:
- 如何基于YMP框架搭建WEB应用程序;
- 如何添加事件和异常处理器;
- 如何开发、配置控制器和视图;
- 如何实现控制器参数绑定;
- 如何实现参数验证;
- 如何实现拦截器;
- 如何时创建数据库实体;
- 如何创建和配置存储器;
- 如何扩展插件模块;
- 插件的开发流程;
-
新建Eclipse工程
STEP 1:选择”Web”->”Dynamic Web Project”,点击”Next”按钮;
STEP 2:键入工程名称并调整相关设置,点击”Finish”按钮完成;
-
调整源码包和编译路径
STEP 1:打开新建工程”ympweb-demo”的属性设置,将”Default output folder”路径修改为与下图相同的地址:
STEP 2:移除已存在的”src”源码包,并添加”src/conf”和”src/core”两个源码包路径,修改结果如下图所示,点击”Ok”保存设置;
FINAL:工程创建完成后,其目录结构如下图所示,其中”src/conf”目录用于存放相关配置文件,”src/core”目录用于存放相关代码;
-
添加依赖包,框架所需依赖包复制到”WEB-INF/lib”目录下并刷新工程,如下图所示;
-
配置并初始化YMP框架
STEP 1:修改”web.xml”文件
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ympweb-demo</display-name> <listener> <listener-class>net.ymate.platform.mvc.web.WebMvcEventListener</listener-class> </listener> <filter> <filter-name>ymatemvc</filter-name> <filter-class>net.ymate.platform.mvc.web.DispatcherFilter</filter-class> </filter> <filter-mapping> <filter-name>ymatemvc</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
STEP 2:添加”src/conf/ymp-conf.properties”文件
ymp.dev_model=true ymp.module_list=configuration|logger|jdbc|webmvc ymp.modules.configuration=net.ymate.platform.module.ConfigModule ymp.modules.logger=net.ymate.platform.module.LogModule ymp.modules.webmvc=net.ymate.platform.module.WebMvcModule ymp.modules.jdbc=net.ymate.platform.module.JdbcModule ymp.configs.configuration.config_home=${root} ymp.configs.logger.name=default ymp.configs.logger.level=debug ymp.configs.logger.xml_cfg_file=${user.dir}cfgs/log4j.xml ymp.configs.logger.output_path=${user.dir}logs/ ymp.configs.logger.allow_print_console=true ymp.configs.webmvc.base.locale=zh_CN ymp.configs.webmvc.base.charset_encoding=UTF-8 ymp.configs.webmvc.base.view_path=/WEB-INF/templates/ ymp.configs.webmvc.base.restful_model=true ymp.configs.jdbc.base.show_sql=true ymp.configs.jdbc.base.table_prefix=ymweb_ ymp.configs.jdbc.base.datasource_default=default ymp.configs.jdbc.base.datasource_list=default ymp.configs.jdbc.datasource.default.driver_class=com.mysql.jdbc.Driver ymp.configs.jdbc.datasource.default.connection_url=jdbc:mysql://localhost:3306/ymateweb_v2?useUnicode=true&characterEncoding=UTF-8 ymp.configs.jdbc.datasource.default.username=root ymp.configs.jdbc.datasource.default.password=admin
STEP 3:创建配置体系目录并添加日志配置文件
添加”src/conf/commons-logging.properties”文件,内容如下:
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
在”WEB-INF”目录下添加”cfgs”目录并添加”log4j.xml”文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "/org/apache/log4j/xmllog4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="RootFileAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="${LOGS_DIR}/logger-root.log" /> <param name="Append" value="true" /> <param name="DatePattern" value="'.'yyMMddHH" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss,SSS}] [%p] [%l] %x - %m%n" /> </layout> </appender> <appender name="FileAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="${LOGS_DIR}/logger-default.log" /> <param name="Append" value="true" /> <param name="DatePattern" value="'.'yyMMddHH" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%m%n" /> </layout> </appender> <logger name="default"> <level value="debug" /> <appender-ref ref="FileAppender" /> </logger> <root> <priority value ="debug"/> <appender-ref ref="RootFileAppender"/> </root> </log4j:configuration>
STEP 4:调整后,整个工程结构如下图所示:
STEP 5:部署到Tomcat容器并启动,检查日志输出,确认框架配置是否成功
-
STEP 1:创建WebErrorHandler类并实现IWebErrorHandler接口
public class WebErrorHandler implements IWebErrorHandler { public void onError(Throwable e) { Logs.debug("", e); } public IView onConvention(String requestMapping) { return null; } public IView onValidation(Set<ValidateResult> results) { return null; } }
-
STEP 2:创建WebEventHandler类并实现IWebEventHandler接口
public class WebEventHandler implements IWebEventHandler { public void onInitialized() { } public void onDestroyed() { } public void onRequestDestroyed(ServletRequestEvent event) { } public void onRequestInitialized(ServletRequestEvent event) { } public void onSessionCreated(HttpSessionEvent event) { } public void onSessionDestroyed(HttpSessionEvent event) { } public void onShutdown(ServletContextEvent event) { } public void onStartup(ServletContextEvent event) { } }
-
STEP 3:修改”src/conf/ymp-conf.properties”文件,添加相关配置
ymp.configs.webmvc.base.event_handler_class=net.ymate.web.demo.WebEventHandler ymp.configs.webmvc.base.error_handler_class=net.ymate.web.demo.WebErrorHandler
-
STEP 4:至此,框架的事件和异常处理器添加完成,整个工程结构如下图所示:
-
STEP 1:修改”src/conf/ymp-conf.properties”文件,添加控制器包扫描路径配置
ymp.configs.webmvc.base.controller_packages=net.ymate.web.demo.controller
-
STEP 2:创建控制器包路径和类对象
@Controller public class DemoController { @RequestMapping("hello") @RequestMethod public IView hello() { return new TextView("Hello, world!"); } }
-
STEP 3:部署分发到Tomcat容器并启动,通过浏览器访问:
-
方式一:绑定请求参数
-
在控制器中添加如下代码
@RequestMapping("/hello/sayHi") @RequestMethod public IView sayHi(@RequestParam String name) { return new TextView("Hi, " + name); }
-
部署分发到Tomcat容器并启动,通过浏览器访问:
-
-
方式二:绑定URL参数
-
在控制器中添加如下代码
@RequestMapping("/hello/sayHi/{name}") @RequestMethod public IView sayHi2(@PathVariable String name) { return new TextView("Hi, " + name); }
-
部署分发到Tomcat容器并启动,通过浏览器访问:
-
-
STEP 1:在控制器中添加如下代码
@RequestMapping("/valid/{name}/{age}") @RequestMethod @Validation(fullMode = true) public IView paramValidator( @Validate({ @ValidateRule(RequriedValidator.NAME), @ValidateRule(value = LengthValidator.NAME, params = { "min=3", "max=6" }) }) @PathVariable String name, @Validate({ @ValidateRule(RequriedValidator.NAME), @ValidateRule(value = NumericValidator.NAME, params = { "min=18", "max=20" }) }) @PathVariable String age) { return new TextView(""); }
-
STEP 2:通过浏览器访问http://localhost:8080/ympweb-demo/valid/lz/13,控制台将抛出如下异常:
2013-07-28 23:31:44.415[调试][18:WebErrorHandler.onError:44] - 以下是异常(net.ymate.platform.validation.ValidationException:[ { fieldName : 'age', message : '长度必须介于18和20之间' }, { fieldName : 'name', message : '长度必须介于3和6之间' }])的堆栈信息: at net.ymate.platform.mvc.support.RequestExecutor.execute(RequestExecutor.java:125) at net.ymate.platform.mvc.web.DispatcherFilter.doFilter(DispatcherFilter.java:125) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619)
-
STEP 3:若希望将验证信息输出到浏览器,可以通过WebErrorHandler类中onValidation方法实现,代码如下:
public IView onValidation(Set<ValidateResult> results) { StringBuilder _sb = new StringBuilder(); for (ValidateResult _result : results) { _sb.append(_result.getMessage()).append("<br/>"); } return new TextView(_sb.toString()); }
-
STEP 4:再次通过浏览器访问:
-
STEP 1:创建拦截器类,用于拦截年龄大于19岁,代码如下:
@Bean public class DemoFilter implements IFilter { public IView doFilter(RequestMeta meta, String params) throws Exception { Integer _age = Integer.parseInt(StringUtils.defaultIfEmpty((String) WebContext.getContext().get("age"), "0")); if (_age > 19) { return new TextView("年龄大于19岁,被拦截"); } return null; } }
-
STEP 2:将@Filter注解添加到控制器方法,修改后代码如下:
@RequestMapping("/valid/{name}/{age}") @RequestMethod @Validation(fullMode = true) @Filter(DemoFilter.class) public IView paramValidator( @Validate({ @ValidateRule(RequriedValidator.NAME), @ValidateRule(value = LengthValidator.NAME, params = { "min=3", "max=6" }) }) @PathVariable String name, @Validate({ @ValidateRule(RequriedValidator.NAME), @ValidateRule(value = NumericValidator.NAME, params = { "min=18", "max=20" }) }) @PathVariable int age) { return new TextView("你好," + name + ", 你今年" + age + "岁了!"); }
-
STEP 3:再次通过浏览器分别访问:
-
STEP 1:创建数据库表,假设现在存在如下表结构:
-
STEP 2:为了方便日后对实体类进行扩展,先创建实体基类对象,代码如下:
public abstract class BaseEntity<PK> implements IEntity<PK> { private static final long serialVersionUID = 1L; public BaseEntity() { } }
-
STEP 3:创建实体对象,继承BaseEntity抽象类,代码如下:
@Entity(name = "system_config") public class SystemConfigModel extends BaseEntity<String> { private static final long serialVersionUID = 1L; @Id @Property(name = "id") private String id; @Property(name = "cfg_value") private String cfgValue; @Property(name = "data_type") private String dataType; @Column(name = "remark") private String remark; public SystemConfigModel() { } public SystemConfigModel(String id, String cfgValue, String dataType, String remark) { this.id = id; this.cfgValue = cfgValue; this.dataType = dataType; this.remark = remark; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCfgValue() { return cfgValue; } public void setCfgValue(String cfgValue) { this.cfgValue = cfgValue; } public String getDataType() { return dataType; } public void setDataType(String dataType) { this.dataType = dataType; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public class FIELDS { public static final String ID = "id"; public static final String CFG_VALUE = "cfg_value"; public static final String DATA_TYPE = "data_type"; public static final String REMARK = "remark"; } public static final String TABLE_NAME = JDBC.TABLE_PREFIX + "system_config"; }
-
STEP 1:定义存储器接口,代码如下:
public interface ISystemConfigRepository { public List<SystemConfigModel> findById(String id, String... filter) throws Exception; public SystemConfigModel insert(SystemConfigModel model) throws Exception; public SystemConfigModel update(SystemConfigModel model, String...filter) throws Exception; public SystemConfigModel delete(SystemConfigModel model) throws Exception; }
-
STEP 2:实现存储器接口,代码如下:
@Repository public class SystemConfigRepository implements ISystemConfigRepository { public List<SystemConfigModel> findById(String id, String... filter) throws Exception { ISession _session = JDBC.openSession(); try{ return _session.find(SystemConfigModel.class, id, filter); } finally { _session.close(); } } public SystemConfigModel insert(SystemConfigModel model) throws Exception { ISession _session = JDBC.openSession(); try{ return _session.insert(model); } finally { _session.close(); } } public SystemConfigModel update(SystemConfigModel model, String... filter) throws Exception { ISession _session = JDBC.openSession(); try{ return _session.update(model, filter); } finally { _session.close(); } } public SystemConfigModel delete(SystemConfigModel model) throws Exception { ISession _session = JDBC.openSession(); try{ return _session.delete(model); } finally { _session.close(); } } }
-
STEP 3:需要修改”src/conf/ymp-conf.properties”文件,添加存储器包扫描路径配置:
ymp.configs.jdbc.base.repository_packages=net.ymate.web.demo.repository
-
STEP 1:添加控制器方法,代码如下:
@RequestMapping("/testdb") @RequestMethod public IView testRepo() throws Exception { SystemConfigModel _model = new SystemConfigModel(); _model.setId("cfg_username"); _model.setCfgValue("suninformation"); ISystemConfigRepository _repo = JDBC.getBean(ISystemConfigRepository.class); _repo.insert(_model); _repo.findById("cfg_username", SystemConfigModel.FIELDS.ID); _model.setCfgValue("suninformation#163.com"); _repo.update(_model, SystemConfigModel.FIELDS.CFG_VALUE); _repo.delete(_model); return new TextView(""); }
-
STEP 2:使用浏览器访问http://localhost:8080/ympweb-demo/testdb,查询日志输出: