首先要知道springmvc主要流程:
当用户,也是就是请求送达过来的时候,
1.前端控制器会获取,
2.请求处理映射器,返回执行链接
3.获取执行适配器适配,交给执行器
4.返回modelandview给其前端控制器
5.前端控制器把信息给视图解析器进行渲染
6.渲染的视图传给客户
所以根据这个流程进行以下操作:
1.在tomcat启动时加载web.xml也就要对前端控制器
public void init(ServletConfig config) throws ServletException { //1.加载配置文件 springmvc.properties String contextConfigLocation = config.getInitParameter("contextConfigLocation"); doLoadConfig(contextConfigLocation); //2.扫描相关类 System.out.println(properties.getProperty("scanPackge")); doScan(properties.getProperty("scanPackge")); //3.初始化bean对象(ioc) doInstance(); //4.依赖注入(di) doAutoWired(); //5构造一个Handler ininHandlerMapping(); System.out.println("badfisher mvc 初始化 成功!!!"); }
/** * author: Badfsiher(yhy) * date 2020/6/17 21:12 */ @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.FIELD}) @Documented public @interface MyAutowired { String value() default ""; } /** * author: Badfsiher(yhy) * date 2020/6/28 20:21 */ @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.TYPE}) @Documented public @interface MyController { String value() default ""; } /** * author: Badfsiher(yhy) * date 2020/6/17 21:12 */ @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.TYPE,ElementType.METHOD}) @Documented public @interface MyRequestMapping { String value() default ""; } /** * author: Badfsiher(yhy) * date 2020/6/17 20:51 */ @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.TYPE}) @Documented public @interface MyService { String value() default ""; }
//文件获取 private void doLoadConfig(String contextConfigLocation) { InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation); try { properties.load(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } // 扫描 // pathPackage 会是全类名 com.badfisher.demo这样的递归扫描-->替换磁盘路径 private void doScan(String pathPackage){ String scanPathPackage = Thread.currentThread().getContextClassLoader().getResource("").getPath()+ pathPackage.replaceAll("\\.","/"); File pack = new File(scanPathPackage); System.out.println(scanPathPackage); File[] files = pack.listFiles(); for (File file :files) { if (file.isDirectory()){ doScan(pathPackage +"."+ file.getName()); }else if (file.getName().endsWith(".class")){ String className = pathPackage +"."+file.getName().replaceAll(".class",""); classNames.add(className); } } } //反射完成对对象创建 private void doInstance(){ if(classNames.size() == 0) return; try{ for (int i =0 ; i < classNames.size();i++){ String className = classNames.get(i); //反射 Class<?> myClazz = Class.forName(className); //区分注解 if(myClazz.isAnnotationPresent(MyController.class)){ //MyController获取类名并直接那类名小写 String simpleName = lowerFirst(myClazz.getSimpleName()); Object o = myClazz.getDeclaredConstructor().newInstance(); iocMap.put(simpleName,o); }else if (myClazz.isAnnotationPresent(MyService.class)){ MyService myService = myClazz.getAnnotation(MyService.class); //MyService 获取注解的值 String beanName = myService.value(); Object o = myClazz.getDeclaredConstructor().newInstance(); if (!"".equals(beanName.trim())){ iocMap.put(beanName,o); }else { String simpleName = lowerFirst(myClazz.getSimpleName()); iocMap.put(simpleName,o); } //service 往往存在接口,再以接口名称放入一份id到iocMap Class<?>[] interfaces = myClazz.getInterfaces(); for(int j = 0;j < interfaces.length; j++){ Class<?> ainterface = interfaces[j]; //以接口名称放入 iocMap.put(ainterface.getName(),o); } }else{ continue; } } }catch (Exception e){ System.out.println("注解类加载失败!!!"); e.printStackTrace(); } }
接下来是对注解解析实现我们要的注解功能
private void doAutoWired() { if (iocMap.isEmpty()) return; for (Map.Entry<String,Object> entry:iocMap.entrySet()) { //注入对象 Field[] declaredFields = entry.getValue().getClass().getDeclaredFields(); //便利并判断 for (int i = 0; i < declaredFields.length; i++) { Field declaredField = declaredFields[i]; //不存在跳出 if(!declaredField.isAnnotationPresent(MyAutowired.class)){ continue; } MyAutowired autowired = declaredField.getAnnotation(MyAutowired.class); String beanName = autowired.value(); if ("".equals(beanName.trim())){ beanName = declaredField.getType().getName(); } //赋值 declaredField.setAccessible(true); try { declaredField.set(entry.getValue(),iocMap.get(beanName)); } catch (IllegalAccessException e) { System.out.println("MyAutowired 注入失败!!!"); e.printStackTrace(); } } } }
//最重要的环节,完成url和methrd建立联系 private void ininHandlerMapping() { if (iocMap.isEmpty()) return; for (Map.Entry<String,Object> entry:iocMap.entrySet()) { //获取ioc当前便利对象的class类型 Class<?> myClass = entry.getValue().getClass(); if(!myClass.isAnnotationPresent(MyController.class)){ continue; } String baseUrl = ""; if (myClass.isAnnotationPresent(MyRequestMapping.class)){ MyRequestMapping myRequestMapping = myClass.getAnnotation(MyRequestMapping.class); baseUrl = myRequestMapping.value();//"/demo" } //获取方法 Method[] methods = myClass.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (!method.isAnnotationPresent((MyRequestMapping.class))){ continue; } MyRequestMapping myRequestMapping = method.getAnnotation(MyRequestMapping.class); String methodUrl = myRequestMapping.value(); String URL = baseUrl + methodUrl; //建立联系 //封装自定的hadler Handler handler = new Handler(entry.getValue(),method,Pattern.compile(URL)); // handlerMap.put(URL,method); //计算参数位置 Parameter[] parameters = method.getParameters(); for (int j = 0; j < parameters.length; j++) { Parameter parameter = parameters[j]; if (parameter.getType() == HttpServletResponse.class || parameter.getType() == HttpServletRequest.class){ // //HttpServletResponse HttpServletRequest 获取类名 handler.getParaIndexMapping().put(parameter.getType().getSimpleName(),j); }else{ handler.getParaIndexMapping().put(parameter.getName(),j); } } handlerMap.add(handler); } } }
完成绑定之后实现dopost逻辑
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //需求处理根据url找到对应的method方法进行调取 //获取url // String requestURI = req.getRequestURI(); // Method method = handlerMap.get(requestURI); //反射调用需要传入对象,需要传入参数,此处无法调用,没有缓存对象 // method.invoke(); Handler handler = getHandler(req); if (handler == null){ resp.getWriter().write("404 not found !"); return; } //参数绑定 //获取所有参数 Class<?>[] parameterTypes =handler.getMethod().getParameterTypes(); //参数数组反射调用 Object[] paraValues = new Object[parameterTypes.length]; //参数数组放值 Map<String,String[]> parameterMap = req.getParameterMap(); //遍历request中的参数 for (Map.Entry<String,String[]> param:parameterMap.entrySet()) { //name=1&name=2 name[1.2] String value = StringUtils.join(param.getValue(),","); //1,2 //如果匹配成功,填充 if (!handler.getParaIndexMapping().containsKey(param.getKey())){continue;} Integer index = handler.getParaIndexMapping().get(param.getKey()); paraValues[index] = value; } //放入 indexHttpServletRequestr indexHttpServletResponse int indexHttpServletRequestr = handler.getParaIndexMapping().get(HttpServletRequest.class.getSimpleName()); //0 paraValues[indexHttpServletRequestr] = req; int indexHttpServletResponse = handler.getParaIndexMapping().get(HttpServletResponse.class.getSimpleName());//1 paraValues[indexHttpServletResponse] = resp; // 最后的handler事物·method属性 try { handler.getMethod().invoke(handler.getController(),paraValues); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } private Handler getHandler(HttpServletRequest req) { if (handlerMap.isEmpty()){ return null; } String requestURI = req.getRequestURI(); for (Handler handler : handlerMap) { Matcher matcher = handler.getPattern().matcher(requestURI); if (!matcher.matches()){continue;} return handler; } return null; }
我的handler定义
package com.badfisher.mvcFramework.pojo; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; /** * author: Badfsiher(yhy) * date 2020/6/29 23:17 * 封装handler相关信息 */ public class Handler { private Object controller;//method.invoke private Method method; private Pattern pattern;//url 支持正则 private Map<String,Integer> paraIndexMapping;//参数顺序 参数绑定 public Handler(Object controller, Method method, Pattern pattern) { this.controller = controller; this.method = method; this.pattern = pattern; this.paraIndexMapping = new HashMap<>(); } public Object getController() { return controller; } public void setController(Object controller) { this.controller = controller; } public Method getMethod() { return method; } public void setMethod(Method method) { this.method = method; } public Pattern getPattern() { return pattern; } public void setPattern(Pattern pattern) { this.pattern = pattern; } public Map<String, Integer> getParaIndexMapping() { return paraIndexMapping; } public void setParaIndexMapping(Map<String, Integer> paraIndexMapping) { this.paraIndexMapping = paraIndexMapping; } }
如此就完成我们整体的简易SpringMVC的框架
原文:https://www.cnblogs.com/badfisher/p/13227509.html