SSM框架流程及原理分析

网友投稿 725 2023-01-12

SSM框架流程及原理分析

SSM框架流程及原理分析

前言:学ssm框架已经有很长时间,今天来复习一下

SSM图示流程:

Spring核心:java反射

Mybatis:动态代理,而动态代理又是基于反射的,所以,ssm框架核心原理在反射。

(1)Spring(对象工厂): 平时开发接触最多的估计就是这个IOC容器,它可以装载bean(也就是Java中的类,当然也包括service、dao里面的),有了这个机制,就不用在每次使用这个类的时候为它初始化,很少看到关键字new。

(2)SpringMVC(视图控制器): 核心为一个DispatcherServlet,控制所有请求

这里奉上手写SpringMVC的核心DispatcherServlet源码

package servlet;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.lang.reflect.Method;

import java-.URL;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import java.util.Properties;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servleDLPGbOCSFbt.http.HttpServletResponse;

import annotation.HController;

import annotation.HRequestMapping;

/**

* 手写SpringMVC

*

* @author hxz

* @description TODO

* @data 2020年1月2日 上午9:39:57

*/

public class MyDispatcherServlet extends HttpServlet {

//加载属性文件

private Properties properties = new ProperDLPGbOCSFbties();

//装载beanname

private List classNames = new ArrayList();

//ioc容器

private Map ioc = new HashMap();

//类似于以前自定义的cache缓存容器,这里也是起到一个容器的作用

//用于加载各个mapping

private Map handlerMapping = new HashMap();

//容器加载所有的controller

private Map controllerMap = new HashMap();

@Override

public void init(ServletConfig config) throws ServletException {

// 1.加载配置文件

doLoadConfig(config.getInitParameter("contextConfigLocation"));

// 2.初始化所有相关联的类,扫描用户设定的包下面所有的类

doScanner(properties.getProperty("scanPackage"));

// 3.拿到扫描到的类,通过反射机制,实例化,并且放到ioc容器中beanName默认是首字母小写

doInstance();

// 4.初始化HandlerMapping(将url和method对应上)

initHandlerMapping();

}

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

this.doPost(req, resp);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

try {

// 处理请求

doDispatch(req, resp);

} catch (Exception e) {

resp.getWriter().write("500!! Server Exception");

}

}

private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {

if (handlerMapping.isEmpty()) {

return;

}

String url = req.getRequestURI();

String contextPath = req.getContextPath();

url = url.replace(contextPath, "").replaceAll("/+", "/");

if (!this.handlerMapping.containsKey(url)) {

resp.getWriter().write("404 NOT FOUND!");

return;

}

Method method = this.handlerMapping.get(url);

// 获取方法的参数列表

Class>[] parameterTypes = method.getParameterTypes();

// 获取请求的参数

Map parameterMap = req.getParameterMap();

// 保存参数值

Object[] paramValues = new Object[parameterTypes.length];

// 方法的参数列表

for (int i = 0; i < parameterTypes.length; i++) {

// 根据参数名称,做某些处理

String requestParam = parameterTypes[i].getSimpleName();

if (requestParam.equals("HttpServletRequest")) {

// 参数类型已明确,这边强转类型

paramValues[i] = req;

continue;

}

if (requestParam.equals("HttpServletResponse")) {

paramValues[i] = resp;

continue;

}

if (requestParam.equals("String")) {

for (Entry param : parameterMap.entrySet()) {

String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");

paramValues[i] = value;

}

}

}

// 利用反射机制来调用

try {

method.invoke(this.controllerMap.get(url), paramValues);// 第一个参数是method所对应的实例

// 在ioc容器中

} catch (Exception e) {

e.printStackTrace();

}

}

private void doLoadConfig(String location) {

// 把web.xml中的contextConfigLocation对应value值的文件加载到流里面

InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);

try {

// 用Properties文件加载文件里的内容

properties.load(resourceAsStream);

} catch (IOException e) {

e.printStackTrace();

} finally {

// 关流

if (null != resourceAsStream) {

try {

resourceAsStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

private void doScanner(String packageName) {

// 把所有的.替换成/

URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.", "/"));

File dir = new File(url.getFile());

for (File file : dir.listFiles()) {

if (file.isDirectory()) {

// 递归读取包

doScanner(packageName + "." + file.getName());

} else {

String className = packageName + "." + file.getName().replace(".class", "");

classNames.add(className);

}

}

}

//利用java的反射机制

private void doInstance() {

if (classNames.isEmpty()) {

return;

}

for (String className : classNames) {

try {

// 把类搞出来,反射来实例化

Class> clazz = Class.forName(className);

if (clazz.isAnnotationPresent(HController.class)) {

ioc.put(toLowerFirstWord(clazz.getSimpleName()), clazz.newInstance());

} else {

continue;

}

} catch (Exception e) {

e.printStackTrace();

continue;

}

}

}

private void initHandlerMapping() {

if (ioc.isEmpty()) {

return;

}

try {

for (Entry entry : ioc.entrySet()) {

Class extends Object> clazz = entry.getValue().getClass();

if (!clazz.isAnnotationPresent(HController.class)) {

continue;

}

// 拼url时,是controller头的url拼上方法上的url

String baseUrl = "";

if (clazz.isAnnotationPresent(HRequestMapping.class)) {

HRequestMapping annotation = clazz.getAnnotation(HRequestMapping.class);

baseUrl = annotation.value();

}

Method[] methods = clazz.getMethods();

for (Method method : methods) {

if (!method.isAnnotationPresent(HRequestMapping.class)) {

continue;

}

HRequestMapping annotation = method.getAnnotation(HRequestMapping.class);

String url = annotation.value();

url = (baseUrl + "/" + url).replaceAll("/+", "/");

handlerMapping.put(url, method);

controllerMap.put(url, clazz.newInstance());

System.out.println(url + "," + method);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 把字符串的首字母小写

*

* @param name

* @return

*/

private String toLowerFirstWord(String name) {

char[] charArray = name.toCharArray();

charArray[0] += 32;

return String.valueOf(charArray);

}

}

从源码及可看出流程:

1)客户端发送请求到DispacherServlet(由web.xml拦截所有请求到改servlet);

2)由DispacherServlet(核心servlet)控制器查询HanderMapping,找到处理请求的Controller;(这里我用了一个map类似于缓存容器,装载所有的mapping即映射)

3)Controller层调用业务逻辑处理后,返回ModelAndView,即下一层(往往是service、serviceimpl,mapper层)返回的的数据;

4)DispacherSerclet查询视图解析器,找到ModelAndView指定的视图;

5)视图负责将结果显示到客户端。

(3)Mybatis(持久层框架):mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再通过得到Mapper文件sqlSession.getMapper()最后调用的是JDK的动态代理(exlipse一直Ctrl+鼠标左键点击到最后发现如此,源码附上)。

protected T newInstance(MapperProxy mapperProxy) {

return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

发人员只需要创建Mapper接口,并使用Mapper接口即可。Mybatis会对Mapper接口产生动态代理对象,这个动态代理对象实现了Mapper接口,拥有Mapper中定义的所有方法,并对这些方法进行了增强。增强的逻辑是获得sql语句和执行sql语句。

动态代理:

通过实现 InvocationHandler 接口创建自己的调用处理器;

通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

框架核心原理

AOP 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。除了类(classes)以外,AOP提供了切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。Spring的一个关键的组件就是AOP框架,可以自由选择是否使用AOP。提供声明式企业服务,特别是为了替代EJB声明式服务。最重要的服务是声明性事务管理,这个服务建立在Spring的抽象事物管理之上。允许用户实现自定义切面,用AOP来完善OOP的使用可以把Spring AOP看作是对Spring的一种增强。AOP的实现乃至spring框架基本上核心代码都是基于Java语言的反射机制(所谓的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。)。

AOP主要作用就是不通过修改源代码的方式、将非核心功能代码织入来实现对方法的增强。那么Spring AOP的底层如何实现对方法的增强?实现的关键在于使用了代理模式。代理模式的作用就是为其它对象提供一种代理,以控制对这个对象的访问,用于解决在直接访问对象时带来的各种问题,比如要访问的对象在远程的机器上。在面向对象系统中,由于其他某些原因(对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问)等

代理主要分为两种方式:静态代理和动态代理

IOC IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以相较于传统的java servlet需要自己request.getParamiter等需要一系列取值,转换中文,转换值类型的繁琐,更重要的是使得程序的整个体系结构变得非常灵活。

自定义一个IOC容器的思路:

Map做一个容器,然后用解析xml文件的工具解析出需要扫描的包。利用Java反射机制拿到锁具有的方法,属性,注入到Map容器中

DI 依赖注入,是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态地将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻http://辑,而不需要关心具体的资源来自何处,由谁实现。

以上就是深入浅出SSM框架流程以及原理的详细内容,更多关于SSM框架原理的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:企业app开发品牌(app集团旗下品牌)
下一篇:小程序生态奖励(微信小程序激励)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~