一、项目搭建相关
1、目录结构:
2、开源中国免费使用Git提交方法:
git remote add origin < Git仓库地址 >
git push -u origin master
3、前端页面放在WEB-INF内部,这样浏览器就不能通过地址栏直接请求,必须通过servlet程序进行转发或重定向。
4、日志添加SLF4J依赖,使用Log4J作为实现,必须在main/resources目录下添加log4J。properties的文件,在其中设置日志级别和appender(哪些文件可输出日志)
5、对于maven目录而言classpath指的是Java和resources这两个根目录
6、maven三坐标:groupId、artifactId、version。如果依赖只参与编译不参与打包可将其scop设置为provided,如果只在运行时需要则设置成runtime
二、搭建框架
MVC核心:请求转发器DispatcherServlet,继承了httpServlet重写init()和service方法,拦截所有的请求并分发到路径映射的类上边:
1、init()
1)初始化相关loader:
ClassHelper、BeanHelper、IocHelper、ControllerHelper
分别的作用是:
类加载器:递归方式加载包名下的所有类或jar包进Set,并根据类上的注解生成区分service的Set和controller的Set;
Bean容器:遍历类加载器获得的类,利用反射生成相应的实例化对象,将创建的对象存放在一个静态的Map<Class<?>,Object>中,通过类名就可以获取相应的对象,每个对象有调用方法和设置成员变量方法;
依赖注入(控制反转):遍历BeanMap容器,分别取出Bean类和其实例,通过反射获得类的成员变量,继续遍历这些成员变量判断其是否带有依赖注入的注解,如果有,则从BeanMap中取出Bean实例,并修改类的成员变量为该Bean实例。这些是在IocHelper静态代码块中完成的,类加载时就会加载这个静态块。(IOC框架中管理的对象都是单例的)
Controller请求映射:类加载器可以获取所有Controller注解的类Set,通过遍历和反射获取Controller中的请求方法和方法上的URL注解得到了请求方法和请求路径组成Request对象、同时遍历过程中也会知道类名和方法名,存入Handler对象中,将(请求对象)request和(处理对象)Handler之间的映射存入Map,可根据请求方法和请求路径获得对象方法。这样只要拦截到请求就可以解析请求的request,并找到对应的Handler,并取出相应的Controller对象和要调用的方法。
2)获取ServletContext对象用于注册servlet
3)注册不同的servlet(jspServlet、处理静态资源的默认servlet)
2、service(request,response)
HttpServletRequest参数中获取请求方法和请求路径;
通过请求方法和路径获取init()方法中已经初始化的处理器handler;
Handler中获取Controller类及其Bean实例和方法;
HttpServletRequest中获取具体参数构建参数map;
ControllerBean+方法+参数map可以调用反射工具的method.invoke方法得到返回值;
判断返回结果返回View类型(视图路径、视图数据)的视图对象,或者Data类型的JSON数据
三、实现AOP
1、定义:面向切面编程,就是针对代理的一种使用
织入是对方法的增强,引入是对类的增强
2、动态代理:
1、JDK方式
1)实现 InvocationHandler 接口创建委托类,必须实现接口的invoke方法,实现增强,且通过构造方法注入目标对象
2)委托类实例化成对象,然后调用JDK提供的Proxy类工厂方法newProxyInstance去动态创建一个代理类(原理是通过反射),参数是ClassLoader、该实现类的所有接口、刚实例化的对象(可将该方法封装)
2、CJLib方式,可代理没有接口的类,原理是对代理的目标类生成一个子类,并覆盖其中方法实现增强,因为底层是基于创建被代理类的一个子类,所以它避免了JDK动态代理类的缺陷。
1)实现 MethodInterceptor 接口,通过实现intercept方法传入被代理的对象以及方法参数,并在该方法中实现增强逻辑,添加一个构造方法可返回enhancer.create()创建的动态带肋对象
3、Spring实现AOP
1)通过实现Spring提供的不同的增强类接口(这种方式叫编程式),创建前置增强类、创建后置增强类或环绕增强;
2)创建代理工厂,将目标类、增强类放入代理工厂
3)从代理工厂ProxyFactory获取代理,调用代理方法
声明式不过是将以上三步通过xml的bean配置的方式实现
抛出增强在排除异常时用
引入增强可以扩展类的功能:引入增强类通过实现新接口,继承DelegatingIntroductionInterceptor类,覆盖父类方法的invoke()方法,目标类就可以不用实现这个接口就可以向上转型为增强类里边实现的接口并调用其属性和方法
4)将切面配置进ProxyFactory,切面实现的增强类和切点(拦截匹配条件)的组合。也就是切面封装了增强(Advice)和切点(pointcut),所以就可以把上边第1)2)步的增强换成切面,这样可以实现对某个方法拦截,对另一个方法不拦截的控制:Spring提供了很多切面类,如基于正则
Spring提供的切面还有
5)自动代理:对于生成很多代理时,上边3)4)会重复进行,可用自动代理优化:
BeanNameAutoProxyCreator可根据bean名称自动生成代理(如对Impl结尾的Bean生成代理);
DefaultAdvisorAutoProxyCreator可自动扫描符合切面要求的bean
4、spring+AspectJ
Spring自己实现的AOP优化后还需要自己定义切面类,AspectJ可以避免这一点:
1)基于注解@Aspect定义委托类(其实就是个Advisor),并通过表达式实现被代理对象bean的扫描拦截和注入如
其中切点表达式:
如果要拦截指定注解可在此表达式中填上注解名称。Around也可以换成其他增强类型,如引入增强是@DeclareParents
项目上要开启配置:
false只能代理接口(JDK),true(CJLib)
2)基于配置方式可以实现相同功能:<aop:config>
5、自己实现AOP
1)定义切面注解
2)搭建代理框架(链式代理),对有注解的类自动创建代理类
3)AOPHelper将目标类和代理类关系放入BeanMap中交给IOC托管
四、Threadlocal
本地线程,其实是个容器,用于存放线程的局部变量。
线程共享的static变量无法保证线程安全,ThreadLocal为每个线程提供独立的副本
自己实现:
ThreadLocal就是生成一个
Private Map<Thread,T> map = Conllections.synchronizedMap(new HashMap<Thread,T>());
五、事务
ACID:原子性、一致性、隔离性、持久性
脏读:事务A读取了事务B没有提交的事务
不可重复读:事务A读取了事务B提交的修改数据
幻读:事务A读取了事务B已提交的新增数据
Spring中事务的解决方案:7种事务传播行为
自己实现事务:
1、定义事务注解
2、提供事务相关操作:conn事务开启、提交、回滚
3、编写事务代理切面
4、框架中添加事务代理机制
六、扩展
1、shiro
1)shiro执行过程
读取classpath下shiro.ini配置文件,通过工厂创建securityManager,放入SecurityUtils中供随时获取;
SecurityUtils获取subject(主体);
securityManager读取Realm(用户信息数据源)对subject进行验证;
验证通过穿件session,验证失败注销本次session;
实际开发中会通过EnvironmentLoaderListener来监听初始化securityManager,通过ShiroFilter完成认证授权。
权限的RBAC模型:
WSDL:Web服务描述语言,用来描述WS的具体内容,发布WS后可在浏览器通过一个地址查看WSDL文档,在definitions根节点下有五种子节点。
WSDL描述WS是什么,SOAP表示WS里有什么,SOAP就是一个信封,包括header和body,数据都放在body,特殊属性放在header
REST没有WSDL概念,传递的是JSON格式,使用URL来访问资源,是无状态的框架协议所以是SOA所说的面向服务思想,REST是轻量级的SOA实现技术。
跨域问题解决:
- JSONP但只能处理GET请求
- CORS(跨域资源共享)