mvc框架upgrade

upgrade...

  • 1. actionservlet核心控制器更改以上1,2点
  • 2. 工具类(对反射拿到的属性对象数据转型)
  • 3. 业务服务类使用适配器设计模式

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

1. actionservlet核心控制器更改以上1,2点

  • action.xml 映射请求路径和服务类全路径
  • 描述action.xml 的数据结构
package com.lovely.mvc;/*** * @author echo lovely* * action.xml 映射数据, 加载xml中的类**/
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 {/*** 核心控制servlet* 根据访问方式 和 类的路径信息 到对应的servlet来处理*/private static final long serialVersionUID = 1L;Map<String, MapperAction> map = new HashMap<String, MapperAction>();@Overridepublic void init() throws ServletException {// 加载xml内容 调用具体服务类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 = (Action) c.newInstance();// 对request请求数据进行封装		// xxx服务类直接拿到 前台数据Map<String, String[]> requestMap = req.getParameterMap();Set<Entry<String,String[]>> entrySet = requestMap.entrySet();// 对表单提交过来的每个值 封装到xxxaction服务类中的属性for (Entry<String, String[]> entry : entrySet) {// 表单的名字String name = entry.getKey();// 表单的值 String[] formValue = entry.getValue();// 判断表单元素的名称是p.name 或者 是name 这里判断是 nameif (name.indexOf(".") == -1) {// 直接提交属性名 为xxxAction中的属性赋值try {Field field = c.getDeclaredField(name);field.setAccessible(true);// 属性的类型可能是 String int/Integer double/Double boolean Date/Timstamp Integer[]/int[] Double[]/doble[] 转型field.set(action, ConvertUtil.convert(field, formValue));} catch (NoSuchFieldException e) {//e.printStackTrace(); 可能没这个属性} catch (SecurityException e) {e.printStackTrace();}} else {// 提交的值 封装到对象中try {// p.name p.age 表单元素的名称写法  对象.属性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);}		// 取到二级对象 // f.name 取到name			// 父级属性类对象Class<?> ff = fieldEntity.getType();Field field = ff.getDeclaredField(split[1]);field.setAccessible(true);// 设置 p.name 的值 转型field.set(entity, ConvertUtil.convert(field, formValue));} catch (NoSuchFieldException e) {// e.printStackTrace();} 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 {/*** 把数据库查出来的string转换为对应的属性类型* @param f 属性对象* @param value rs结果集中返回的string值* @return 返回属性对象的值*/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);			// 把util日期转换成 sql 日期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 {// 属性对象 是Double Integer 之类的转型Class<?> type = f.getType();// getClass 得到本身类名路径 getType得到当前类型// System.out.println(type + "\t" + f.getClass() + "\t" + (type == f.getClass()));Constructor<?> con = type.getDeclaredConstructor(String.class);obj = con.newInstance(value);}			} catch (Exception e) {e.printStackTrace();}return obj;}/*** 封装的属性对象值可能是 各种类型滴 考虑转型...* @param f 要被赋值的属性对象* @param value 被转换的值* @return 转换属性对象对应类型的值*/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]);			// 把util日期转换成 sql 日期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 {// service服务方法接口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";}// 根据id查询票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";}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1013 数素数 (20分)

输入样例&#xff1a; 5 27 输出样例&#xff1a; 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 # -*- encoding: utf-8 -*- import mathdef get_primes(n):prime_list [1] * (n 1)for i in range(2, int(math.sqrt(n)) 1):if prime_list[i]…

1014 福尔摩斯的约会 (20分)

输入样例&#xff1a; 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm 输出样例&#xff1a; THU 14:04 # -*- coding: utf-8 -*- import stringweek {A: MON,B: TUE,C: WED,D: THU,E: FRI,F: SAT,G: SUN}hour {0:00, 1:01, 2:02, 3:03, 4:04, 5:05, 6:0…

MSSQL如何在没有主键的表中删除重复数据

MSSQL如何在没有主键的表中删除重复数据 原文:MSSQL如何在没有主键的表中删除重复数据为了对重复数据进行实验&#xff0c;下面建一个设计不太好&#xff08;没有主键&#xff09;表并插入了一些重复数据&#xff1a; create database testdbuse testdb ; go create table Dups…

1015 德才论 (25分)

输入样例&#xff1a; 14 60 80 10000001 64 90 10000002 90 60 10000011 85 80 10000003 85 80 10000004 80 85 10000005 82 77 10000006 83 76 10000007 90 78 10000008 75 79 10000009 59 90 10000010 88 45 10000012 80 100 10000013 90 99 10000014 66 60 输出样例&#…

1016 部分A+B (15分)

输入样例 1&#xff1a; 3862767 6 13530293 3 输出样例 1&#xff1a; 399 输入样例 2&#xff1a; 3862767 1 13530293 8 输出样例 2&#xff1a; 0 # -*- coding: utf-8 -*-if __name__ __main__:input_list input().split()a, d_a, b, d_b input_list[0], input_li…

马哥学习笔记二十七——IO复用

I/O动作模式  阻塞 非阻塞 I/O复用 信号驱动 异步 转载于:https://www.cnblogs.com/wangyongbin/p/3817353.html

1017 A除以B (20分)

输入样例&#xff1a; 123456789050987654321 7 输出样例&#xff1a; 17636684150141093474 3 # -*- coding: utf-8 -*- import redef big_division(a, b):q_list, r [], 0len_a len(a)for i in range(0, len_a):dividend 10 * r eval(a[i])q_list.append(dividend // …

Idea创建web项目,配置tomcat服务器

使用idea创建web项目 新下载的idea&#xff0c;需要启用插件&#xff0c;才可创建web项目 启用Java ee&#xff0c;servlet有web项目选项 创建项目 选好jdk&#xff0c;要配置好jdk环境变量https://blog.csdn.net/crossing2012/article/details/81292547 选路径 to…

CSS 最核心的几个概念

本文将讲述 CSS 中最核心的几个概念&#xff0c;包含&#xff1a;盒模型、position、float等。这些是 CSS 的基础&#xff0c;也是最经常使用的几个属性&#xff0c;它们之间看似独立却又相辅相成。为了掌握它们&#xff0c;有必要写出来探讨一下&#xff0c;如有错误欢迎指正。…

1018 锤子剪刀布 (20分)

输入样例&#xff1a; 10 C J J B C B B B B C C C C B J B B C J J 输出样例&#xff1a; 5 3 2 2 3 5 B B 本题有几个地方需要注意&#xff1a; 当甲乙没有赢&#xff0c;怎么输出&#xff0c;正确答案是都输出B&#xff0c;这个在题目中找不出线索&#xff0c;有点坑&am…

1020 月饼 (25分)

输入样例&#xff1a; 3 20 18 15 10 75 72 45 输出样例&#xff1a; 94.50 解题心得&#xff1a; 本题因为要排序&#xff0c;优先考虑使用二维数组和sorted最常用的模式&#xff1b;python在建立二维数组时有一个坑&#xff0c;就是[[]] * n中出现浅拷贝问题&#xff0c;…

在Java web中使用json

json包下载 下载jar包当然是下大厂滴 推荐Alibaba的fastjson推荐Google的gjson 本文讲fastjson https://github.com/alibaba/fastjson.git json的常见格式 key - value 键值对 {"key":"value"}多个key - value对 {"key1":"value"…

1019 数字黑洞 (20分)

输入样例 1&#xff1a; 6767 输出样例 1&#xff1a; 7766 - 6677 1089 9810 - 0189 9621 9621 - 1269 8352 8532 - 2358 6174 输入样例 2&#xff1a; 2222 解体心得&#xff1a; 在初次写str2list时没有考虑到输入是‘123’这样的情形&#xff1b; # -*- coding: …

再看数据库——(2)视图

概念 *是从用户使用数据库的观点来说的。 *从一个或多个表&#xff08;视图&#xff09;中导出来的 *一个虚表&#xff0c;或者说查询表 为什么要用视图呢&#xff1f; 一是简单&#xff0c;看到的就是需要的。视图不仅可以简化用户对数据的理解&#xff0c;也可以简化他们的操…

spring bean的创建,生命周期

1. 初探spring 什么是spring Spirng 是分层的Java se/ee应用full-stack&#xff08;web层mvc dao层jdbc模板 业务事务管理&#xff09;轻量级开源框架&#xff0c;以IoC(inverse of control :反转和控制) 和 AOP&#xff08;Aspect Oriented Programming: 面向切面编程&#xf…