【Java】深度分析!深入浅出总结一下手撕springMVC的要点,建议收藏起来慢慢看!

1、创建过程与文件目录

1.1、创建Maven工程

【Java】深度分析!深入浅出总结一下手撕springMVC的要点,建议收藏起来慢慢看!

【Java】深度分析!深入浅出总结一下手撕springMVC的要点,建议收藏起来慢慢看!

【Java】深度分析!深入浅出总结一下手撕springMVC的要点,建议收藏起来慢慢看!

【Java】深度分析!深入浅出总结一下手撕springMVC的要点,建议收藏起来慢慢看!

2、pom依赖与配置文件

2.1、pom依赖

<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.zhz</groupId>

<artifactId>simulation-springmvc</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>war</packaging>

<name>simulation-springmvc Maven Webapp</name>

<!-- FIXME change it to the project's website -->

<url>http://www.example.com</url>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.7</maven.compiler.source>

<maven.compiler.target>1.7</maven.compiler.target>

</properties>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.11</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>javax.servlet-api</artifactId>

<version>3.1.0</version>

<scope>provided</scope>

</dependency>

<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.12</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.9.1</version>

</dependency>

</dependencies>

<build>

<finalName>simulation-springmvc</finalName>

<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

<plugins>

<plugin>

<artifactId>maven-clean-plugin</artifactId>

<version>3.1.0</version>

</plugin>

<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->

<plugin>

<artifactId>maven-resources-plugin</artifactId>

<version>3.0.2</version>

</plugin>

<plugin>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.8.0</version>

</plugin>

<plugin>

<artifactId>maven-surefire-plugin</artifactId>

<version>2.22.1</version>

</plugin>

<plugin>

<artifactId>maven-war-plugin</artifactId>

<version>3.2.2</version>

</plugin>

<plugin>

<artifactId>maven-install-plugin</artifactId>

<version>2.5.2</version>

</plugin>

<plugin>

<artifactId>maven-deploy-plugin</artifactId>

<version>2.8.2</version>

</plugin>

</plugins>

</pluginManagement>

</build>

</project>

2.2、springmvc配置类

<?xml version="1.0" encoding="UTF-8" ?>

<beans>

<!--配置创建容器时要扫描的包-->

<component-scan base-package="com.zhz.controller,com.zhz.service"></component-scan>

</beans>

2.3、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>

<!--配置前端控制器-->

<servlet>

<servlet-name>DispatcherServlet</servlet-name>

<servlet-class>com.zhz.springmvc.servlet.DispatcherServlet</servlet-class>

<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>

<url-pattern>/</url-pattern>

</servlet-mapping>

</web-app>

3、实体类(User)

实体类:User.java

package com.zhz.bean;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

/**

* @author :zhz

* @date :Created in 2021/01/04

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description: 实体类

**/

@Data

@NoArgsConstructor

@AllArgsConstructor

public class User {

private Integer id;

private String name;

private String password;

}

4、控制器(UserController)

package com.zhz.controller;

import com.zhz.bean.User;

import com.zhz.service.UserService;

import com.zhz.springmvc.annotation.Autowired;

import com.zhz.springmvc.annotation.Controller;

import com.zhz.springmvc.annotation.RequestMapping;

import com.zhz.springmvc.annotation.ResponseBody;

/**

* @author :zhz

* @date :Created in 2021/01/03

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description: 控制器

**/

@Controller

public class UserController {

@Autowired(value = "userService")

private UserService userService;

@RequestMapping("/listUsers")

public String listUsers(){

userService.listUsers();

return "forward:/success.jsp";

}

@RequestMapping("/getData")

@ResponseBody //返回json格式的数据

public User getData(){

//调用服务层

return userService.getUser();

}

}

5、业务处理类与实现类(UserService,UserServiceImpl)

package com.zhz.service;

import com.zhz.bean.User;

/**

* @author :zhz

* @date :Created in 2021/01/03

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description:

**/

public interface UserService {

void listUsers();

User getUser();

}

package com.zhz.service.impl;

import com.zhz.bean.User;

import com.zhz.service.UserService;

import com.zhz.springmvc.annotation.Service;

/**

* @author :zhz

* @date :Created in 2021/01/03

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description:

**/

@Service("userService")

public class UserServiceImpl implements UserService {

@Override

public void listUsers() {

System.out.println("===调用===UserServiceImpl===listUser===");

}

@Override

public User getUser() {

return new User(1,"zhz","123456");

}

}

6、手撕mvc具体代码

6.1、核心annotation注解

package com.zhz.springmvc.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* @Retention注解表示Annotation的保留策略 RetentionPolicy.Class:运行时不保留,不可以通过反射读取。

* RetentionPolicy.RUNTIME:运行是保留,可以通过反射读取。

* RetentionPolicy.SOURCE:丢弃。

*/

@Target(value = ElementType.FIELD) //作用在属性上

@Retention(value = RetentionPolicy.RUNTIME)

public @interface Autowired {

String value();

}

package com.zhz.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.TYPE) // //作用在类上

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Controller {

String value() default "";

}

package com.zhz.springmvc.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD) //作用在方法上

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RequestMapping {

String value() default "";

}

package com.zhz.springmvc.annotation;

import java.lang.annotation.*;

/**

* @BelongsProject: SpringMvc

*/

@Target(ElementType.METHOD) //作用在方法上

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface ResponseBody {

}

package com.zhz.springmvc.annotation;

import java.lang.annotation.*;

/**

* @Description: 自定义注解

*/

@Target(ElementType.TYPE) //作用在类上

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Service {

String value();

}

6.2、context上下文(SpringMVC容器)

package com.zhz.springmvc.context;

import com.zhz.springmvc.annotation.Autowired;

import com.zhz.springmvc.annotation.Controller;

import com.zhz.springmvc.annotation.Service;

import com.zhz.springmvc.xml.XmlParse;

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 :zhz

* @date :Created in 2021/01/03

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description: SpringMVC容器

**/

public class WebApplicationContext {

//classpath:springmvc.xml

String contextConfigLocation;

//定义集合 用于存放 bean 的权限名|包名.类名

List<String> classNameList = new ArrayList<>();

//创建Map集合用于扮演IOC容器: key存放bean的名字 value存放bean实例

public Map<String, Object> iocMap = new ConcurrentHashMap<>();

public WebApplicationContext() {

}

public WebApplicationContext(String contextConfigLocation) {

this.contextConfigLocation = contextConfigLocation;

}

/**

* 初始化Spring容器

*/

public void onRefresh() {

//1、进行解析spring mvc配置文件操作 ==》 com.zhz.controller,com.zhz.service

String basePackage = XmlParse.getBasePackage(contextConfigLocation.split(":")[1]);

//通过","来分割com.zhz.controller,com.zhz.service 获得对应的包名

String[] packs = basePackage.split(",");

//2、进行包扫描

for (String pack : packs) {

executeScanPackage(pack);

}

//3、实例化容器中的bean

executeInstance();

//4、进行自动注入操作

executeAutowired();

}

/**

* 进行包扫描

*

* @param pack

*/

private void executeScanPackage(String pack) {

//1、把com.zhz.controller====>com/zhz/controller com.zhz.service====>com/zhz/controller

URL url = this.getClass().getClassLoader().getResource("/" + pack.replaceAll("\\.", "/"));

String path = url.getFile();

//2、/com/zhz/service

File dir = new File(path);

for (File file : dir.listFiles()) {

if (file.isDirectory()) {//说明是com.zhz.service.impl层

executeScanPackage(pack + "." + file.getName());

} else {

//文件目录下文件 获取全路径 UserController.class ==> com.zhz.controller.UserController

String className = pack + "." + file.getName().replaceAll(".class", "");

classNameList.add(className);

}

}

}

/**

* 实例化容器

*/

private void executeInstance() {

try {

// com.zhz.controller.UserController com.zhz.service.impl.UserServiceImpl

for (String className : classNameList) {

Class<?> clazz = Class.forName(className);

if (clazz.isAnnotationPresent(Controller.class)) {

//控制层的bean,得到类的简写名称也就是UserController

String beanName = clazz.getSimpleName().substring(0, 1).toLowerCase()+clazz.getSimpleName().substring(1);//首位变为小写

iocMap.put(beanName, clazz.newInstance());

} else if (clazz.isAnnotationPresent(Service.class)) {

//Service层,主要是为了获得他的value

Service service = clazz.getAnnotation(Service.class);

String beanName = service.value();

iocMap.put(beanName, clazz.newInstance());

}

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

}

}

/**

* 进行自动注入操作

*/

private void executeAutowired() {

try {

//从容器中取出bean,然后判断bean中是否有属性上使用Autowired,如果使用了该注解,就需要进行自动注入操作

for (Map.Entry<String, Object> entry : iocMap.entrySet()) {

//取出容器中的bean

Object bean = entry.getValue();

//从bean中获取属性

Field[] fields = bean.getClass().getDeclaredFields();

for (Field field : fields) {

if (field.isAnnotationPresent(Autowired.class)) {

//获取注解中的value值,该值是bean的name

Autowired autowired = field.getAnnotation(Autowired.class);

String beanName = autowired.value();

;

//取消检查机制

field.setAccessible(true);

field.set(bean, iocMap.get(beanName));

}

}

}

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

6.3、映射处理(url与ccontroller之间的映射)

package com.zhz.springmvc.handler;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.lang.reflect.Method;

/**

* @author :zhz

* @date :Created in 2021/01/04

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description:

**/

@Data

@AllArgsConstructor

@NoArgsConstructor

public class HandlerMapping {

//请求URL地址

private String url;

//控制器

private Object controller;

//控制器的方法

private Method method;

}

6.4、前端处理器

package com.zhz.springmvc.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.zhz.springmvc.annotation.Controller;

import com.zhz.springmvc.annotation.RequestMapping;

import com.zhz.springmvc.annotation.ResponseBody;

import com.zhz.springmvc.context.WebApplicationContext;

import com.zhz.springmvc.handler.HandlerMapping;

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.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

/**

* @author :zhz

* @date :Created in 2021/01/03

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description: 前端控制器

**/

public class DispatcherServlet extends HttpServlet {

//指定SpringMvc容器

private WebApplicationContext webApplicationContext;

//创建集合,用于存放映射关系、映射地址与控制器.方法,用于发送请求直接从该集合中进行匹配

List<HandlerMapping> handList = new ArrayList<>();

@Override

public void init() throws ServletException {

//1、从web.xml中获得加载初始化参数contextConfigLocation的值classpath:springmvc.xml

String configLocation = this.getServletConfig().getInitParameter("contextConfigLocation");

//2、创建SpringMVC容器

webApplicationContext = new WebApplicationContext(configLocation);

//3、进行初始化操作

webApplicationContext.onRefresh();

//4、初始化请求映射关系 /findUser ===》控制器.方法

initHandlerMapping();

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//进行请求分发处理

doDispatcher(request, response);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doPost(request, response);

}

/**

* 初始化请求映射关系(获取链接地址0

*/

private void initHandlerMapping() {

//遍历map, key存放bean的名字 value存放bean实例

for (Map.Entry<String, Object> entry : webApplicationContext.iocMap.entrySet()) {

//获得bean的class类型

Class<?> clazz = entry.getValue().getClass();

if (clazz.isAnnotationPresent(Controller.class)) {

//获取bean中所有的方法,为这些方法建立映射关系

Method[] methods = clazz.getDeclaredMethods();

for (Method method : methods) {

if (method.isAnnotationPresent(RequestMapping.class)) {

RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);

//获取注解中的值

String url = requestMapping.value();

//建立映射地址,与控制器 方法

HandlerMapping handlerMapping = new HandlerMapping(url, entry.getValue(), method);

handList.add(handlerMapping);

}

}

}

}

}

/**

* 进行请求分发处理

*

* @param request

* @param response

*/

private void doDispatcher(HttpServletRequest request, HttpServletResponse response) {

try {

//根据用户的请求地址(/listUsers)查找Controller

HandlerMapping handlerMapping = getHandler(request);

if (handlerMapping == null) {

response.getWriter().print("<h1>404 NOT FOUND!</h1>");

} else {

//调用处理方法之前 进行参数的注入

//调用目标方法---》获得方法的返回值类型

Object result = handlerMapping.getMethod().invoke(handlerMapping.getController());

if (result instanceof String){

//跳转到JSP中

String viewName = (String)result;

//forward:/success.jsp重定向

if (viewName.contains(":")){

String viewType=viewName.split(":")[0];//也就是forward或者redirect

String viewPage=viewName.split(":")[1];//跳转的页面

if (viewType.equals("forward")){//请求转发

request.getRequestDispatcher(viewPage).forward(request,response);

}else{//重定向

response.sendRedirect(viewPage);

}

}else{

//默认请求转发

request.getRequestDispatcher(viewName).forward(request,response);

}

}else{

//返回JSON格式数据

Method method=handlerMapping.getMethod();

if (method.isAnnotationPresent(ResponseBody.class)){

//将返回值转换成 json格式数据

ObjectMapper objectMapper = new ObjectMapper();

String json = objectMapper.writeValueAsString(result);

response.setContentType("text/html;charset=utf-8");

PrintWriter writer= response.getWriter();

writer.print(json);

writer.flush();

writer.close();

}

}

}

} catch (IOException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

} catch (ServletException e) {

e.printStackTrace();

}

}

/**

* 根据用户请求查找对应的Handler======>获取请求对应的handler(也就是从handList中取出)

*

* @param request

* @return

*/

private HandlerMapping getHandler(HttpServletRequest request) {

String requestURI = request.getRequestURI();

for (HandlerMapping handlerMapping : handList) {

//从容器的Handle取出URL 和 用户的请求地址进行匹配,找到满足条件的Handler(controller)

if (handlerMapping.getUrl().equals(requestURI)) {

return handlerMapping;

}

}

return null;

}

}

6.5、解析XML

package com.zhz.springmvc.xml;

import lombok.val;

import org.dom4j.Attribute;

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import java.io.File;

import java.io.InputStream;

/**

* @author :zhz

* @date :Created in 2021/01/04

* @version: V1.0

* @slogan: 天下风云出我辈,一入代码岁月催

* @description: 解析spring mvc.xml

**/

public class XmlParse {

public static String getBasePackage(String xml){

try {

SAXReader saxReader=new SAXReader();

// 通过reader对象的read方法加载spring mvc.xml文件,获取docuemnt对象。

InputStream inputStream = XmlParse.class.getClassLoader().getResourceAsStream(xml);

Document document = saxReader.read(inputStream);

// 通过document对象获取根节点beans

Element rootElement = document.getRootElement();

// 通过element对象的返回给定本地名称和任何名称空间的第一个元素

Element componentScan = rootElement.element("component-scan");

//返回componentScan的参数

Attribute attribute = componentScan.attribute("base-package");

//返回base-package的值

String basePackage = attribute.getText();

return basePackage;

} catch (DocumentException e) {

e.printStackTrace();

}

return "";

}

}

7、前端页面

7.1、index.jsp

<html>

<body>

<h2>Hello World!</h2>

</body>

</html>

7.2、succes.jsp

<html>

<body>

<h2>Hello World!</h2>

跳转至success.jsp页面

</body>

</html>

总结

这篇关于手撕springMVC的文章就先更到这里了,感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!
springMVC其实并不算是一个很难的知识点,用点心多看就很简单,最后点击这里即可领取Java架构大礼包哦!!!

以上是 【Java】深度分析!深入浅出总结一下手撕springMVC的要点,建议收藏起来慢慢看! 的全部内容, 来源链接: utcz.com/a/95319.html

回到顶部