简易版mvc框架

简易版框架

1.项目需求

用一个通用的控制器,进行开发一个web应用程序,只添加相应的配置,就可以通过控制器就可以调用相应的模型和视图的功能

2.初始设计
2.1项目结构

2.2项目搭建
2.3加载配置文件

1.加载配置文件beans标签的依赖

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.1</version>
</dependency>

2.用于加载核心文件----自定义文件mymvc.xml

​ 就像mvc框架的核心文件springmvc_config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<!--    一个bean就相当于一个controller对象-->
    <bean class="com.demomvc.web.controller.HelloController"/>
</beans>

3.定义一个关键的DispatcherServlet类,让这个类接收所有请求,并且加载配置文件

package com.demomvc.web.servlet;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
 * 用于处理请求和加载配置映射的控制器
 * @author miracle
 * @date 2022年, 05月, 04日, 11:29
 */
public class DispatcherServlet extends HttpServlet {
    /**
     * 调用之前,先读取配置文件的属性所指的类加载并创建出对象
     */
    @Override
    public void init() {
        //1.加载读取mymvc.xml配置文件
        InputStream in = getClass().getClassLoader().getResourceAsStream("mymvc.xml");
        //2.加载数据结构(树状的结构),
        SAXReader saxReader = new SAXReader();
        //3.创建对象,并保存下来
        List<Object> beans = new ArrayList<>();
        try {
            //返回一个document对象,一个树状的结构
            Document read = saxReader.read(in);
            //获取xml文件的根路径
            Element root = read.getRootElement();
            //获取根节点中的所有子节点
            List<Element> elements = root.elements();
            //读取每个子节点的class的值进行类加载对象
            for (Element element : elements) {
                //获取子节点的属性值--值对应的就是类的全称名称
                String s = element.attributeValue("class");
                //关键信息,创建对象
                Object  bean  = Class.forName(s).getConstructor().newInstance();
                //保存对象
                beans.add(bean);
                System.out.println("属性值 = " + s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.一个控制器类,HelloController类

​ 测试

public class HelloController {
    /**
     * 一个方法对应一个请求地址
     */
    @RequestMapping("/hello")
    public String hello(){
        //业务逻辑代码
        System.out.println("我已知晓了");
        return "1111";
    }
}

5.关键的注解@RequestMapper(自定义)

​ @ResponseMapper(可写可不写)

package com.demomvc.web.annotation;
import java.lang.annotation.*;
/** 
 * 用于映射规则:请求地址和那个对象的处理方法进行映射
 * @author Miracle
 */
@Documented
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    /**
     * url的地址
     */
    String value() default "";
}
package com.demomvc.web.annotation;
import java.lang.annotation.*;
/**
 * @author Miracle
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseBody {
    //设置响应体的编码方式
    String charSet() default "text/html; charset=UTF-8";
}
2.4初始化参数
 <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>com.demomvc.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
<!--        接收所有的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
3.结构设计
3.1项目结构

3.2处理器设计

1.创建一个Handler对象(进行url对象的映射)

package com.demomvc.web.processor;
import java.lang.reflect.Method;
/**
 * 用于处理那个类和那个方法进行映射
 * @author miracle
 */
public class Handler {
    /**
     * 类的对象
     */
    private Object object;
    /**
     * 类中的方法
     */
    private Method method;
    public Handler() {
    }
    public Handler(Object object, Method method) {
        this.object = object;
        this.method = method;
    }
    public Object getObject() {
        return object;
    }
    public void setObject(Object object) {
        this.object = object;
    }
    public Method getMethod() {
        return method;
    }
    public void setMethod(Method method) {
        this.method = method;
    }
    @Override
    public String toString() {
        return "Handler{" +
                "object=" + object +
                ", method=" + method +
                '}';
    }
}

2.在 DispatcheServlet类的init()的方法补全

public void init() {
        //1.加载读取mymvc.xml配置文件
        InputStream in = getClass().getClassLoader().getResourceAsStream("mymvc.xml");
        //2.加载数据结构(树状的结构),
        SAXReader saxReader = new SAXReader();
        //3.创建对象,并保存下来
        List<Object> beans = new ArrayList<>();
        try {
            //返回一个document对象,一个树状的结构
            Document read = saxReader.read(in);
            //获取xml文件的根路径
            Element root = read.getRootElement();
            //获取根节点中的所有子节点
            List<Element> elements = root.elements();
            //读取每个子节点的class的值进行类加载对象
           for (Method method : methods) {
                //判断方法上是否有注解
                if(method.isAnnotationPresent(RequestMapping.class)){
                //获取方法上的注解
                RequestMapping declaredAnnotation = 					                               method.getDeclaredAnnotation(RequestMapping.class);
                //获取注解的值--url
                String value = declaredAnnotation.value();
                //添加
                handlers.put(value, new Handler(bean,method));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.控制器和处理器(HandlerMapping)进行映射关联,process(List beans)

package com.demomvc.web.processor;
import com.demomvc.web.annotation.RequestMapping;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * url和方法进行映射
 * @author miracle
 * @date 2022年, 05月, 06日, 10:47
 */
public class HandlerMapping {
    /**
     * 一个key对应一个方法的映射
     */
    private final Map<String, Handler> handlers = new HashMap<>();

    /**
     * 获取path对应的Handler对象
     * @param path 请求路径
     * @return handler对象
     */
    public Handler getHandler(String path){
        return handlers.get(path);
    }
    /**
     * path和handler对象进行捆绑
     * @param beans Controller对象
     */
    public void process(List<Object> beans) {
        //遍历集合中的对象
        for (Object bean : beans) {
            //获取实例化对象
            Class<?> aClass = bean.getClass();
            //获取声明的方法
            Method[] methods = aClass.getDeclaredMethods();

            for (Method method : methods) {
                //获取方法上的注解
                method.getDeclaredAnnotationsByType(RequestMapping.class);
                RequestMapping declaredAnnotation = method.getDeclaredAnnotation(RequestMapping.class);
                //获取注解的值--url
                String value = declaredAnnotation.value();
                //添加
                handlers.put(value, new Handler(bean,method));
            }
        }
        System.out.println("handlers = " + handlers);
    }
}

到这里地址和对象就可以进行映射了,还有一个重点(servlet和控制器进行连接)

这里的业务层比较多。。。。。

3.3界面跳转模块开发

​ 这里实现一个简单的业务
1.在DispatcherServlet中的serivce方法进行补全

 public void service(ServletRequest req, ServletResponse res) {
        //强制HttpServletRequest对象
        HttpServletRequest request=(HttpServletRequest)req;
        HttpServletResponse response=(HttpServletResponse)res;
        //获取请求路径
        String requestURI= request.getRequestURI();
        System.out.println("uri=" + requestURI);
        //拿到地址和控制器对象的映射
        Handler handler = handlerMapping.getHandler(requestURI);
        //判断是否为空
        Optional.ofNullable(handler).ifPresent(u->{
            //不为空是执行方法的内容
            Method method = u.getMethod();
            try {
                String invoke = (String) method.invoke(handler.getObject());
                if (method.isAnnotationPresent(ResponseBody.class)) {
                    //获取相应编码方式
                    String s = method.getAnnotation(ResponseBody.class).charSet();
                    //设置编码方式
                    response.setContentType(s);
                    //说明返回的结果是数据
                    response.getWriter().println("执行的结果:"+invoke);
                }else{
                //    返回的结果是页面
                    if (invoke.startsWith("redirect:")) {
                        //重定向
                        response.sendRedirect(invoke.substring(invoke.indexOf(":")+1));
                    }else {
                        //转发
                        request.getRequestDispatcher(invoke).forward(request,response);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

ndRedirect(invoke.substring(invoke.indexOf(“:”)+1));
}else {
//转发
request.getRequestDispatcher(invoke).forward(request,response);
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值