<?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>复制代码
<?xml version="1.0" encoding="UTF-8" ?> <beans> <!--配置建立容器时要扫描的包--> <component-scan base-package="com.zhz.controller,com.zhz.service"></component-scan> </beans>复制代码
<!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>复制代码三、实体类(User)
实体类:User.javahtml
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; }复制代码四、控制器(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(); } }复制代码五、业务处理类与实现类(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"); } }复制代码六、手撕mvc具体代码
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(); }复制代码
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() { //一、进行解析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(","); //二、进行包扫描 for (String pack : packs) { executeScanPackage(pack); } //三、实例化容器中的bean executeInstance(); //四、进行自动注入操做 executeAutowired(); } /** * 进行包扫描 * * @param pack */ private void executeScanPackage(String pack) { //一、把com.zhz.controller====>com/zhz/controller com.zhz.service====>com/zhz/controller URL url = this.getClass().getClassLoader().getResource("/" + pack.replaceAll("\\.", "/")); String path = url.getFile(); //二、/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(); } } }复制代码
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; }复制代码
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 { //一、从web.xml中得到加载初始化参数contextConfigLocation的值classpath:springmvc.xml String configLocation = this.getServletConfig().getInitParameter("contextConfigLocation"); //二、建立SpringMVC容器 webApplicationContext = new WebApplicationContext(configLocation); //三、进行初始化操做 webApplicationContext.onRefresh(); //四、初始化请求映射关系 /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; } }复制代码
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 ""; } }复制代码七、前端页面
<html> <body> <h2>Hello World!</h2> </body> </html>复制代码
<html> <body> <h2>Hello World!</h2> 跳转至success.jsp页面 </body> </html>复制代码
这篇关于手撕springMVC的文章就先更到这里了,感谢你看到这里,文章有什么不足还请指正,以为文章对你有帮助的话记得给我点个赞,天天都会分享java相关技术文章或行业资讯,欢迎你们关注和转发文章!前端