Web4J之试用
Web4J是一个比较新潮的Web框架,具体信息可以参考官网的相关说明: http://www.web4j.com/,下面是我的简单试用1、数据库准备(MySQL):
创建一个数据库和一个单表:
create
database
test4j;
use test4j;
create table tbl_log(
log_id mediumint unsigned auto_increment primary key ,
log_msg varchar ( 100 ) not null ,
log_date date
)type = innodb;
insert into tbl_log values ( 1 , ' good job ' ,curdate());
use test4j;
create table tbl_log(
log_id mediumint unsigned auto_increment primary key ,
log_msg varchar ( 100 ) not null ,
log_date date
)type = innodb;
insert into tbl_log values ( 1 , ' good job ' ,curdate());
2、web4j.jar改进:
将AppInfo等7个类打包到web4j.jar中
3、开始试用:
配置web.xml:
<
servlet-name
>
Controller
</
servlet-name
>
< servlet-class > hirondelle.web4j.Controller </ servlet-class >
< init-param >
< description >
</ description >
< param-name > ImplicitMappingRemoveBasePackage </ param-name >
< param-value > test </ param-value >
</ init-param >
< init-param >
< param-name > ImplementationFor.hirondelle.web4j.ApplicationInfo </ param-name >
< param-value > test.main.AppInfo </ param-value >
< description >
</ description >
</ init-param >
< init-param >
< description >
</ description >
< param-name > LoggingDirectory </ param-name >
< param-value > E:\jdev\eclipse\workspace\My4JTest\log\ </ param-value >
</ init-param >
< init-param >
< param-name > DefaultDbConnectionString </ param-name >
< param-value > java:comp/env/jdbc/test4j </ param-value >
</ init-param >
..
< resource-ref >
< description > DB Connection Pool For Main Application </ description >
< res-ref-name > jdbc/test4j </ res-ref-name >
< res-type > javax.sql.DataSource </ res-type >
< res-auth > Container </ res-auth >
</ resource-ref >
< servlet-class > hirondelle.web4j.Controller </ servlet-class >
< init-param >
< description >
</ description >
< param-name > ImplicitMappingRemoveBasePackage </ param-name >
< param-value > test </ param-value >
</ init-param >
< init-param >
< param-name > ImplementationFor.hirondelle.web4j.ApplicationInfo </ param-name >
< param-value > test.main.AppInfo </ param-value >
< description >
</ description >
</ init-param >
< init-param >
< description >
</ description >
< param-name > LoggingDirectory </ param-name >
< param-value > E:\jdev\eclipse\workspace\My4JTest\log\ </ param-value >
</ init-param >
< init-param >
< param-name > DefaultDbConnectionString </ param-name >
< param-value > java:comp/env/jdbc/test4j </ param-value >
</ init-param >
..
< resource-ref >
< description > DB Connection Pool For Main Application </ description >
< res-ref-name > jdbc/test4j </ res-ref-name >
< res-type > javax.sql.DataSource </ res-type >
< res-auth > Container </ res-auth >
</ resource-ref >
相应的tomcat部署文件test4j.xml为:
<
Context
path
="/test4j"
docBase
="E:\jdev\eclipse\workspace\My4JTest\WebContent"
debug ="5" reloadable ="true" crossContext ="true" >
< Resource name ="jdbc/test4j" auth ="Container" type ="javax.sql.DataSource"
username ="root" password ="root" driverClassName ="org.gjt.mm.mysql.Driver"
url ="jdbc:mysql://localhost:3306/test4j?useServerPrepStmts=false"
maxActive ="10" maxIdle ="5" />
</ Context >
debug ="5" reloadable ="true" crossContext ="true" >
< Resource name ="jdbc/test4j" auth ="Container" type ="javax.sql.DataSource"
username ="root" password ="root" driverClassName ="org.gjt.mm.mysql.Driver"
url ="jdbc:mysql://localhost:3306/test4j?useServerPrepStmts=false"
maxActive ="10" maxIdle ="5" />
</ Context >
主干文件的编写:
MODEL:
package
test.main;
import static hirondelle.web4j.util.Consts.FAILS;
import hirondelle.web4j.model.Check;
import hirondelle.web4j.model.Id;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.model.ModelUtil;
import hirondelle.web4j.security.SafeText;
import java.util.Date;
public final class Log {
private Id logId;
private SafeText logMsg;
private Long logDate;
private void validate() throws ModelCtorException {
ModelCtorException ex = new ModelCtorException();
if (FAILS == Check.optional(logMsg, Check.range(0, 100))) {
ex.add("Message cannot be longer than 1,000 characters.");
}
if (ex.isNotEmpty()) {
throw ex;
}
}
public Id getLogId() {
return logId;
}
public SafeText getLogMsg() {
return logMsg;
}
public Date getLogDate() {
return new Date(logDate);
}
public Log(Id id, SafeText msg, Date date) throws ModelCtorException {
this.logId = id;
this.logMsg = msg;
this.logDate = date == null ? null : date.getTime();
validate();
}
@Override
public String toString() {
return ModelUtil.toStringFor(this);
}
}
import static hirondelle.web4j.util.Consts.FAILS;
import hirondelle.web4j.model.Check;
import hirondelle.web4j.model.Id;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.model.ModelUtil;
import hirondelle.web4j.security.SafeText;
import java.util.Date;
public final class Log {
private Id logId;
private SafeText logMsg;
private Long logDate;
private void validate() throws ModelCtorException {
ModelCtorException ex = new ModelCtorException();
if (FAILS == Check.optional(logMsg, Check.range(0, 100))) {
ex.add("Message cannot be longer than 1,000 characters.");
}
if (ex.isNotEmpty()) {
throw ex;
}
}
public Id getLogId() {
return logId;
}
public SafeText getLogMsg() {
return logMsg;
}
public Date getLogDate() {
return new Date(logDate);
}
public Log(Id id, SafeText msg, Date date) throws ModelCtorException {
this.logId = id;
this.logMsg = msg;
this.logDate = date == null ? null : date.getTime();
validate();
}
@Override
public String toString() {
return ModelUtil.toStringFor(this);
}
}
ACTION:
package
test.main;
import hirondelle.web4j.action.ActionTemplateListAndEdit;
import hirondelle.web4j.action.ResponsePage;
import hirondelle.web4j.database.DAOException;
import hirondelle.web4j.database.SqlId;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.model.ModelFromRequest;
import hirondelle.web4j.request.RequestParameter;
import hirondelle.web4j.request.RequestParser;
import hirondelle.web4j.util.Util;
import java.util.logging.Logger;
public final class LogAction extends ActionTemplateListAndEdit {
private static final ResponsePage FORWARD = TmplPage.get("Log", "view.jsp", LogAction.class);
private static final ResponsePage REDIRECT = new ResponsePage("LogAction.list");
private LogDAO fDAO = new LogDAO();
private Log fModel;
private static final Logger fLogger = Util.getLogger(LogAction.class);
public static final RequestParameter MSG = RequestParameter.withLengthCheck("LogMsg");
public static final RequestParameter ID = RequestParameter.withLengthCheck("LogId");
public static final RequestParameter DATE = RequestParameter.withLengthCheck("LogDate");
public static final SqlId LIST_LOG = new SqlId("LIST_LOG");
public static final SqlId FETCH_LOG = new SqlId("FETCH_LOG");
public static final SqlId ADD_LOG = new SqlId("INSERT_LOG");
public static final SqlId CHANGE_LOG = new SqlId("UPDATE_LOG");
public static final SqlId DELETE_LOG = new SqlId("DELETE_LOG");
public LogAction(RequestParser aRequestParser) {
super(FORWARD, REDIRECT, aRequestParser);
}
@Override
protected void attemptAdd() throws DAOException {
fLogger.fine("Attempting to add new Spending item.");
fDAO.add(fModel);
addMessage("Item added successfully.");
}
@Override
protected void attemptChange() throws DAOException {
fLogger.fine("Attempting to change an existing log item.");
boolean success = fDAO.change(fModel);
if (success) {
addMessage("Item changed successfully.");
} else {
addError("No update occurred. Item likely deleted by another user.");
}
}
@Override
protected void attemptDelete() throws DAOException {
fLogger.fine("Attempting to delete an existing log item.");
fDAO.delete(getIdParam(ID));
addMessage("Item deleted successfully.");
}
@Override
protected void attemptFetchForChange() throws DAOException {
fLogger.fine("Attempting to fetch an existing log item.");
Log model = fDAO.fetch(getIdParam(ID));
if (model == null) {
addError("Item no longer exists. Likely deleted by another user.");
} else {
addToRequest(ITEM_FOR_EDIT, model);
}
}
@Override
protected void doList() throws DAOException {
fLogger.fine("Listing all log items.");
addToRequest(ITEMS_FOR_LISTING, fDAO.list());
}
@Override
protected void validateUserInput() {
fLogger.fine("Validating user input.");
ModelFromRequest builder = new ModelFromRequest(getRequestParser());
try {
fModel = builder.build(Log.class, ID, MSG, DATE);
} catch (ModelCtorException ex) {
addError(ex);
}
}
}
import hirondelle.web4j.action.ActionTemplateListAndEdit;
import hirondelle.web4j.action.ResponsePage;
import hirondelle.web4j.database.DAOException;
import hirondelle.web4j.database.SqlId;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.model.ModelFromRequest;
import hirondelle.web4j.request.RequestParameter;
import hirondelle.web4j.request.RequestParser;
import hirondelle.web4j.util.Util;
import java.util.logging.Logger;
public final class LogAction extends ActionTemplateListAndEdit {
private static final ResponsePage FORWARD = TmplPage.get("Log", "view.jsp", LogAction.class);
private static final ResponsePage REDIRECT = new ResponsePage("LogAction.list");
private LogDAO fDAO = new LogDAO();
private Log fModel;
private static final Logger fLogger = Util.getLogger(LogAction.class);
public static final RequestParameter MSG = RequestParameter.withLengthCheck("LogMsg");
public static final RequestParameter ID = RequestParameter.withLengthCheck("LogId");
public static final RequestParameter DATE = RequestParameter.withLengthCheck("LogDate");
public static final SqlId LIST_LOG = new SqlId("LIST_LOG");
public static final SqlId FETCH_LOG = new SqlId("FETCH_LOG");
public static final SqlId ADD_LOG = new SqlId("INSERT_LOG");
public static final SqlId CHANGE_LOG = new SqlId("UPDATE_LOG");
public static final SqlId DELETE_LOG = new SqlId("DELETE_LOG");
public LogAction(RequestParser aRequestParser) {
super(FORWARD, REDIRECT, aRequestParser);
}
@Override
protected void attemptAdd() throws DAOException {
fLogger.fine("Attempting to add new Spending item.");
fDAO.add(fModel);
addMessage("Item added successfully.");
}
@Override
protected void attemptChange() throws DAOException {
fLogger.fine("Attempting to change an existing log item.");
boolean success = fDAO.change(fModel);
if (success) {
addMessage("Item changed successfully.");
} else {
addError("No update occurred. Item likely deleted by another user.");
}
}
@Override
protected void attemptDelete() throws DAOException {
fLogger.fine("Attempting to delete an existing log item.");
fDAO.delete(getIdParam(ID));
addMessage("Item deleted successfully.");
}
@Override
protected void attemptFetchForChange() throws DAOException {
fLogger.fine("Attempting to fetch an existing log item.");
Log model = fDAO.fetch(getIdParam(ID));
if (model == null) {
addError("Item no longer exists. Likely deleted by another user.");
} else {
addToRequest(ITEM_FOR_EDIT, model);
}
}
@Override
protected void doList() throws DAOException {
fLogger.fine("Listing all log items.");
addToRequest(ITEMS_FOR_LISTING, fDAO.list());
}
@Override
protected void validateUserInput() {
fLogger.fine("Validating user input.");
ModelFromRequest builder = new ModelFromRequest(getRequestParser());
try {
fModel = builder.build(Log.class, ID, MSG, DATE);
} catch (ModelCtorException ex) {
addError(ex);
}
}
}
DAO:
package
test.main;
import static test.main.LogAction.ADD_LOG;
import static test.main.LogAction.CHANGE_LOG;
import static test.main.LogAction.DELETE_LOG;
import static test.main.LogAction.FETCH_LOG;
import static test.main.LogAction.LIST_LOG;
import hirondelle.web4j.database.DAOException;
import hirondelle.web4j.database.Db;
import hirondelle.web4j.model.Id;
import hirondelle.web4j.util.Util;
import java.util.List;
final class LogDAO {
private Object[] baseParamsFrom(Log aLog) {
return new Object[] { aLog.getLogMsg() };
}
List<Log> list() throws DAOException {
return Db.list(Log.class, LIST_LOG);
}
Log fetch(Id aId) throws DAOException {
return Db.fetch(Log.class, FETCH_LOG, aId);
}
void add(Log aLog) throws DAOException {
Db.add(ADD_LOG, baseParamsFrom(aLog));
}
boolean change(Log aLog) throws DAOException {
Object[] params = Db.addIdTo(baseParamsFrom(aLog), aLog.getLogId());
return Util.isSuccess(Db.edit(CHANGE_LOG, params));
}
void delete(Id aId) throws DAOException {
Db.delete(DELETE_LOG, aId);
}
}
import static test.main.LogAction.ADD_LOG;
import static test.main.LogAction.CHANGE_LOG;
import static test.main.LogAction.DELETE_LOG;
import static test.main.LogAction.FETCH_LOG;
import static test.main.LogAction.LIST_LOG;
import hirondelle.web4j.database.DAOException;
import hirondelle.web4j.database.Db;
import hirondelle.web4j.model.Id;
import hirondelle.web4j.util.Util;
import java.util.List;
final class LogDAO {
private Object[] baseParamsFrom(Log aLog) {
return new Object[] { aLog.getLogMsg() };
}
List<Log> list() throws DAOException {
return Db.list(Log.class, LIST_LOG);
}
Log fetch(Id aId) throws DAOException {
return Db.fetch(Log.class, FETCH_LOG, aId);
}
void add(Log aLog) throws DAOException {
Db.add(ADD_LOG, baseParamsFrom(aLog));
}
boolean change(Log aLog) throws DAOException {
Object[] params = Db.addIdTo(baseParamsFrom(aLog), aLog.getLogId());
return Util.isSuccess(Db.edit(CHANGE_LOG, params));
}
void delete(Id aId) throws DAOException {
Db.delete(DELETE_LOG, aId);
}
}
statements.sql文件:
LIST_LOG {
SELECT log_id, log_msg, log_date
FROM tbl_log
ORDER BY log_date DESC
}
FETCH_LOG {
SELECT log_id, log_msg, log_date
FROM tbl_log
WHERE log_id = ?
}
INSERT_LOG {
INSERT INTO tbl_log (log_msg, log_date) VALUES (?,curdate())
}
UPDATE_LOG {
UPDATE tbl_log SET log_msg = ? WHERE log_id = ?
}
DELETE_LOG {
DELETE FROM tbl_log WHERE log_id = ?
}
SELECT log_id, log_msg, log_date
FROM tbl_log
ORDER BY log_date DESC
}
FETCH_LOG {
SELECT log_id, log_msg, log_date
FROM tbl_log
WHERE log_id = ?
}
INSERT_LOG {
INSERT INTO tbl_log (log_msg, log_date) VALUES (?,curdate())
}
UPDATE_LOG {
UPDATE tbl_log SET log_msg = ? WHERE log_id = ?
}
DELETE_LOG {
DELETE FROM tbl_log WHERE log_id = ?
}
视图view.jsp文件:
<%
-- List-and-edit form for Electricity Spending. --
%>
<% @ include file="/JspHeader.jsp" %>
< c:set value ='LogAction' var ='baseURL' />
< tags:setFormTarget using ='${baseURL}' />
<% -- Form for adds and edits. -- %>
< form action ='${formTarget}' method ="post" class ="user-input" >
< table align ="center" >
< w:populate using ="itemForEdit" >
< input name ="LogId" type ="hidden" >
< input name ="LogDate" type ="hidden" >
< tr >
< td >< label > LOG MSG: </ label ></ td >
< td >< input name ="LogMsg" type ="text" maxlength ='100' ></ td >
</ tr >
</ w:populate >
< tr >
< td align ="center" >< input type ="submit" value ="Add/Edit" >
</ td >
</ tr >
</ table >
</ form >
< P > <% -- Listing of all items. -- %>
< table class ="report" align ="center" >
< caption > Here is The Logs </ caption >
< tr >
< th title ="Line Number" > # </ th >
< th title ='Log Msg' > Log Msg </ th >
< th title ='Log Date' > Log Date </ th >
< th ></ th >
</ tr >
< w:alternatingRow >
< c:forEach var ="item" items ="${itemsForListing}" varStatus ="index" >
< tr class ="row_highlight" >
< td title ="Line Number" > ${index.count} </ td >
< td > ${item.logMsg} </ td >
< td align ='right' >< c:set value ="${item.logDate}" var ="paidOn" />
< w:showDate name ='paidOn' pattern ='yyyy-MM-dd' /></ td >
< tags:editLinks baseURL ='${baseURL}' id ='${item.logId}' />
</ tr >
</ c:forEach >
</ w:alternatingRow >
</ table >
<% @ include file="/JspHeader.jsp" %>
< c:set value ='LogAction' var ='baseURL' />
< tags:setFormTarget using ='${baseURL}' />
<% -- Form for adds and edits. -- %>
< form action ='${formTarget}' method ="post" class ="user-input" >
< table align ="center" >
< w:populate using ="itemForEdit" >
< input name ="LogId" type ="hidden" >
< input name ="LogDate" type ="hidden" >
< tr >
< td >< label > LOG MSG: </ label ></ td >
< td >< input name ="LogMsg" type ="text" maxlength ='100' ></ td >
</ tr >
</ w:populate >
< tr >
< td align ="center" >< input type ="submit" value ="Add/Edit" >
</ td >
</ tr >
</ table >
</ form >
< P > <% -- Listing of all items. -- %>
< table class ="report" align ="center" >
< caption > Here is The Logs </ caption >
< tr >
< th title ="Line Number" > # </ th >
< th title ='Log Msg' > Log Msg </ th >
< th title ='Log Date' > Log Date </ th >
< th ></ th >
</ tr >
< w:alternatingRow >
< c:forEach var ="item" items ="${itemsForListing}" varStatus ="index" >
< tr class ="row_highlight" >
< td title ="Line Number" > ${index.count} </ td >
< td > ${item.logMsg} </ td >
< td align ='right' >< c:set value ="${item.logDate}" var ="paidOn" />
< w:showDate name ='paidOn' pattern ='yyyy-MM-dd' /></ td >
< tags:editLinks baseURL ='${baseURL}' id ='${item.logId}' />
</ tr >
</ c:forEach >
</ w:alternatingRow >
</ table >
更多内容请参考附件,接下就是将test4j.xml文件拷贝到conf\Catalina\localhost路径下,启动tomcat之后,访问http://localhost:8080/test4j即可看到效果
下载附件请点击此处(内容为eclipse工程的压缩包): MyWeb4JTest