首先使用IDEA创建Java工程,目录如下图所示:
使用 Jetty作为Web服务器,配置 jetty.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id='Contexts' class="org.eclipse.jetty.webapp.WebAppContext">
<New id="mysql" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg></Arg>
<Arg>jdbc/mall</Arg>
<Arg>
<New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
<Set name="Url">jdbc:mysql://127.0.0.1:3306/mall?useUnicode=true&amp;characterEncoding=utf-8&amp;jdbcCompliantTruncation=false&amp;autoReconnect=true&allowPublicKeyRetrieval=true</Set>
<Set name="User">root</Set>
<Set name="Password"></Set>
</New>
</Arg>
</New>
</Configure>
配置joy.props:
jndiName=java:comp/env/jdbc/mall
编写AppListener.java
package io.github.mall.api;
import jodd.db.connection.DataSourceConnectionProvider;
import jodd.joy.JoddJoy;
import jodd.joy.JoyContextListener;
import jodd.madvoc.petite.PetiteWebApp;
import jodd.petite.PetiteContainer;
import jodd.props.Props;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.annotation.WebListener;
import java.util.function.Supplier;
@WebListener
public class AppListener extends JoyContextListener {
private static Logger logger = LoggerFactory.getLogger(AppListener.class);
private PetiteContainer container = null;
@Override
protected JoddJoy createJoy() {
Props props = new Props();
props.loadFromClasspath("/joy.props");
String jndiName = props.getValue("jndiName");
logger.info("使用 [{}] 作为默认的数据源!", jndiName);
Supplier<PetiteContainer> petiteContainer= PetiteContainer::new;
JoddJoy joy = super.createJoy();
joy.withDb(db -> db.withConnectionProvider(() -> new DataSourceConnectionProvider(jndiName)));
joy.withPetite(joyPetiteConfig -> joyPetiteConfig.withPetite(consumer->{
container = consumer;
logger.info("容器 container={}",container);
}));
Supplier<PetiteWebApp> petiteWebAppSupplier = () -> new AppWeb(container);
joy.useWebApp(petiteWebAppSupplier); // 使用自定义AppWeb
return joy;
}
}
编写自定义的AppWeb.java:
package io.github.mall.api;
import io.github.mall.api.config.AppRestActionConfig;
import jodd.madvoc.WebApp;
import jodd.madvoc.component.ActionConfigManager;
import jodd.madvoc.meta.RestAction;
import jodd.madvoc.petite.PetiteWebApp;
import jodd.petite.PetiteContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AppWeb extends PetiteWebApp {
private static Logger logger = LoggerFactory.getLogger(AppWeb.class);
public AppWeb(PetiteContainer petiteContainer) {
super(petiteContainer);
}
@Override
public WebApp start() {
// 登记默认的RestActionConfig配置
super.withRegisteredComponent(ActionConfigManager.class,acm->{
acm.bindAnnotationConfig(RestAction.class, AppRestActionConfig.class);
});
return super.start();
}
}
AppRestActionConfig.java:
package io.github.mall.api.config;
import io.github.mall.api.interceptor.ApiInterceptor;
import jodd.joy.i18n.I18nInterceptor;
import jodd.madvoc.action.RestActionConfig;
import jodd.madvoc.interceptor.ServletConfigInterceptor;
/**
* 此处设置默认的拦截器配置
**/
public class AppRestActionConfig extends RestActionConfig {
@SuppressWarnings("unchecked")
public AppRestActionConfig() {
super();
setInterceptors(
I18nInterceptor.class,
ApiInterceptor.class,
ServletConfigInterceptor.class
);
}
}
ApiInterceptor.java 拦截器:
package io.github.mall.api.interceptor;
import io.github.mall.api.data.Result;
import io.github.mall.api.exception.ServiceException;
import jodd.madvoc.ActionRequest;
import jodd.madvoc.interceptor.ActionInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApiInterceptor implements ActionInterceptor {
private static final Logger logger = LoggerFactory.getLogger(ApiInterceptor.class);
@Override
public Object intercept(ActionRequest actionRequest) throws Exception {
Result<Object> result = new Result<>();
logger.info("在 {} 拦截器中运行...",ApiInterceptor.class.getName());
try {
Object val = actionRequest.invoke();
result.setData(val);
result.setResultCode(0);
result.setResultMsg("");
}catch (ServiceException se){
result.setResultCode(se.getErrorCode());
result.setResultMsg(se.getErrorMsg());
}
return result;
}
}
Result.java:
package io.github.mall.api.data;
/*
* Api 接口返回对象
*/
public class Result<T> {
private Integer resultCode = null;
private String resultMsg = "";
private T data = null;
public Integer getResultCode() {
return resultCode;
}
public void setResultCode(Integer resultCode) {
this.resultCode = resultCode;
}
public String getResultMsg() {
return resultMsg;
}
public void setResultMsg(String resultMsg) {
this.resultMsg = resultMsg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
测试的IndexAction.java:
package io.github.mall.api.action;
import io.github.mall.api.entity.User;
import io.github.mall.api.exception.ServiceException;
import io.github.mall.api.service.UserService;
import jodd.madvoc.meta.In;
import jodd.madvoc.meta.MadvocAction;
import jodd.madvoc.meta.RestAction;
import jodd.petite.meta.PetiteInject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
@MadvocAction
public class IndexAction {
private static final Logger logger = LoggerFactory.getLogger(IndexAction.class);
@PetiteInject
private UserService userService=null;
@In
private Integer index=null;
//RestAction标注的Action其返回将默认使用AppRestActionConfig中配置的拦截器
@RestAction("/")
public List<User> index(){
List<User> users = userService.list(User.class);
logger.info("index={}",index);
userService.check();
if(index!=null)
throw new ServiceException(3,"错误");
return users;
}
}
BaseDao.java:
package io.github.mall.api.dao;
import jodd.db.DbOom;
import jodd.db.oom.DbOomQuery;
import jodd.db.oom.dao.GenericDao;
import jodd.jtx.meta.ReadOnlyTransaction;
import jodd.petite.meta.PetiteBean;
import java.util.List;
import java.util.Map;
@PetiteBean
public class BaseDao<T> {
private GenericDao dao;
public BaseDao() {
dao = new GenericDao(DbOom.get());
}
public T load(Class<T> glass, Long id) {
return dao.findById(glass, id);
}
public void insert(T o) {
dao.store(o);
}
public void update(T o) {
dao.update(o);
}
public void remove(T o) {
dao.deleteById(o);
}
public List<T> list(String sql, Map<String, Object> params) {
DbOomQuery query = DbOomQuery.query(sql).autoClose();
if (params != null && params.size() > 0) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
query.setObject(entry.getKey(), entry.getValue());
}
}
return query.list();
}
@ReadOnlyTransaction
public List<T> all(Class<T> glass) {
return dao.listAll(glass);
}
}
如此则其他Dao类写起来就非常简单了,继承BaseDao即可,例如 UserDao.java:
package io.github.mall.api.dao;
import io.github.mall.api.entity.User;
import jodd.petite.meta.PetiteBean;
@PetiteBean
public class UserDao extends BaseDao<User>{
}
对于Service类,同样如此,编写BaseService.java:
package io.github.mall.api.service;
import io.github.mall.api.dao.BaseDao;
import jodd.jtx.meta.ReadOnlyTransaction;
import jodd.jtx.meta.ReadWriteTransaction;
import jodd.petite.meta.PetiteBean;
import jodd.petite.meta.PetiteInject;
import java.util.List;
import java.util.Map;
@PetiteBean
public class BaseService<T> {
@PetiteInject
private BaseDao<T> dao;
@ReadOnlyTransaction
public T load(Class<T> glass,Long id){
return dao.load(glass,id);
}
@ReadWriteTransaction
public void save(T entity)
{
dao.insert(entity);
}
@ReadWriteTransaction
public void update(T entity){
dao.update(entity);
}
@ReadWriteTransaction
public void remove(T entity){
dao.remove(entity);
}
@ReadOnlyTransaction
public List<T> list(String sql, Map<String,Object> params){
return dao.list(sql,params);
}
@ReadOnlyTransaction
public List<T> list(Class<T> glass){
return dao.all(glass);
}
}
由于从Jodd 5.0.4开始支持超类(SupperClass)的私有属性的注入(private field),以及超类的私有属性的注解解析,因此 其他的Service类更加简单,例如UserService.java:
package io.github.mall.api.service;
import io.github.mall.api.entity.User;
import jodd.petite.meta.PetiteBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
@PetiteBean
public class UserService extends BaseService<User>{
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
// @PetiteInject
// private BaseDao<User> baseDao;
@ReadOnlyTransaction
public List<User> users(){
// logger.info("baseDao={}",baseDao);
return list(User.class);
}
}