SpringMVC学习
SpringMVC是 Spring提供的用于简化web开发的框架。
1.5 Servlet
Servlet能够响应请求的对象。接收请求,返回响应
SpringMVC可以认为是Servlet的封装。
1.6 SpringMVC开发流程回顾
各种配置。Controller,DispatchServlet,
1.9 url-pattern配置及原理剖析
静态资源配置
<mvc:default-servlet-handler/>
<resources location="classpath:/" mapping="resources/**">
1.10 数据处理机制Model、Map及ModelMap
用ModelMap传输局
1.11 请求参数绑定 (就是url上的参数)
http协议,超文本传输协议
1.12 简单类型参数
可以一致可以不一致,添加注解
1.13 绑定POJO及包装类型参数回顾
- Pojo,属性名要对应
- 形参名无所谓
- 嵌套pojo 就是包装类型
1.14 接受日期类型参数
- 可以定义converter转换
- 配在springmvc.xml 配置转换
1.15 深刻理解Rest风格
1)Rest风格请求是什么样的?
事例. rest是一个URL请求的风格,基于这种风格设计请求的Url。没有Rest的话,
http://localhost:8080/user/.action?id=3
有了rest风格之后,rest中认为互联网中的所有东西都是资源,就会有一个Uri标识。根据请求方式不同有不同的操作动作
用占位符表示参数
1.19 拦截器监听器
作用:
- 做一些初始化工作
- 监听web的特定事件,比如监听session
- 拦截器:拦截handler
1.20 单个拦截器
四线接口 HandlerInterceptor
- preHandle. 往往在这里完成权限校验, 默认不通过 false,需要修改值
- postHandle
- afterCompletion
2.1 手写MVC框架值原理回顾
@Override public void init(ServletConfig config) throws ServletException { //加载配置文件 String location = config.getInitParameter("contextConfigLocation"); doLoadConfig(location); //扫描相关的类 doScan(""); //初始化相应Bean对象,实现IoC容器 doInstance(); //实现依赖注入 doAutoWired(); //构造一个handlerMapping处理器,映射器,将配置好的url和Method建立关系 initHandlerMapping(); System.out.println("Dispatcher init finish"); }
2.4 doScan把设置需要扫描的路径下面的Controller类名存起来
private void doScan(String packagePath) { String scanPackagePath = Thread.currentThread() .getContextClassLoader() .getResource("") .getPath() + packagePath.replaceAll("\\.", "/"); File pack = new File(scanPackagePath); File[] files = pack.listFiles(); for (File file : files) { if (file.isDirectory()) { doScan(packagePath + "." + file.getName()); } else if (file.getName().endsWith(".class")) { String className = packagePath+ "." + file.getName().replaceAll(".class", ""); classNames.add(className); } } } //加载配置文件 private void doLoadConfig(String location) { InputStream resourceStream = this.getClass().getClassLoader().getResourceAsStream(location); try { properties.load(resourceStream); } catch (Exception e) { e.printStackTrace(); } }
2.5 initHandlerMapping, 把url和对应处理方法存起来
private void initHandlerMapping() { for (Map.Entry<String, Object> entry : ioc.entrySet()) { Class<?> clazz = entry.getValue().getClass(); if (clazz.isAnnotationPresent(LagouController.class)) { String baseUrl = ""; if (clazz.isAnnotationPresent(LagouRequestMapping.class)) { LagouRequestMapping annotation = clazz.getAnnotation(LagouRequestMapping.class); baseUrl = annotation.value(); } Method[] methods = clazz.getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(LagouRequestMapping.class)) { LagouRequestMapping methodAnnotation = method.getAnnotation(LagouRequestMapping.class); String methodUrl = methodAnnotation.value(); String url = baseUrl + methodUrl; handlerMapping.put(url, method); } } } } }
2.6 doAutoWired, 把Autowired对应的实例存起来
private void doAutoWired() { if (ioc.isEmpty()) { return; } //有对象再依赖注入处理 for (Map.Entry<String, Object> entry : ioc.entrySet()) { Field[] declares = entry.getValue().getClass().getDeclaredFields(); for (Field field : declares) { if (field.isAnnotationPresent(LagouAutoWired.class)) { LagouAutoWired annotation = field.getAnnotation(LagouAutoWired.class); String beanName = annotation.value(); if ("".equals(beanName.trim())) { beanName = field.getType().getName(); } field.setAccessible(true); try { field.set(entry.getValue(), ioc.get(beanName)); } catch (Exception e) { e.printStackTrace(); } } } } }
2.7 实现ioc容器 (存controller,service,的实例,service有注解,找对应的interface,然后把interface对应上service实例)
private void doInstance() { if (classNames.isEmpty()) return; try { for (String className : classNames) { //DemoController Class<?> clazz = Class.forName(className); //区分controller 和 service if (clazz.isAnnotationPresent(LagouController.class)) { //controller id不处理 String simpleName = clazz.getSimpleName(); String lowerName = lowerFirstAlpha(simpleName); ioc.put(lowerName, clazz.newInstance()); } else if (clazz.isAnnotationPresent(LagouService.class)) { LagouService annotation = clazz.getAnnotation(LagouService.class); //获取注解值 String beanName = annotation.value(); if (!"".equals(beanName.trim())) { ioc.put(beanName, clazz.newInstance()); } else { beanName = lowerFirstAlpha(clazz.getSimpleName()); ioc.put(beanName, clazz.newInstance()); } // service 是有接口的, 放入ioc Class<?>[] interfaces = clazz.getInterfaces(); for (Class<?> inter : interfaces) { ioc.put(inter.getName(), clazz.newInstance()); } } } } catch (Exception e) { e.printStackTrace(); } }
2.8 doScan 扫描包,存入class的路径
private void doScan(String packagePath) { String scanPackagePath = Thread.currentThread() .getContextClassLoader() .getResource("") .getPath() + packagePath.replaceAll("\\.", "/"); File pack = new File(scanPackagePath); File[] files = pack.listFiles(); for (File file : files) { if (file.isDirectory()) { doScan(packagePath + "." + file.getName()); } else if (file.getName().endsWith(".class")) { String className = packagePath + "." + file.getName().replaceAll(".class", ""); classNames.add(className); } } }
2.9 doLoadConfig 把配置文件放入内存
private void doLoadConfig(String location) { InputStream resourceStream = this.getClass().getClassLoader().getResourceAsStream(location); try { properties.load(resourceStream); } catch (Exception e) { e.printStackTrace(); } }
谢谢!