Java EE 分层模型
- Domain Object(领域对象)层:本层有一系列普通的、传统的Java对象(POJO)组成,这些对象是该系统的Domain Object,通常包含各自所需实现的业务逻辑方法。
- DAO(Data Access Object,数据访问对象)层:有一系列DAO组件组成,DAO实现了对数据库的创建、查询等操作。
- Service(业务逻辑)层:由一系列的业务逻辑对象组成,这些逻辑对象实现了系统所需要的业务逻辑方法。
- Controller(控制器)层:由一系列控制器组成,用于拦截用户的请求,调用业务逻辑组件的业务逻辑方法去处理用户请求,然后根据处理结果向不同的View组件转发。
- View(表现)层:由一系列的页面和视图组件组成,负责收集用户请求,并显示处理后的结果。
Java MVC
- Controller:接收用户请求,传送用户需求给Model
- Model:接收用户需求,判断逻辑,调用数据库,返回数据给View
- View:渲染视图,返回给用户
Servlet
Servlet3.0之前的版本都是在web.xml中配置,而3.0之后使用注解方式来配置。
基于web.xml
<web-app>
<servlet>
<description>xxx</description>
<display>user</display>
<servlet>user</servlet>
<servlet-class>com.sec.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>user</servlet-name>
<url-pattern>/user</url-pattern>
</servlet-mapping>
</web-app>
- <servlet>:声明Servlet配置入口
- <description>:声明Servlet描述信息
- <display-name>:定义Web应用的名字
- <servlet-name>:声明Servlet名称以便在后面的映射时使用
- <servlet-class>:指定当前servlet对应的类的路径
- <servlet-mapping>:注册组件访问配置的路径入口
- <servlet-name>:指定上文配置的Servlet的名称
- <url-pattern>:指定配置这个组件的访问路径
基于注解的方式
3.0以上版本,可以通过@WebServlet注解即可修改Servlet的属性。
@WebServlet(description = "this is a description", urlPatterns; {"/test"})
Servlet访问流程
在浏览器中输入/user,根据<servlet-mapping>标签中的文件名为user的url-pattern,通过对应的servlet-name寻找servlet标签中servlet-name相同的servlet,通过servlet-name获取class参数,得到具体的路径,执行响应的class的逻辑。
Servlet方法
创建Servlet文件时,需要创建响应的接口方法。
- init():第一次创建Servlet时被调用,用来初始化对象。
- service():执行任务的主要方法。
- doGet()/doPost():根据HTTP不通请求调用不同的方法。
- destroy():移除对象。
- getServletConfig():初始化参数
filter:Java Web过滤器
配合方式同Servlet类似,3.0前在web.xml中配置,3.0后通过注解方式配置。
基于web.xml
<web-app>
<filter>
<display-name>test</display-name>
<filter-anme>test</filter-name>
<filter-class>com.sec.test.test</filter-name>
</filter>
<filter-mapping>
<filter-name>test</filter-name>
<url-pattern>/test</url-pattern>
</filter-mapping>
</web-app>
配置方式与Serlvet逻辑大致相同
filter接口方法
- init()
- doFilter()
- destroy()
反射机制
反射使Java代码能够发现有关已加载类的字段、方法和构造函数的信息,并在安全限制内使用反射的字段、方法和构造函数对其底层对应的对象进行操作。这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
获取类对象
获取类对象的方法
- forName():使用Class类中的方法获取类对象
- .class:直接获取其对应的Class对象,但是要明确到类中的静态成员
- getClass():通过Object类中的getClass()方法获取字节码对象
- getSystemClassLoader().loadClass():与forName()类似,但是知识只是加载类到内存中,不会执行静态代码
获取类方法
获取某个Class对象的方法集合
- getDeclaredMethods:返回声明的所有方法,但不包括继承的方法
- getMethods:返回某个类所有的public方法
- getMethod:返回一个特定方法
- getDeclaredMethod:返回特定方法
获取类成员变量
获取类成员变量
- getDeclaredFields:获得类成员变量数组,不包括父类的申明字段。
- getFields:获取某个类所有的public字段
- getDeclaredField:获得某个特定的类成员变量
- getField:获得某个特定的public类成员变量
ClassLoader类加载机制
ClassLoader类是个抽象类,通过指定的类名称找到或生成对应字节码,返回一个java.lang.Class类的示例。可以继承ClassLoader来实现自定义的类加载器。
- getParent():返回类加载器的父加载器
- loadClass(String name):加载名称为name的类,返回的结果是 java.lang.Class类的实例
- findClass(String name):查找名称为name的类,返回的结果是java.lang.Class类的实例
- findLoadedClass(String name):查找名称为name的已经被加载过的类,返回的结果是java.lang.Class的实例
- defineClass(String name, byte[] b, int off, int len):把字节数组b中的内容转换成java类,返回的结果是java.lang.Class类的实例,该方法被声明为final
- resolveClass(Class<?>c):链接指定的java类
loadClass()方法与Class.forName的区别
loadClass()只会对类进行加载,不会对类进行初始化。Class.forName会默认对类进行初始化,执行静态的代码块。
URLClassLoader
是ClassLoader的一个实现,拥有从远程服务器加载类的能力,可以实现对webshell的远程加载等。
代理
静态代理
静态代理中,代理类和被代理类实现了同样的接口,代理类同时持有被代理类的引用,当我们需要调用被代理类的方法时,可以通过调用代理类的方法实现。
动态代理
基于反射的代理模式,动态代理通过Proxy类创建对象,然后将接口方法“代理”给InvocationHandler接口完成的。
CGLib代理
基于反射的代理模式,只能基于接口设计。性能较高。
Javassist动态编程
绕过编译过程在运行时进行操作的技术。
- ClassPool类:基于HashMap实现的CtClass对象容器,其中键是类名称,值是CtClass对象。
- CtClass类:表示一个类,这些对象可以从ClassPool中获得
- CtMethods类:类中的方法
- CtFields类:类中的字段
可以利用Javassist对目标函数动态注入字节码代码,劫持框架的关键函数,对中间件的安全进行测试,也可以劫持函数进行攻击阻断。