<?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相關技術文章或行業資訊,歡迎你們關注和轉發文章!前端