upgrade...
- 1. actionservlet核心控制器更改以上1,2点
- 2. 工具类(对反射拿到的属性对象数据转型)
- 3. 业务服务类使用适配器设计模式
- 针对上一篇文字做出了改造,既然要写手写lowb版mvc框架,就得付出一定代价,加大代码量,只考虑实现业务
上一篇的升级版 - 更改的地方:
- 使用xml配置文件代替config.properties,更灵活方便,用来映射请求方式与实现业务类的路径
- 按规则封装了request请求对象中的数据,规则(a. 表单中的表单元素名称同实体类中属性的名称一样 b. 表单中的元素名称 以 实体对象.属性名称命名)
- 一个服务类就可完成增删改查业务逻辑操作
1. actionservlet核心控制器更改以上1,2点
- action.xml 映射请求路径和服务类全路径

- 描述action.xml 的数据结构
package com.lovely.mvc;
public class MapperAction {private String path; private String type; public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String getType() {return type;}public void setType(String type) {this.type = type;}@Overridepublic String toString() {return "MapperAction [path=" + path + ", type=" + type + "]";}}
package com.lovely.mvc;import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import com.lovely.util.ConvertUtil;public class ActionServlet extends HttpServlet {private static final long serialVersionUID = 1L;Map<String, MapperAction> map = new HashMap<String, MapperAction>();@Overridepublic void init() throws ServletException {SAXReader reader = new SAXReader();InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/action.xml");try {Document doc = reader.read(in);List<Element> list = doc.selectNodes("//action");for (Element action : list) {String path = action.elementText("path");String type = action.elementText("type");MapperAction mapper = new MapperAction();mapper.setPath(path);mapper.setType(type);map.put(path, mapper);}} catch (DocumentException e) {e.printStackTrace();} finally {try {if (in != null)in.close();} catch (IOException e) {e.printStackTrace();}}}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String uri = req.getRequestURI();String key = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf("."));String value = map.get(key).getType();if (value == null) {resp.sendError(404, key + "不在配置文件xml中");return;}try {Class<?> c = Class.forName(value);Action action = (Action) c.newInstance();Map<String, String[]> requestMap = req.getParameterMap();Set<Entry<String,String[]>> entrySet = requestMap.entrySet();for (Entry<String, String[]> entry : entrySet) {String name = entry.getKey();String[] formValue = entry.getValue();if (name.indexOf(".") == -1) {try {Field field = c.getDeclaredField(name);field.setAccessible(true);field.set(action, ConvertUtil.convert(field, formValue));} catch (NoSuchFieldException e) {} catch (SecurityException e) {e.printStackTrace();}} else {try {String[] split = name.split("\\.");Field fieldEntity = c.getDeclaredField(split[0]);fieldEntity.setAccessible(true);Object entity = fieldEntity.get(action);if (entity == null) {entity = fieldEntity.getType().newInstance();fieldEntity.set(action, entity);} Class<?> ff = fieldEntity.getType();Field field = ff.getDeclaredField(split[1]);field.setAccessible(true);field.set(entity, ConvertUtil.convert(field, formValue));} catch (NoSuchFieldException e) {} catch (SecurityException e) {e.printStackTrace();}}}String result = action.service(req, resp);if (result == "")return;if (result != null) {if (result.startsWith("forward")) {String path = result.split(":")[1];req.getRequestDispatcher(path).forward(req, resp);} else if (result.startsWith("redirect")) {String path = result.split(":")[1];resp.sendRedirect(req.getContextPath() + path);} else {req.getRequestDispatcher(result).forward(req, resp);} }} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
2. 工具类(对反射拿到的属性对象数据转型)
- 由于数据库dao层使用ConverUtil中的convert, 所以为了不改代码,使用重载设计
package com.lovely.util;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;public class ConvertUtil {public static Object convert(Field f, String value) {if (value == null)return null;Object obj = null;try {if (f.getType() == Date.class) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");java.util.Date date = sdf.parse(value); obj = new Date(date.getTime());} else if (f.getType() == Timestamp.class) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");java.util.Date date = sdf.parse(value);obj = new Timestamp(date.getTime());} else {Class<?> type = f.getType();Constructor<?> con = type.getDeclaredConstructor(String.class);obj = con.newInstance(value);} } catch (Exception e) {e.printStackTrace();}return obj;}public static Object convert(Field f, String[] value) {if (value == null || value.length == 0)return null;Object obj = null;try {if (f.getType() == Date.class) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");java.util.Date date = sdf.parse(value[0]); obj = new Date(date.getTime());} else if (f.getType() == Timestamp.class) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");java.util.Date date = sdf.parse(value[0]);obj = new Timestamp(date.getTime());} else if ((f.getType() == int.class || f.getType() == Integer.class) && value[0] != "") { obj = new Integer(value[0]);} else if ((f.getType() == double.class || f.getType() == Double.class) && value[0] != "") {obj = new Double(value[0]);} else if (f.getType() == String.class && value[0] != "") {obj = value[0];} else if (f.getType() == Integer[].class) {Integer[] integer = new Integer[value.length];for (int i = 0; i < value.length; i++) {integer[i] = new Integer(value[i]);}obj = integer;} else if (f.getType() == int[].class) {int[] arr = new int[value.length];for (int i = 0; i < arr.length; i++) {arr[i] = Integer.parseInt(value[i]);}} else if ((f.getType() == boolean.class || f.getType() == Boolean.class) && value[0] != "") {if (value[0] == "y" || value[0] == "1" || value[0] == "true") {obj = true;} else {obj = false;} }} catch (Exception e) {e.printStackTrace();}return obj;}}
3. 业务服务类使用适配器设计模式
package com.lovely.mvc;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public interface Action {public String service(HttpServletRequest req, HttpServletResponse resp);}
package com.lovely.mvc;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DispatcherAction implements Action {public String service(HttpServletRequest req, HttpServletResponse resp) {Class<?> c = this.getClass();String method = req.getParameter("method");String returnValue = "";try {Method methodObj = c.getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);returnValue = methodObj.invoke(this, req, resp).toString(); } catch (NoSuchMethodException e) {try {resp.sendError(404, method + "方法不存在...");} catch (IOException e1) {e1.printStackTrace();}} catch (SecurityException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} return returnValue;}}
package com.lovely.action;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.lovely.dao.CommonDao;
import com.lovely.entity.Ticket;
import com.lovely.mvc.DispatcherAction;public class TicketAction extends DispatcherAction {CommonDao dao = new CommonDao();public String queryAll(HttpServletRequest req, HttpServletResponse resp) {req.setAttribute("list", dao.queryAll(Ticket.class));return "/index.jsp";}private Ticket t;public String save(HttpServletRequest req, HttpServletResponse resp) {System.out.println(t);int count = dao.save(t);if (count > 0)return "/TicketAction.do?method=queryAll";return "/add.jsp";}public String findOneTicket(HttpServletRequest req, HttpServletResponse resp) {req.setAttribute("ticket", dao.queryOne(t));return "/update.jsp";}public String update(HttpServletRequest req, HttpServletResponse resp) {int count = dao.update(t);if (count > 0)return "redirect:/TicketAction.do?method=queryAll";return "/TicketAction.do?method=findOneTicket";}public String delete(HttpServletRequest req, HttpServletResponse resp) {int count = dao.delete(t);if (count > 0)return "/TicketAction.do?method=queryAll";else return "/TicketAction.do?method=queryAll";}}