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; } @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 = 1 L; 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" ; } }