手写简单框架,对上篇"从IO 到框架(4)-Servlet + JDBC (Idea Maven)" 的第一次迭代。
1)控制层:
核心思想:使用反射、泛型和注解技术设计通用(批量处理) 的工具类。
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。一直以来反射技术都是Java中的闪亮点,这也是目前大部分框架(如Spring / Mybatis等)得以实现的支柱。在Java中,Class类与java.lang.reflect类库一起对反射技术进行了全力的支持。
- 简化事件分发步骤
- 简化页面提交参数获取
- 参数列表的简化
- 跳转的简化 - 默认就是转发,重定向加上前缀 "redirect:"
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理事件分发
String method = request.getParameter("method");
if (method == null) {
System.out.println("method Can't be null!");
return;
}
/* 获得其Class 实例的三种方法:1)通过被页面调用的servlet 的实例,这是Class类从Object 继承的方法
2)通过Class的静态方法Class.forName(String className), 可用配置文件
3)Class字面常量 类名.class
其中实例类的getClass方法和Class类的静态方法forName都将会触发类的初始化阶段,
而字面常量获取Class对象的方式则不会触发初始化。*/
Class<? extends BaseServlet> aClass = this.getClass();
Method[] methods = aClass.getMethods();
for (Method m : methods) {
int modifiers = m.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
if (m.getName().equals(method)) {
Login l = m.getAnnotation(Login.class);
Object obj = request.getSession().getAttribute("user");
if (l == null || (l != null && obj != null)) {
Object[] params = getParams(request, response, m);
try {
String result = (String) m.invoke(this, params);
if (result != null) {
if (result.startsWith("redirect:")) {
response.sendRedirect(result.split(":")[1]);
} else {
request.getRequestDispatcher(result).forward(request, response);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}else{
String url = request.getRequestURI();
url += "?" + request.getQueryString();
response.sendRedirect("front/login.jsp?gotourl=" + url);
}
}
}
}
}
private Object[] getParams(HttpServletRequest request, HttpServletResponse response, Method m) throws IOException {
List<Object> list = new ArrayList<>();
Class<?>[] types = m.getParameterTypes();
for (Class<?> type : types) {
if (type == HttpServletRequest.class) {
list.add(request);
} else if (type == HttpServletResponse.class) {
list.add(response);
} else if (type == HttpSession.class) {
list.add(request.getSession());
} else if (type == PrintWriter.class) {
list.add(response.getWriter());
} else if (type.isAnnotationPresent(Entity.class)) {
list.add(parseRequest(request, type));
} else if (type == Page.class) {
//@Rock 此处Goods 写死了,记得修改
Page<Goods> pageObj = new Page<>();
String page = request.getParameter("page");
if (page == null) {
pageObj.setPage(1);
} else {
pageObj.setPage(Integer.parseInt(page));
}
String uri = request.getRequestURI();
pageObj.setUrl(uri);
String params = request.getQueryString();
if (params != null && params.trim() != "") {
if (params.lastIndexOf("page") != -1) {
params = params.substring(0, params.lastIndexOf("page") - 1);
}
} else {
params = "1=1";
}
pageObj.setParams(params);
list.add(pageObj);
} else {
list.add(null);
}
}
return list.toArray();
}
public <T> T parseRequest(HttpServletRequest request, Class<T> cls) {
T t = null;
try {
t = cls.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
int modifiers = field.getModifiers();
if (Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
field.setAccessible(true);
String value = request.getParameter(field.getName());
if (value != null) {
Object v = null;
Format annotation = field.getAnnotation(Format.class);
if (annotation != null) {
RequestTypeHandler<?> typeHandler = null;
try {
typeHandler = annotation.value().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
v = typeHandler.string2Field(value);
} else {
if (field.getType() == String.class) {
v = value;
} else if (field.getType() == int.class || field.getType() == Integer.class) {
v = Integer.parseInt(value);
} else if (field.getType() == Double.class || field.getType() == double.class) {
v = Double.parseDouble(value);
} else if (field.getType() == Float.class || field.getType() == float.class) {
v = Float.parseFloat(value);
} else if (field.getType() == Short.class || field.getType() == short.class) {
v = Short.parseShort(value);
} else if (field.getType() == Boolean.class || field.getType() == boolean.class) {
v = Boolean.parseBoolean(value);
} else if (field.getType() == Long.class || field.getType() == long.class) {
v = Long.parseLong(value);
} else if (field.getType() == Character.class || field.getType() == char.class) {
v = value.toCharArray()[0];
} else if (field.getType() == Byte.class || field.getType() == byte.class) {
v = Byte.parseByte(value);
}
}
try {
field.set(t, v);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return t;
}
}
2)持久层:将常用操作的增删改查封装在一个工具类
public class BaseDaoImpl {
public int insert(String sql, Object... params) {
Connection conn = ConnectionUtil.getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
int result = ps.executeUpdate();
if (result > 0) {
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
return rs.getInt(1);
}
}
return result;
} catch (SQLException e) {
e.printStackTrace();
} finally {
ConnectionUtil.close(conn, ps, null);
}
return 0;
}
public int update(String sql, Object... params) {
Connection conn = ConnectionUtil.getConnection();
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
ConnectionUtil.close(conn, ps, null);
}
return 0;
}
public <T> List<T> queryAll(String sql, Class<T> tcls, Object... params) {
Connection conn = ConnectionUtil.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
List<T> list = new ArrayList<>();
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
rs = ps.executeQuery();
while (rs.next()) {
T t = null;
try {
t = tcls.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
Field[] fields = tcls.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object o = rs.getObject(field.getName());
field.set(t, o);
} catch (Exception e) {
}
}
list.add(t);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
ConnectionUtil.close(conn, ps, rs);
}
return list;
}
public <T> T queryOne(String sql, Class<T> tcls, Object... params) {
List<T> ts = queryAll(sql, tcls, params);
return ts != null && ts.size() > 0 ? ts.get(0) : null;
}
public ResultSet query(String sql, Object... params) throws SQLException {
Connection conn = ConnectionUtil.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
rs = ps.executeQuery();
RowSetFactory rowSetFactory = RowSetProvider.newFactory();
CachedRowSet cachedRowSet = rowSetFactory.createCachedRowSet();
cachedRowSet.populate(rs);
return cachedRowSet;
} finally {
ConnectionUtil.close(conn, ps, rs);
}
}
public <T> Page<T> queryByPage(Page<T> pageObj, Class<T> cls, String sql, Object... params) throws SQLException {
sql = sql.toLowerCase();
String sqlcount = "select count(*) " + sql.substring(sql.indexOf("from"));
ResultSet rs = query(sqlcount, params);
int sum = 0;
if (rs.next()) {
sum = rs.getInt(1);
}
pageObj.setPageSum(sum);
pageObj.setPageCount((sum - 1) / pageObj.getPageSize() + 1);
List<Object> list = new ArrayList<>();
for (Object param : params) {
list.add(param);
}
list.add((pageObj.getPage() - 1) * pageObj.getPageSize());
list.add(pageObj.getPageSize());
sql = sql + " limit ?,?";
List<T> ts = queryAll(sql, cls, list.toArray());
pageObj.setDatas(ts);
return pageObj;
}
}