- 针对上一篇文字做出了改造,既然要写手写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;
}
@Override
public 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>();
@Override
public 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();
}
}
}
@Override
protected 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";
}
}