当前位置:网站首页>自定义MVC(上)

自定义MVC(上)

2022-07-23 05:40:00 _Leaf1217

目录

一、反射版增删改查

二、自定义MVC框架工作原理图

三、编写自定义MVC框架


一、反射版增删改查

1.1 小前言

平常我们没有接触任何框架知识的时候,

我们写Web项目都是在Jsp直接跳转向servlet发送请求,

基本要实现一个功能就要建立一个servlet方便请求,但是这样会有一系列的问题,如下:

    <!-- 
        问题:
            1、建的类过多;
            2、新增业务的话需要修改、增加前面的代码;
            3、反射相关的代码在每一个实体类对应的servlet中都存在;
            4、每一个servlet中都有doget、doset方法。
     -->

繁杂的代码过多,不利于我们开发,因此,今天我们来一步步尝试优化

乃至自己编写一个MVC框架。

1.2 优化servlet类

例:A同学提出可以利用传值然后根据传过来的方法名判断要调用那个方法;

问题:

2、当我们的业务需求越来越多,需要不断的改变判断的代码,照样不够友好。

于是Leaf同学就提出了可以使用反射!(hhh开个玩笑) 

确实,我们要想不改变--->判断传过来的值的代码的话就要--->想到反射的动态调用方法

反射的一个特点就是不管你传了什么,但是反正只要你传了谁就调用谁。

所以我们尝试一下使用反射,不会使用反射的小伙伴可以参考一下我之前的文章噢,

点这里可以直接抵达:Java反射机制的基本使用__Leaf1217的博客-CSDN博客

这里直接放上servlet的代码了:

package com.leaf.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.filters.AddDefaultCharsetFilter;

@WebServlet("/BookServlet")
public class BookServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//设置编码方式
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		
		//获取输出流out
		PrintWriter out = response.getWriter();
		
		//为了区分当前请求方法,获取传过来的方法名
		String ff = request.getParameter("methodName");
		
		//拿到类类
		Class<? extends BookServlet> cl = this.getClass();
		try {
			//拿到方法对象
			Method m = cl.getDeclaredMethod(ff, HttpServletRequest.class,HttpServletResponse.class);
			//打开权限
			m.setAccessible(true);
			//调用当前类实例的方法
			m.invoke(this, request,response);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

	private void add(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('增加成功!');location.href='Test.jsp'</script>");
	}
	
	private void delete(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('删除成功!');location.href='Test.jsp'</script>");
	}
	
	private void update(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('修改成功!');location.href='Test.jsp'</script>");
	}
	
	private void list(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('查询成功!');location.href='Test.jsp'</script>");
	}

}

1.3 测试请求

    <h3>反射版增删改查</h3>
    <a href="BookServlet?methodName=add">增加</a>
    <a href="BookServlet?methodName=delete">删除</a>
    <a href="BookServlet?methodName=update">修改</a>
    <a href="BookServlet?methodName=list">查询</a>

 

 


二、自定义MVC框架工作原理图

虽然我们利用反射优化了servlet,但是还是存在一些问题:

 3、反射相关的代码在每一个实体类对应的servlet中都存在;

 4、每一个servlet中都有doget、doset方法。

所以,我们需要进一步的进行优化,那就是自定义一个MVC框架,

而在我们正式编写之前就需要了解一下我们设计的这个框架的工作原理图

2.1 工作原理图

 

我们一起来看看分析一下这个工作原理图,运行流程

 从浏览器发送请求:

 中央控制器(Action)--->子控制器(Action)--->实现处理的方法(execute)--->业务逻辑层处理(方法)


三、编写自定义MVC框架

根据我们一起分析的框架工作运行原理后,我们就可以开始逐步编码了;

3.1 建立子控制器接口:Action

package com.leaf.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 子控制器:
 * 	对应请求的处理人
 * @author Leaf
 *
 * 2022年6月25日 上午9:05:41
 */
public interface Action {
	
	void execute(HttpServletRequest req,HttpServletResponse resp);
	
}

上面这个子控制器就是用来处理不同的请求的请求人,任何人都需要找他,

然后再由他推荐适合你的处理方法;所以我们还需要一个类实现这个万能的寻找方法:

3.2 建立实现寻找方法的类:ActionSupport

package com.leaf.mvc;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.leaf.servlet.BookServlet;

public class ActionSupport implements Action {

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse resp) {
		
		//为了区分当前请求方法,获取传过来的方法名
		String ff = req.getParameter("methodName");
		
		//拿到类类
		Class<? extends ActionSupport> cl = this.getClass();
		try {
			//拿到方法对象
			Method m = cl.getDeclaredMethod(ff, HttpServletRequest.class,HttpServletResponse.class);
			//打开权限
			m.setAccessible(true);
			//调用当前类实例的方法
			m.invoke(this, req,resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

 而这个方法类里面就是使用我们前面用过的反射来实现的~是谁的请求就调用谁的方法

所以我们就直接建立一个我们真正实现业务的方法的类:BookAction

3.3 建立方法类:BookAction

package com.leaf.servlet;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.leaf.mvc.ActionSupport;

/**
 * 放真正处理业务的方法类
 * @author Leaf
 *
 * 2022年6月25日 上午11:01:21
 */
public class BookAction extends ActionSupport {
	
	private void add(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('增加成功!');location.href='Test.jsp'</script>");
	}
	
	private void delete(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('删除成功!');location.href='Test.jsp'</script>");
	}
	
	private void update(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('修改成功!');location.href='Test.jsp'</script>");
	}
	
	private void list(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		//获取输出流out
		PrintWriter out = resp.getWriter();
		out.print("<script>alert('查询成功!');location.href='Test.jsp'</script>");
	}
	
}

3.4 建立中央控制器:DispatcherServlet

最后我们再来建立一个最初接收浏览器请求与方法名的类:中央控制器,就会理解了。

这个中央控制器的命名Leaf就不搞和工作原理图一样的了,但是地位是一样的;

package com.leaf.mvc;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.leaf.servlet.BookAction;

/**
 * 中央控制器
 * 	主要职能:接收浏览器请求,找到对应的处理人;
 * @author Leaf
 *
 * 2022年6月25日 上午9:04:15
 */
//凡是以action结尾的请求的要经过总控制器
@WebServlet("*.action")
public class DispatcherServlet extends HttpServlet {
	
	//定义一个变量储存找到的action
	private Map<String, Action> actions = new HashMap<String, Action>();
	
	@Override
	public void init() throws ServletException {
		//这里是请求的servlet,暂时定死,下篇文章进行优化。
		actions.put("/Book", new BookAction());
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);	
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//拿到路径
		String uri = req.getRequestURI();
		//截取拿到--/Book---,就是最后一个/和最后一个.之间
		uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
		//拿到请求的action
		Action action = actions.get(uri);
		//执行前面定义的接口的方法
		action.execute(req, resp);
	}
	
}

3.5 测试请求

最后我们来试一下在前台请求测试一下是否能够实现;

    <h3>框架版增删改查</h3>
    <a href="Book.action?methodName=add">增加</a>
    <a href="Book.action?methodName=delete">删除</a>
    <a href="Book.action?methodName=update">修改</a>
    <a href="Book.action?methodName=list">查询</a>

运行:

 


OK,好啦,今天Leaf带来的有关自定义MVC框架的学习笔记分享就到这里啦,喜欢的可以关注一下,后期可以一起学习!有不懂的地方也欢迎评论或者私信问我噢~下次见啦!!!

原网站

版权声明
本文为[_Leaf1217]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_63492318/article/details/125455808