1. 介绍

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

我们今天就来搭建一个自己的从URL访问到JAVA控制器的简单框架。

2. 准备

首先,我们应该对JAVA的反射机制、Servlet最基本原理、以及JAVA注解有所了解。不了解的读着可先学习:

3. 实现思路

  • 首先,我们要将URL访问请求和我们的后台JAVA方法形成一一对应关系。
  • 然后,我们需要在tomcat容器启动网站加载的时候获取上一步骤中记录的一一对应关系,并记录下来。
  • 最后,完成URL访问到后台JAVA方法的跳转。

4. 实现方式:

(1)通过注解来标记出URL到后台JAVA方法的映射关系。

A.    定义注解:这个注解可以标注在类和方法上。

package com.mvc.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface URLMapping {
public String url() default "";
}

B.    JAVA后台中针对URI的相应方法:

package com.mvc.controller;

import com.mvc.annotation.URLMapping;

@URLMapping(url="/Say")
public class SayController{ @URLMapping(url="/Hello")
public String SayHello(){
System.out.println("Hello");
return "Hello";
} @URLMapping(url="/Hi")
public String SayHi(){
System.out.println("Hi");
return "Hi";
} }

通过注解,我们可以看出我们拟定将来用SayController这个类来相应/Say/***的URL。其中SayHello方法相应的URL是/Say/Hello,SayHi方法相应的URL是/Say/Hi。

这样,我们就定义好了URL和JAVA后台方法的对应关系。接下来我们要实现如果完成这种对应关系的跳转

(2)实现URL到JAVA后台方法的跳转

A.    定义我们用来存储URL到JAVA后台方法对应关系的基础数据类型:

package com.mvc.base;

public class MVCBase {
private String url; //我们将来要访问的URL
private String controller; //这个URL对应的后台JAVA类
private String method; //这个URL对应的后台方法名称 public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getController() {
return controller;
}
public void setController(String controller) {
this.controller = controller;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}

B.    通过监听器在tomcat启动的时候收集URL到JAVA后台方法的对应关系并存储起来:

package com.mvc.listener;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.mvc.annotation.URLMapping;
import com.mvc.base.MVCBase; public class UrlMappingCollection implements ServletContextListener {
//被注解了URLMapper的类方法列表
private static List<MVCBase> mvcBases; //我们要扫描的Controller列表
private final String[] controllerList = {"com.mvc.controller.SayController"}; @Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
} @Override
public void contextInitialized(ServletContextEvent sce) {
mvcBases = new ArrayList<MVCBase>(); try {
//循环所有需要扫描的Controller
for (int i = 0; i < controllerList.length; i++) {
String controllerName = controllerList[i]; String classURL = "";
String methodURL = ""; Class<?> clazz = Class.forName(controllerName); //获取Controller类
if (clazz.isAnnotationPresent(URLMapping.class)) { //class被标记了URLMapping注解
classURL = ((URLMapping) clazz.getAnnotation(URLMapping.class)).url();
}
//获取method列表
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(URLMapping.class)) {
                    //method被标记了URLMapping注解
methodURL = ((URLMapping) method.getAnnotation(URLMapping.class)).url(); MVCBase mvcBase = new MVCBase();
mvcBase.setUrl(classURL+methodURL);
mvcBase.setController(controllerName);
mvcBase.setMethod(method.getName()); mvcBases.add(mvcBase);
}
}
}
}
catch (Exception e) { }
} public static List<MVCBase> getMvcBases() {
return mvcBases;
} }
    • mvcBases就是将来我们要将URL到JAVA后台方法对应关系存储到的地方。我们将他定义为静态方法,以便后续我们直接访问获取。
    • controllerList是用来告诉监听器,我们要从哪些类中获取URL到JAVA后台方法的对应关系。因为在程序设计期我们就已经知道了,所以定义为final属性。
    • 然后在监听器初始化的时候,循环controllerList中的class,根据注解的信息来收集URL到JAVA后台方法的对应关系并存储到mvcBases中。

C.    配置Servlet访问:

首先我们要准备我们的Servlet类,将来所有的URL请求都要跳转到这个Servlet中。

package com.mvc.servlet;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mvc.base.MVCBase;
import com.mvc.listener.UrlMappingCollection; public class ServletCenter extends HttpServlet {
private static final long serialVersionUID = -1163369749078348562L; private void doTransfer(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException, ClassNotFoundException,
SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
                   InstantiationException    {
for (MVCBase mvcBase : UrlMappingCollection.getMvcBases()) {
if (req.getRequestURI().equals(
                               req.getServletContext().getContextPath()+mvcBase.getUrl())) {
Class<?> clazz = Class.forName(mvcBase.getController());
Method method = clazz.getMethod(mvcBase.getMethod());
method.invoke(clazz.newInstance());
}
}
} @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
              throws ServletException, IOException {
try {
doTransfer(req, resp);
} catch (Exception e) { }
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
              throws ServletException, IOException {
try {
doTransfer(req, resp);
} catch (Exception e) { }
}
}

可以看到,doGet和doPost里面都执行的是doTransfer方法。相应的web.xml配置为:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<listener>
<listener-class>com.mvc.listener.UrlMappingCollection</listener-class>
</listener> <servlet>
<servlet-name>main</servlet-name>
<servlet-class>com.mvc.servlet.ServletCenter</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

在web.xml中,我们将所有的请求都跳转到com.mvc.servlet.ServletCenter中。

5. 测试

将MyMVC部署到tomcat容器中,启动tomcat,输入http://127.0.0.1:8080/MyMVC/Say/Hello 以及http://127.0.0.1:8080/MyMVC/Say/Hi 就可以看到后台输出的Hello和Hi了。

6. 目录结构

JavaWeb之搭建自己的MVC框架(一)的更多相关文章

  1. JavaWeb之搭建自己的MVC框架(二)

    1. 前言 在 JavaWeb之搭建自己的MVC框架(一) 中我们完成了URL到JAVA后台方法的最基本跳转.但是实际操作中会发现有一个不方便的地方,现在在com.mvc.controller包中只有 ...

  2. JavaWeb之搭建自己的MVC框架

    https://blog.csdn.net/anita9999/article/details/83378111 自己写一个mvc框架吧(一) https://www.cnblogs.com/heba ...

  3. JavaWeb之搭建自己的MVC框架(三)

    1. 前言         在前两节的内容中,我们完成了一个基本的框架搭建.但是如果我们在前端请求中增加参数,我们要怎么传递到后台方法呢?接下来我们就来研讨这部分内容. 2. 实现         ( ...

  4. 使用PHP搭建自己的MVC框架

    一.什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  5. Java Servlet开发的轻量级MVC框架最佳实践

    在Servlet开发的工程实践中,为了减少过多的业务Servlet编写,会采用构建公共Servlet的方式,通过反射来搭建轻量级的MVC框架,从而加快应用开发. 关于Servlet开发的基础知识,请看 ...

  6. Spring MVC 框架的架包分析,功能作用,优点

    由于刚搭建完一个MVC框架,决定分享一下我搭建过程中学习到的一些东西.我觉得不管你是个初级程序员还是高级程序员抑或是软件架构师,在学习和了解一个框架的时候,首先都应该知道的是这个框架的原理和与其有关j ...

  7. ASP.NET MVC搭建项目后台UI框架—1、后台主框架

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  8. ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...

  9. Spring MVC篇一、搭建Spring MVC框架

    本项目旨在搭建一个简单的Spring MVC框架,了解Spring MVC的基础配置等内容. 一.项目结构 本项目使用idea intellij创建,配合maven管理.整体的目录结构如图: 其中ja ...

随机推荐

  1. InnoDB 和 MyISAM的索引区别

    MyISAM索引实现 MyISAM索引文件和数据文件是分离的,索引文件的data域保存记录所在页的地址(物理存储位置),通过这些地址来读取页,进而读取被索引的行数据. MyISAM的索引原理图如下,C ...

  2. HihoCoder 1246:王胖浩与环

    #1246 : 王胖浩与环 时间限制:6000ms 单点时限:1000ms 内存限制:256MB 描述 王胖浩有一个环,环上有n个正整数.他有特殊的能力,能将环切成k段,每段包含一个或者多个数字. 对 ...

  3. 2-10 就业课(2.0)-oozie:12、cm环境搭建的基础环境准备

    8.clouderaManager5.14.0环境安装搭建 Cloudera Manager是cloudera公司提供的一种大数据的解决方案,可以通过ClouderaManager管理界面来对我们的集 ...

  4. 035、Java中自增之++在后面的写法

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  5. 印度第一颗CPU横空出世!阵势庞大

    我们忙着推进国产芯片的同时,隔壁的印度也没闲着.作为印度顶级高校的印度理工学院(IIT)之马德拉斯校区已经发布了其首颗处理器“Shakti”(代表女性力量的印度神话人物)的SDK软件开发包,并承诺会很 ...

  6. 5 —— node —— 响应一段中文给客户端

    const http = require('http'); const server = http.createServer(); server.on('request',function(req,r ...

  7. Python中的numpy函数的使用ones,zeros,eye

    在看别人写的代码时,看到的不知道的函数,就在这里记下来. 原文是这样用的: weights = ones((numfeatures,1)) 在python中help(): import numpy a ...

  8. JPA#实体属性转换器

    __震惊,一下内容竟然是空白 用途 (自动转换数据库字段和实体属性间的最佳取值): - 1. POJO持久化到数据库表中的时候,对某些特殊属性处理后,用处理过的值作为数据库字段的值. 2. 从数据库查 ...

  9. 72.Python中ORM聚合函数详解:Avg,aggregate,annotate

    聚合函数: 如果你用原生SQL语句,则可以使用聚合函数提取数据.比如提取某个商品销售的数量,那么就可以使用Count,如果想要知道销售的平均价格,那么就可以使用Avg. 聚合函数是通过aggregat ...

  10. 4. Linux 集群安装

    1. 配置yum yum clean all yum makecache yum install wget 2.安装JDK (1) 将jdk-7u60-linux-i586.rpm通过WinSCP上传 ...