Servlet、JDBC简易封装框架-lovew

  baikapala

说明

个人所用的轻量级的servlet和orm框架,没什么技术而言,完全是因为在平常测试工作中经常需要写一些小型的web应用工具,既不想使用SSH这么庞大的框架,也不想直接使用servlet或者JDBC,写起来也是及其麻烦。

源码和Demo示例都放在了GitHub上,有兴趣的可以一起交流学习。



源码: https://github.com/xuwangcheng14/lovew

Demo: https://github.com/xuwangcheng14/lovewDemo




依赖Jar

除了lovew.jar,


以下jar包是必须的:

commons-beanutils.jar
commons-collections.jar
commons-lang.jar
ezmorph-1.0.6.jar
json-lib-2.2.3-jdk15.jar

以下jar可能你会用得上:

jackson-all-1.9.0.jar

commons-logging.jar
log4j-1.2.17.jar

配置文件

目前配置文件仅有一个:lovew.properties



#database configuration#
db.classname=org.sqlite.JDBC
db.url=jdbc:sqlite:info.db
db.username=
db.password=

db.autoCreateTable=true

#Bean Mapper#
Person.id=id
Person.name=name
Person.city=city
Person.age=age

#create Table SQL#
table.Person=create table if not exists person(id integer primary key autoincrement,name text,age integer)
table.User=create table if not exists person(id integer primary key autoincrement,name text,age integer)



db.autoCreateTable配置说明了是否需要在初始化时自动执行建表语句,默认为false,相应的建表语句也需要配置在配置文件中,对应key值必须为table开头,例如table.Person

db前缀的配置了对应的数据库配置,如果用户不自行配置,默认使用sqlite(嵌入型文件数据库)

同时可以自行配置bean实体类与数据库表字段的对应关系,配置方式为:类名称.属性名=对应字段名,如果你没用配置,则默认字段名称与类中属性名相同


ORM

说起来是orm,其实完全是将jdbc给做了个简单的包装而已。


自定义Mapper需要继承AbstractMapper<T>


import bean.User;
import xuwangcheng.love.w.orm.AbstractMapper;

public class UserMapper extends AbstractMapper<User> {
	
	public UserMapper() {
		// TODO Auto-generated constructor stub
		super();
	}
}


然后在对应的Dao中直接使用Mapper即可



import bean.User;
import mapper.UserMapper;

public class UserDao {
	
	public User get(String name) throws Exception {
		String sql = "select * from user where name=?";
		UserMapper mapper = new UserMapper();
		
		mapper.execSQL(sql, name);
		
		return mapper.getObject();
	}
	
	public int save(User user) throws Exception {
		String sql = "insert into user values(?,?,?)";
		UserMapper mapper = new UserMapper();
		mapper.execSQL(sql, user.getName(), user.getCity(), user.getAge());
		
		return mapper.getEffectRowCount();
		
	}
}	
在针对不同的SQL语句,通过execSQL方法传入SQL语句和替换参数(按照占位符的位置序号),执行完毕之后,在通过mapper实例获取需要的结果,具体的返回获取方法可以参考AbstractMapper源码部分:




/**
	 * 获取返回的一个指定的对象实例<br>
	 * 多个只返回第一个
	 * 
	 * @return
	 */
	public T getObject() 


/**
	 * 返回对象集合,只有select * from才会用此接收<br>
	 * 要设置的属性必须要有set方法
	 * @return
	 */
	public List<T> getObjectList()


/**
	 * 影响到的记录行数<br>
	 * 默认为0
	 * @return
	 */
	public int getEffectRowCount()

/**
	 * 返回对象数组集合,除select * from之外其他的返回都用此接收
	 * @return
	 */
	public List<Object[]> getReturnObjects() 

/**
	 * 通过查询语句查询到的记录数
	 * @return
	 */
	public int getQueryCount()


Servlet

目前servlet只能返回json字符串,主要于前后台分离时,交互方式为ajax的场景。


自定义servlet需要继承AbstractHttpServlet,同时在初始化时需要显式的调用AbstractHttpServletsetServlet方法(自身作为方法参数)。

通过传入的具体requestUri来匹配servlet中对应的方法来做对应的处理,每个对应的处理方法上必须有@ExecuteRequest注解,默认请求的uri必须和方法名或者注解中自定义的value值相同,例如:@ExecuteRequest("save")public void insertUser() 该方法对应的uri为save
同时处理请求的方法上必须固定的两个参数Map<String, Object> ajaxMap, HttpServletRequest request,前者为返回给前台的ajaxMap(会自动转换成json字符串),后者为对应请求的request对象,如果你需要框架为你自动注入请求参数,可以自行添加更多的方法参数,例如:

public void insertUser(Map<String, Object> ajaxMap, HttpServletRequest request, @RequestBody("name") String name,@RequestBody("city") String city, @RequestBody("age") int age) 

暂时不支持自动注入复杂对象参数。

下面是demo中的示例:

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

import bean.User;
import dao.UserDao;
import xuwangcheng.love.w.servlet.AbstractHttpServlet;
import xuwangcheng.love.w.servlet.annotation.ExecuteRequest;
import xuwangcheng.love.w.servlet.annotation.InjectDao;
import xuwangcheng.love.w.servlet.annotation.RequestBody;
import xuwangcheng.love.w.util.Constants;

public class TestServlet extends AbstractHttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public TestServlet() {
		// TODO Auto-generated constructor stub
		super.setServlet(this);
	}
	
	@InjectDao
	private UserDao userDao;
	
	@ExecuteRequest
	public void getName(Map<String, Object> ajaxMap, HttpServletRequest request, @RequestBody("name") String name) {
		
		if (StringUtils.isBlank(name)) {
			ajaxMap.put("msg", "参数不正确");
			ajaxMap.put("returnCode", 1);
			return;
		}
		
		ajaxMap.put("msg", "Test:Hello " + name);
		ajaxMap.put("returnCode", 0);
	}
	
	@ExecuteRequest("save")
	public void insertUser(Map<String, Object> ajaxMap, HttpServletRequest request, @RequestBody("name") String name
			,@RequestBody("city") String city, @RequestBody("age") int age) throws Exception {
		User user = new User(name, city, age);
		int ret = userDao.save(user);
		ajaxMap.put(Constants.RETURN_CODE_ATTRIBUTE_NAME, Constants.CORRECT_RETURN_CODE);
		ajaxMap.put(Constants.RETURN_MSG_ATTRIBUTE_NAME, ret);
	}
	
	@ExecuteRequest
	public void get(Map<String, Object> ajaxMap, HttpServletRequest request, @RequestBody("name") String name) throws Exception {
		ajaxMap.put(Constants.RETURN_CODE_ATTRIBUTE_NAME, Constants.CORRECT_RETURN_CODE);
		ajaxMap.put("user", userDao.get(name));
	}
	
	/*****************************************************************************/
	public UserDao getUserDao() {
		return userDao;
	}
	
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
}



整合

servlet中自动注入Dao:

Dao属性加上InjectDao注解,同时在serlvet中提供对应的get/set方法。

具体参考上面的示例



web.xml

web.xml配置方式同原生的servlet配置,如果你需要自动建表的功能,加上指定的listener即可(自定义listener请继承此listener)



<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" 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>TestProject</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <listener>
  	<listener-class>xuwangcheng.love.w.servlet.listener.LovewInitListener</listener-class>
  </listener>
  
  <servlet>
  	<servlet-name>test</servlet-name>
  	<servlet-class>servlet.TestServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>test</servlet-name>
  	<url-pattern>/test/*</url-pattern>
  </servlet-mapping>
</web-app>