本文讲述spring框架的基础部分,如何用自己的方式手动去实现GPDispatcherServlet,其中配置文件只有一个application.properties。Controller、service、dao部分也不进行赘述。 为了解析方便,我们用application.properties来代替application.xml文 件 ,具体配置内容如下: 大家都知道,所有依赖于web容器的项目,都是从读取web.xml文件开始的。我们先配置好web.xml 其中GPDispatcherServlet是有自己模拟Spring实现的核心功能类。 @GPService 注解: @GPAutowired 注 解 : @GPController 注 解 : @GPRequestMapping 注 解 : @GPRequestParam 注 解 :手写Spring之spring初体验V1版本
1.目标及说明
2.基本思路
3.源码实现
3.1.自定义配置 application.properties 文件
scanPackage=com.gupaoedu.demo
3.2.配置web.xml文件
中的内容。<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/j2ee" xmlns:javaee="https://java.sun.com/xml/ns/javaee" xmlns:web="https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="https://java.sun.com/xml/ns/j2ee https://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>Gupao Web Application</display-name> <servlet> <servlet-name>gpmvc</servlet-name> <servlet-class>com.gupaoedu.mvcframework.v2.servlet.GPDispatchServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>application.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>gpmvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
3.3自定义 Annotation
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GPService { String value() default ""; }
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GPAutowired { String value() default ""; }
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GPController { String value() default ""; }
@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GPRequestMapping { String value() default ""; }
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GPRequestParam { String value() default ""; }
3.4 实现GPDispatcherServlet.java
public class GPDispatcherServlet extends HttpServlet { private Properties contextConfig = new Properties(); //享元模式,缓存 private List<String> classNames = new ArrayList<String>(); //ioc容器:key:类名首字母小写,value:对应的实例对象 private Map<String,Object> ioc = new HashMap<String, Object>(); private Map<String,Method> handlerMapping = new HashMap<String, Method>(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //6.委派,根据URL去找到一个对应的Method并通过response返回 try { doDispatch(req,resp); } catch (Exception e) { e.printStackTrace(); resp.getWriter().write("500 Exception,Detail :" + Arrays.toString(e.getStackTrace())); } } private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception { String url = req.getRequestURI(); String contextPath = req.getContextPath(); url = url.replaceAll(contextPath,"").replaceAll("/+","/"); if(!this.handlerMapping.containsKey(url)){ resp.getWriter().write("404 Not Found!!!"); return; } Map<String,String[]> params = req.getParameterMap(); Method method = this.handlerMapping.get(url); Class<?> [] parameterTypes = method.getParameterTypes(); Object [] paramValues = new Object[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { Class paramterType = parameterTypes[i]; if(paramterType == HttpServletRequest.class){ paramValues[i] = req; }else if(paramterType == HttpServletResponse.class){ paramValues[i] = resp; }else if(paramterType == String.class){ //通过运行时的状态拿到注解的值 Annotation[] [] pa = method.getParameterAnnotations(); for (int j = 0; j < pa.length ; j ++) { for(Annotation a : pa[j]){ if(a instanceof GPRequestParam){ String paramName = ((GPRequestParam) a).value(); if(!"".equals(paramName.trim())){ String value = Arrays.toString(params.get(paramName)).replaceAll("\[|\]","") .replaceAll("\s,",","); paramValues[i] = value; } } } } } } //暂时硬编码 String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName()); method.invoke(ioc.get(beanName),new Object[]{req,resp,params.get("name")}); } @Override public void init(ServletConfig config) throws ServletException { //1.加载配置文件 doLoadConfig(config.getInitParameter("contextConfigLocation")); //2.扫描相关的类 doScanner(contextConfig.getProperty("scanPackage")); //============IOC============= //3.初始化Ioc容器,将扫描到的相关的类实例化,保存到Ioc容器中 doInstrance(); //在DI之前加入AOP。 //AOP:新生成的代理对象 //============DI============= //4.完成依赖注入 doAutowired(); //============MVC============= //5.初始化HandlerMapping doInitHandlerMapping(); System.out.println("GP Spring framework init Finished"); } private void doInitHandlerMapping() { if(ioc.isEmpty()){ return; } for (Map.Entry<String, Object> entry : ioc.entrySet()) { Class<?> clazz = entry.getValue().getClass(); if(!clazz.isAnnotationPresent(GPController.class)){ continue; } //提取Controller类上的url String baseUrl = ""; if(clazz.isAnnotationPresent(GPRequestMapping.class)){ GPRequestMapping requestMapping = clazz.getAnnotation(GPRequestMapping.class); baseUrl = requestMapping.value(); } //只获取public方法 for(Method method : clazz.getMethods()){ if(!method.isAnnotationPresent(GPRequestMapping.class)){ continue; } //提取每个方法上的url GPRequestMapping gpRequestMapping = method.getAnnotation(GPRequestMapping.class); //使用正则/+,处理多/问题 String url = "/" + baseUrl + "/" + gpRequestMapping.value().replaceAll("/+","/"); handlerMapping.put(url,method); System.out.println("Mapped : " + url + "," + method); } } } private void doAutowired() { if(ioc.isEmpty()){ return; } for (Map.Entry<String,Object> entry:ioc.entrySet()) { //把所有private/protected/default/public修饰的变量都获取出来 for (Field field:entry.getValue().getClass().getDeclaredFields()) { if(!field.isAnnotationPresent(GPAutowired.class)){ continue; } GPAutowired autowired = field.getAnnotation(GPAutowired.class); String beanName = autowired.value().trim(); //如果用户没有自定义的beanName,就默认根据类型注入 if("".equals(beanName)){ //field.getType().getName() 获取字段的类型 beanName = field.getType().getName(); } //暴力访问 field.setAccessible(true); try { //ioc.get(beanName) 相当于通过接口的全名拿到接口的实现的实例 field.set(entry.getValue(),ioc.get(beanName)); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } private void doInstrance() { if(classNames.isEmpty()){ return; } try { for (String className : classNames) { Class<?> clazz = Class.forName(className); //包含GPController注解或GPService注解 if(clazz.isAnnotationPresent(GPController.class )){ String beanName = toLowerFirstCase(clazz.getSimpleName()); Object instance = clazz.newInstance(); //赋值到ioc容器 ioc.put(beanName,instance); }else if(clazz.isAnnotationPresent(GPService.class)){ //2.在多个包下出现相同类名,只能规定自己起一个全局唯一名字 //如使用注解GPService("aService")自定义命名 String beanName = clazz.getAnnotation(GPService.class).value(); if("".equals(beanName.trim())){ beanName = toLowerFirstCase(clazz.getSimpleName()); } //1.默认的类名首字母小写 Object instance = clazz.newInstance(); ioc.put(beanName,instance); //3.如果是接口 //判断有多少个实现类,如果只有一个,默认就选择这个实现类 //如果有多个,只能抛异常 for (Class<?> i :clazz.getInterfaces()) { if(ioc.containsKey(i.getName())){ throw new Exception("The" + i.getName() + "is exists!!"); } ioc.put(i.getName(),instance); } }else{ continue; } } }catch (Exception e) { e.printStackTrace(); } } private String toLowerFirstCase(String simpleName) { char [] chars = simpleName.toCharArray(); chars[0] += 32; return String.valueOf(chars); } private void doScanner(String scanPackage) { URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\.","/")); File classPath = new File(url.getFile()); // 当成是一个classPath文件夹 for (File file : classPath.listFiles()) { if(file.isDirectory()){ doScanner(scanPackage + "." + file.getName()); }else{ if(!file.getName().endsWith(".class")){ continue; } String className = (scanPackage + "." + file.getName().replace(".class","")); //Class.forName(className); classNames.add(className); } } } private void doLoadConfig(String contextConfigLoation) { InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLoation); try { contextConfig.load(is); } catch (IOException e) { e.printStackTrace(); }finally { if(null != is){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算