标签:tostring 工作 创建 sse context load 生成 stack 集合
一 springMvc核心功能
springMvc是基于分层MVC设计模式的spring实现,他的核心功能是:
1 url跳转
2 ioc
3 aop(本次暂不实现)
二spring工作流程图
三 接下来,让我们写代码实现springMvc框架
通过注解方式实现了跳转和ioc两个核心功能,工程结构如下:
分别创建注解@Controller
package com.hongsen.annotation; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Controller { String value(); }
创建@RequestMapping注解
package com.hongsen.annotation; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestMapping { String value(); }
创建@resource注解
package com.hongsen.annotation; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Resource { String value(); }
创建@Service注解
package com.hongsen.annotation; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Service { String value(); }
创建servlet,代码如下:
package com.hongsen.servlet; /** * springMvc 作用 * <p> * 1 跳转 * 2 ioc * 3 aop * * @author wanghongsen 2018.07.27 */ public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 1L; private List<String> classList = new ArrayList<>(); private Map<String, Object> beanInstanceMap = new HashMap<>(); private Map<String, Method> urlHandlerMap = new HashMap<>(); /** * servlet初始化方法 * 1 scan扫描包路径 * 2 构造所有类集合 (list<String>) * 3 构造所有bean实例集合 (beanName-> bean) * 4 构造所有请求handler跳转(uri -> method) */ public void init() throws ServletException { System.out.println("init() start"); String scanBasePath = "com.hongsen"; scan(scanBasePath); initBeanInstance(); ioc(); initUrlHandlerMap(); } private void scan(String scanBasePath) { URL url = this.getClass().getResource("/" + scanBasePath.replace(".", "/")); String baseFilePath = url.getFile(); File baseFile = new File(baseFilePath); String[] subFilePaths = baseFile.list(); for (String subFilePath : subFilePaths != null ? subFilePaths : new String[0]) { File subFile = new File(baseFilePath + subFilePath); if (subFile.isDirectory()) { scan(scanBasePath + "." + subFilePath); } else { classList.add(scanBasePath + "." + subFilePath); } } }
private void initBeanInstance() { for (String beanName : classList) { try { beanName = beanName.replace(".class", ""); Class beanClass = Class.forName(beanName); try { if (beanClass.isAnnotationPresent(Controller.class)) { Controller controller = (Controller) beanClass.getAnnotation(Controller.class); beanInstanceMap.put(controller.value(), beanClass.newInstance()); } else if (beanClass.isAnnotationPresent(Service.class)) { Service service = (Service) beanClass.getAnnotation(Service.class); beanInstanceMap.put(service.value(), beanClass.newInstance()); } } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } private void ioc() { for (String beanName : classList) { try { beanName = beanName.replace(".class", ""); Class beanClass = Class.forName(beanName); Field[] fields = beanClass.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Resource.class)) { Resource resource = field.getAnnotation(Resource.class); String val = resource.value(); try { field.setAccessible(true); Service service = (Service) beanClass.getAnnotation(Service.class); if (service != null) { field.set(beanInstanceMap.get(service.value()), beanInstanceMap.get(val)); } else { Controller controller = (Controller) beanClass.getAnnotation(Controller.class); if (controller != null) { field.set(beanInstanceMap.get(controller.value()), beanInstanceMap.get(val)); } } } catch (IllegalAccessException e) { e.printStackTrace(); } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } private void initUrlHandlerMap() { for (String beanName : classList) { try { beanName = beanName.replace(".class", ""); Class beanClass = Class.forName(beanName); if (beanClass.isAnnotationPresent(RequestMapping.class)) { RequestMapping baseReqMap = (RequestMapping) beanClass.getAnnotation(RequestMapping.class); if (baseReqMap != null) { String requestBaseUrl = baseReqMap.value(); Method[] methods = beanClass.getMethods(); for (Method method : methods) { RequestMapping reqMap = method.getAnnotation(RequestMapping.class); if (reqMap != null) { urlHandlerMap.put(requestBaseUrl + reqMap.value(), method); } } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { String uri = request.getRequestURI(); String contextPath = request.getContextPath(); String requestUrl = uri.replace(contextPath, ""); Method method = urlHandlerMap.get(requestUrl); if (method == null) { return; } Class beanClass = method.getDeclaringClass(); Controller controller = (Controller) beanClass.getAnnotation(Controller.class); Object bean = beanInstanceMap.get(controller.value()); try { Map<String, String[]> requestParameterMap = request.getParameterMap(); Object[] args = new Object[requestParameterMap.entrySet().size()]; int index = 0; for (Map.Entry entry : requestParameterMap.entrySet()) { args[index] = entry.getValue(); index++; } method.invoke(bean, args); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }
创建完servlet后web.xml自动生成相应代码
<load-on-startup>加这个标签,tomcat启动时会自动加载指定的servlet 大于等于0时启动tomcat会加载 servlet的init()方法 数字越小代表加载的优先级越高
<url-pattern>/这个标签是tomcat请求扫描路径,扫到后会调用servlet相应的doGet或doPost方法
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>com.hongsen.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
创建Controller类
package com.hongsen.controller; @Controller("testController") @RequestMapping("/test") public class TestController { @Resource("testAddService") private TestAddServiceImpl testAddService; @Resource("testDelService") private TestDelServiceImpl testDelService; @RequestMapping("/add.json") public void testAdd() { testAddService.add(); } @RequestMapping("/del.json") public void testDel(Object num1, Object num2) { testDelService.del(num1.toString(), num2.toString()); } }
创建service接口和实现类
package com.hongsen.service; public interface TestAddService { void add(String num); }
package com.hongsen.service; @Service("testAddService") public class TestAddServiceImpl implements TestAddService{ @Override public void add(String num) { System.out.println("add方法执行!"); } }
部署tomcat启动成功后:
访问:http://localhost:8080/test/add.json
标签:tostring 工作 创建 sse context load 生成 stack 集合
原文地址:https://www.cnblogs.com/wanghongsen/p/9377651.html