手写SpringMVC开发框架

运行环境

JDK :17
IntelliJ IDEA : 2022.3
Tomcat:8.5.86

前期工作

  1. 先创建一个新的Maven项目,按照图示操作:
    在这里插入图片描述
  2. 在这里我们选择Maven Archetype选项,写好项目名称:Handwriting-SpringMVC,以及路径并选好Archetype为webapp。点击creat创建。
    在这里插入图片描述
  3. 编辑环境:按照图示选择对应的选项,最后点击OK即可!
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    注意:在开始本项目前你需要了解一些MVC常用注解及其流程。

项目结构

项目类继承关系
在这里插入图片描述

main结构

在这里插入图片描述
在这里插入图片描述
java
com.bruce.controller:用户自定义的SpringMVC控制层
com.bruce.pojo:用户自定义的对象(User)
com.bruce.service:用户自定义的接口和实现类(UserService、UserServiceImpl)

com.springmvc.annotation:SpringMVC的相关注解
com.springmvc.context:Spring容器
com.springmvc.exception:用户自定义异常
com.springmvc.handler:负责处理HTTP请求的组件
com.springmvc.servlet:SpringMVC的核心控制器
com.springmvc.xml:解析springmvc.xml文件

resources
目前只有一个springmvc.xml文件

webapp
WEB-INF:Java的Web应用的安全目录


test结构
在这里插入图片描述
java
com.bruce.test:测试XML解析工具

resources
NULL


两个重要的XML文件和一个JSP文件:

  • springmvc.xml:SpringMVC的配置文件
  • web.xml:web应用的配置文件。
  • user.jsp:后面用来跳转的JSP文件
  • index.jsp:自动生成的,可以不用管 (非必须)
    在这里插入图片描述

项目流程

请添加图片描述
请添加图片描述

  1. 在启动Tomcat后就会自动解析webapp中的WEB-INF中的web.xml,所以我们先配置web.xml
  2. 创建DispatcherServlet(前端控制器)和WebApplicationContext(spring容器)
  3. 接下来会执行DispatcherServlet中的init()方法,创建Spring容器,并从springmvc.xml文件中读取base-package中的包路径,并生成对象,存放在iocMap
  4. 当我们的对象生成完毕之后,就会执行initHandlerMappring()方法,遍历spring容器中的iocMap,遍历其中所有的Controller类型的对象的Class对象,然后判断每一个Class对象中的所有方法,将有@RequestMapping注解的方法封装成一个MyHandler对象,其中包含@RequestMapping注解的名字(url),Controller对象(controller),该方法(method)。然后将这个MyHandler对象放到handlerList集合中。
  5. 当有get请求的时候,就会执行DispatcherServlet中的doGet()方法。遍历handlerList,寻找浏览器url请求路径和我们MyHandler对象中储存的@RequestMapping中相等的对象,然后定义一个参数的Object数组,经过一系列的关于@RequestParam参数的判断,将浏览器请求路径中的参数放到对应位置的Object数组中,然后通过handler.getMethod().invoke()执行这个方法就可以调用控制中的方法并获得返回值,然后做一个返回值类型的判断:String还是Json。最后做跳转JSP或返回JSON数据的代码逻辑。
  6. 最后运行的结果如下,成功跳转到我们的user.jsp文件中:

在这里插入图片描述

注意:整体的流程最好自己debug一遍,印象会更深刻!


pom.xml文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>Handwriting-SpringMVC</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>Handwriting-SpringMVC Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!--解析XML文件-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>

        <!--JSON转换工具-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.16.1</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>Handwriting-SpringMVC</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    
                    <!--JDK8新特性,能够获取到方法中的参数-->
                    <!--[request, response, name]-->
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>

                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

main


com.bruce.controller包:

UserController类:

package com.bruce.controller;

import com.bruce.pojo.User;
import com.bruce.service.UserService;
import com.springmvc.annotation.Autowired;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.RequestMapping;
import com.springmvc.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: 控制器
 * @Version: 1.0
 **/
@Controller
public class UserController {

    // 持有业务逻辑层的对象
    @Autowired
    UserService userService;

    @RequestMapping("/user/query")
    public String findUsers(HttpServletRequest request, HttpServletResponse response, String name) {
        // 处理响应的中文乱码问题
        response.setContentType("text/html;charset=utf-8");
        String message = userService.getMessage(name);
        request.setAttribute("message",message);
        //转发到user.jsp
        return "forward:/user.jsp";

    }

    @RequestMapping("/user/queryjson")
    @ResponseBody
    public List<User> queryUsers(HttpServletRequest request, HttpServletResponse response, String name){
        return userService.findUsers(name);
    }

}

com.bruce.pojo包:

User类:

package com.bruce.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: TODO
 * @Version: 1.0
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private Integer id;
    private String name;
    private String pass;

}

com.bruce.service包:

UserService接口:

package com.bruce.service;

import com.bruce.pojo.User;

import java.util.List;

public interface UserService {

    List<User> findUsers(String name);

    String getMessage(String name);

}

com.bruce.service.impl包:

UserServiceImpl类:

package com.bruce.service.impl;

import com.bruce.pojo.User;
import com.bruce.service.UserService;
import com.springmvc.annotation.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: UserService的实现类
 * @Version: 1.0
 **/
@Service  // 默认就是类名首字母小写
    public class UserServiceImpl implements UserService {
    @Override
    public List<User> findUsers(String name) {
        // 模拟数据
        List<User> users = new ArrayList<>();
        users.add(new User(1,"老王","admin"));
        users.add(new User(2,"小王","12345"));
        return users;
    }

    @Override
    public String getMessage(String name) {
        return "我是getMessage方法," + name;
    }
}

com.springmvc.annotation包:

Autowired注解:

package com.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.FIELD) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

    String value() default "";
}

Controller注解:

package com.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.TYPE) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {

    String value() default "";
}

RequestMapping注解:

package com.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {

    String value() default "";
}

RequestParm注解:

package com.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.PARAMETER) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParm {

    String value() default "";
}

ResponseBody注解:

package com.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {

}

Service注解:

package com.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.TYPE) // 元注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {

    String value() default "";
}

com.springmvc.context包:

WebApplicationContext类:Spring容器

package com.springmvc.context;

import com.springmvc.annotation.Autowired;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.Service;
import com.springmvc.exception.ContextException;
import com.springmvc.xml.XmlParser;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: Spring容器
 * @Version: 1.0
 **/
public class WebApplicationContext {

    // classpath:springmvc.xml
    String contextConfigLocation;
    List<String> classNameList = new ArrayList<>();

    // Spring的Ioc容器
    public Map<String, Object> iocMap = new ConcurrentHashMap<>();

    public WebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    /**
     * 初始化Spring容器
     */
    public void refresh() {
        // 1.解析springmvc.xml文件
        // split方法用于将字符串根据指定的正则表达式进行拆分,这里得到的是springmvc.xml
        String basePackage = XmlParser.getbasePackage(contextConfigLocation.split(":")[1]);
        // 这里通过逗号分隔成了两个字符串:com.bruce.service 和 com.bruce.controller
        String[] basePackages = basePackage.split(",");
        if (basePackages.length > 0) {

            for (String pack : basePackages) {
                // com.bruce.service
                // com.bruce.controller
                excuteScanPackage(pack);
            }

        }
        System.out.println("扫描后的结果是:" + classNameList);
        // 2.实例化Spring容器中的bean
        excuteInstance();
        // Ioc容器中的对象是:
        System.out.println("spring的Ioc容器对象是:" + iocMap);
        // 3.需要实现spring容器中对象的注入
        excuteAutowired();

    }


    /**
     * 扫描包
     */
    public void excuteScanPackage(String pack) {
        //  /com/bruce/service
        URL url = this.getClass().getClassLoader().getResource("/" + pack.replaceAll("\\.", "/"));
        String path = url.getFile();
        File dir = new File(path);
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                // 当前是一个文件目录
                excuteScanPackage(pack + "." + f.getName());
            } else {
                // 文件目录下文件  获取全路径
                String className = pack + "." + f.getName().replaceAll(".class", "");
                classNameList.add(className);
            }
        }
    }

    /**
     * 实例化Spring容器中的bean对象
     */
    public void excuteInstance() {
        if (classNameList.size() == 0) {
            // 没有扫描到需要实例化的类
            throw new ContextException("没有要实例化的class!");
        }
        try {
            for (String className : classNameList) {
                Class<?> clazz = Class.forName(className);
                if (clazz.isAnnotationPresent(Controller.class)) {
                    // 控制层的类  com.bruce.controller
                    // UserController -> userController 控制层对象的名字
                    String beanName = clazz.getSimpleName().substring(0, 1).toLowerCase() + clazz.getSimpleName().substring(1);
                    iocMap.put(beanName, clazz.newInstance());
                } else if (clazz.isAnnotationPresent(Service.class)) {
                    // 业务逻辑层的类 com.bruce.service.impl
                    Service serviceAnnotation = clazz.getAnnotation(Service.class);
                    String beanName = serviceAnnotation.value();
                    if ("".equals(beanName)) {
                        Class<?>[] interfaces = clazz.getInterfaces();
                        for (Class<?> c1 : interfaces) {
                            String beanName1 = c1.getSimpleName().substring(0, 1).toLowerCase() + c1.getSimpleName().substring(1);
                            // 接口名字作为beanName
                            iocMap.put(beanName1, clazz.newInstance());
                        }
                    } else {
                        iocMap.put(beanName, clazz.newInstance());
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 实现spring容器中的对象的依赖注入
     */
    private void excuteAutowired() {
        try {
            if (iocMap.isEmpty()) {
                throw new ContextException("没有找到初始化的bean对象");
            }
            // Map的一种迭代方法
            for (Map.Entry<String, Object> entry : iocMap.entrySet()) {
                // 获取到了一个一个对象名称
                String key = entry.getKey();
                // 获取到了一个一个对象实例
                Object bean = entry.getValue();

                Field[] declaredFields = bean.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    if (declaredField.isAnnotationPresent(Autowired.class)) {
                        Autowired autowiredAnnotation = declaredField.getAnnotation(Autowired.class);
                        String beanName = autowiredAnnotation.value();

                        // 进一步判断是否设置了 value 属性,如果未设置,则根据字段的类型推断 bean 的名称。
                        if (beanName.equals("")) {
                            // 这个拿到的其实是属性类的全名称
                            Class<?> type = declaredField.getType();
                            // 做剪枝操作
                            beanName = type.getSimpleName().substring(0, 1).toLowerCase() + type.getSimpleName().substring(1);

                        }

                        // 暴力反射,因为Controller层的属性类有可能是私有的
                        declaredField.setAccessible(true);
                        // 属性注入  调用反射给属性赋值
                        declaredField.set(bean, iocMap.get(beanName));
                    }
                }

            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

com.springmvc.exception包:

ContextException类:自定义异常

package com.springmvc.exception;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: 自定义异常
 * @Version: 1.0
 **/
public class ContextException extends RuntimeException {

    public ContextException(String message) {
        super(message);
    }

    public ContextException(Throwable cause) {
        super(cause);
    }

    @Override
    public String getMessage() {
        return super.getMessage();
    }
}

com.springmvc.handler包:

MyHandler类:自定义的处理器对象

package com.springmvc.handler;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Method;

/**
 * @Author: Juechen
 * @Date: 2024/4/25
 * @Description: 自定义的处理器对象
 * @Version: 1.0
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyHandler {

    private String url;
    private Object controller;
    private Method method;

}

com.springmvc.servlet包:

DispatcherServlet类:SpringMVC的核心控制器

package com.springmvc.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.RequestMapping;
import com.springmvc.annotation.RequestParm;
import com.springmvc.annotation.ResponseBody;
import com.springmvc.context.WebApplicationContext;
import com.springmvc.exception.ContextException;
import com.springmvc.handler.MyHandler;

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.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: SpringMVC的核心控制器
 * @Version: 1.0
 **/
public class DispatcherServlet extends HttpServlet {

    private WebApplicationContext webApplicationContext;

    // 存储url和对象方法的映射
    List<MyHandler> handlerList = new ArrayList<>();

    @Override
    public void init() throws ServletException {
        // 1.Servlet初始化的时候,读取初始化的参数 classpath:springmvc.xml
        String contextConfigLocation = this.getServletConfig().getInitParameter("contextConfigLocation");
        // 2.创建Spring容器
        webApplicationContext = new WebApplicationContext(contextConfigLocation);
        // 3.初始化Spring容器
        webApplicationContext.refresh();
        // 4.初始化请求映射  /user/query ----> Controller ----> method ----->parameter
        initHandlerMappring();
        System.out.println(handlerList);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 进行请求分发处理
        excuteDispatch(req, resp);

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);

    }

    /**
     * 初始化请求映射
     */
    private void initHandlerMappring() {

        //判断Iocmap中是否有bean对象
        if (webApplicationContext.iocMap.isEmpty()) {
            throw new ContextException("Spring容器为空");
        }

        for (Map.Entry<String, Object> entry : webApplicationContext.iocMap.entrySet()) {
            Class<?> clazz = entry.getValue().getClass();
            if (clazz.isAnnotationPresent(Controller.class)) {
                Method[] declaredMethods = clazz.getMethods();
                for (Method declaredMethod : declaredMethods) {
                    if (declaredMethod.isAnnotationPresent(RequestMapping.class)) {
                        RequestMapping requestMappingAnnotation = declaredMethod.getAnnotation(RequestMapping.class);
                        //  ("/user/query")
                        String url = requestMappingAnnotation.value();
                        // 构造一个自定义的处理器对象
                        MyHandler handler = new MyHandler(url, entry.getValue(), declaredMethod);
                        handlerList.add(handler);

                    }
                }
            }
        }
    }

    /**
     * 请求的分发处理
     */
    public void excuteDispatch(HttpServletRequest req, HttpServletResponse resp) {
        MyHandler handler = getHandler(req);
        try {
            if (handler == null) {
                resp.getWriter().print("<h1>404 NOT FOUND!</h1>");
            } else {

                Class<?>[] parameterTypes = handler.getMethod().getParameterTypes();
                //定义一个参数的数组
                Object[] params = new Object[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> parameterType = parameterTypes[i];
                    if ("HttpServletRequest".equals(parameterType.getSimpleName())) {
                        params[i] = req;
                    } else if ("HttpServletResponse".equals(parameterType.getSimpleName())) {
                        params[i] = resp;
                    }

                }

                // 获取请求中的参数集合
                Map<String, String[]> parameterMap = req.getParameterMap();
                for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                    String name = entry.getKey(); // "name"
                    String value = entry.getValue()[0];  //  "bruce"
                    int index = hasRequestParam(handler.getMethod(), name);
                    if (index != -1) {
                        params[index] = value;
                    } else {
                        // 不加@RequestParam的情况
                        List<String> names = getParameterNames(handler.getMethod());
                        System.out.println(names);
                        for (int i = 0; i < names.size(); i++) {
                            if (name.equals(names.get(i))) {
                                params[i] = value;
                                break;
                            }
                        }
                    }

                }

                //调用控制中的方法
                Object result = handler.getMethod().invoke(handler.getController(), params);
                if (result instanceof String) {
                    // 跳转jsp
                    String viewName = (String) result;
                    if (viewName.contains(":")) {
                        // forward:/user.jsp
                        String viewType = viewName.split(":")[0];
                        String viewPage = viewName.split(":")[1];
                        if (viewType.equals("forward")) {
                            req.getRequestDispatcher(viewPage).forward(req, resp);
                        } else {
                            // redirect:/user.jsp
                            resp.sendRedirect(viewPage);
                        }
                    } else {
                        // 默认就是转发
                        req.getRequestDispatcher(viewName).forward(req, resp);
                    }
                } else {
                    // 返回JSON数据
                    Method method = handler.getMethod();
                    if (method.isAnnotationPresent(ResponseBody.class)) {
                        ObjectMapper objectMapper = new ObjectMapper();
                        String json = objectMapper.writeValueAsString(result);
                        resp.setContentType("text/html;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        out.print(json);
                        out.flush();
                        out.close();
                    }

                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取请求对应的handler
     *
     * @return
     */
    public MyHandler getHandler(HttpServletRequest req) {
        String requestURI = req.getRequestURI();
        for (MyHandler myHandler : handlerList) {
            if (myHandler.getUrl().equals(requestURI)) {
                return myHandler;
            }
        }
        return null;
    }

    /**
     * 判断控制器方法的参数是否有RequestParm注解,且找到对应的value值
     *
     * @param method
     * @param name
     * @return
     */
    public int hasRequestParam(Method method, String name) {
        Parameter[] parameters = method.getParameters(); //method:public void com.bruce.controller.UserController.findUsers
        for (int i = 0; i < parameters.length; i++) {
            Parameter p = parameters[i];
            boolean b = p.isAnnotationPresent(RequestParm.class);
            if (b) {
                RequestParm requestParm = p.getAnnotation(RequestParm.class);
                String requestParmValue = requestParm.value();
                if (name.equals(requestParmValue)) {
                    return i;
                }
            }

        }
        return -1;
    }

    /**
     * 获取控制器方法的参数的名字
     *
     * @param method
     * @return
     */
    public List<String> getParameterNames(Method method) {
        List<String> list = new ArrayList<>();
        for (Parameter parameter : method.getParameters()) {
            String parameterName = parameter.getName();
            list.add(parameterName);
        }

        return list;
    }
}

com.springmvc.xml包:

XmlParser类:解析springmvc.xml文件

package com.springmvc.xml;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: 解析springmvc.xml文件
 * @Version: 1.0
 **/
public class XmlParser {

    public static String getbasePackage(String xml) {
        try {
            SAXReader saxReader = new SAXReader();
            // 获取XML文件的输入流
            InputStream inputStream = XmlParser.class.getClassLoader().getResourceAsStream(xml);
            // 使用SAXReader解析XML,并将结果存储在Document对象中
            Document document = saxReader.read(inputStream);

            // 获取XML文档的根元素
            Element rootElement = document.getRootElement();
            // 在根元素中查找名为"component-scan"的子元素
            Element element = rootElement.element("component-scan");
            // 获取"component-scan"元素的名为"base-package"的属性
            Attribute attribute = element.attribute("base-package");
            // 返回"base-package"属性的文本值,即要扫描的基础包名
            return attribute.getText();
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return "";
    }

}

springmvc.xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <!--设置使用注解的类所在的jar包-->
    <component-scan base-package="com.bruce.service,com.bruce.controller"></component-scan>
</beans>

web.xml文件:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--SpringMVC的核心控制器-->
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>com.springmvc.servlet.DispatcherServlet</servlet-class>

    <!--SpringMVC的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>

    <!--Web服务器一旦启动,Servlet就会实例化创建对象,然后初始化-->
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <!--/表示所有请求都能被DispatcherServlet访问-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

user.jsp文件:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>User.jsp</title>
</head>
<body>
    <h1>${requestScope.message}</h1>
</body>
</html>

index.jsp文件(自动生成的):

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

test


com.bruce.test包:

TestSpringMvc类:测试解析XML

package com.bruce.test;

import com.springmvc.xml.XmlParser;
import org.junit.Test;

/**
 * @Author: Juechen
 * @Date: 2024/4/24
 * @Description: TODO
 * @Version: 1.0
 **/
public class TestSpringMvc {

    @Test
    public void testreadXml() {
        String basePackage = XmlParser.getbasePackage("springmvc.xml");
        System.out.println(basePackage);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值