SSH深度历险(七) 剖析SSH核心原理(一)

时间:2021-10-26 22:28:12

接触SSH有一段时间了,但是对于其原理,之前说不出来莫模模糊糊(不能使用自己的语言描述出来的就是没有掌握),在视频和GXPT学习,主要是实现了代码,一些原理性的内容还是欠缺的,这几天我自己也一直在反问着自己,学习本不应该是这个样子了,道理倘若不懂:就是常说的老牛只知道低头拉磨,不抬头看路,映射到学习中,如果我们只是一味的写代码,而不懂原理的话,这样的生命力是不持久的,是短暂的,后劲会很不足,反问的学习促使我对这些逐步的深入了思考,参考了很多的网友博客与PDF资料,自己感悟而成,现和大家分享。

首先要明白什么是框架?

框架本身就是结合着JDK,又添加了本身框架必须需要的jar包而成,是解决某种特殊问题(共性)而是建立的框架。框架是众多程序员在开发过程中,遇到问题思考之后,不断的抽出共性的内容而形成的解决某一个特定领域问题的思想结晶。

框架的好处?

是无数程序员在经过了无数次尝试后,总结出来处理特定问题的特定方法,使程序员用最少的努力获得最佳的效果的工具

Web开发模型

我们现在都是分层开发,各层管各层的事,现在主要接触的是MVC思想分层模式,表示层,业务层,持久层,一切以业务为核心的分层方式

SSH是什么?



        Struts2、Spring、Hibernate三个框架,SSH的一个集成框架,是目前较流行的一种Web应用程序开源框架。SSH正是为了应对各个层次的编程问题的最佳实践。现在的理解来看Struts对应表示层,Hibernate对应持久层,而Spring(主要是容器来协调管理Struts,Hibernate来指导工作的,现在可以这么认为是业务逻辑层)

Struts 2框架本身大致可以分为3个部分:核心控制器FilterDispatcher、业务控制器Action和用户实现的企业业务逻辑组件。

基本的原理流程:

1:客户端在浏览器中输入一个url地址。

2:这个url请求通过http协议发送给jboss。

3:jboss根据url找到对应项目里面的web.xml文件。

4:在web.xml里面会发现有struts2的配置。

5:然后会找到struts2对应的struts.xml配置文件。

6:根据url解析struts.xml配置文件就会找到对应的class。

7:调用完class返回一个字String,根据struts.xml返回到对应的jsp。

结合高校的代码实现

jsp页面,前台页面请求

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><div class="accordion" fillSpace="sidebar">
<div class="accordionHeader">
<h2><span>Folder</span>新生入学管理</h2>
</div>
<div class="accordionContent">
<ul class="tree treeFolder">
<li><a href="${contextPath}/dormitory/queryDormitoryAction" target="navTab" rel="uas_system_dormitory">宿舍信息</a>
</li>
</ul>
</div>
</div></span></span></span></span>

web.xml,有struts的配置,经过filter过滤器,读取到struts配置

<span style="font-size:18px;"><filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<!--<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> -->
<init-param>
<param-name>config</param-name>
<param-value>struts-default.xml,struts-plugin.xml,config/struts-common.xml
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping></span>

struts-dormitory.xml配置,其

<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"> <struts>
<package name="uas-dormitory" namespace="/dormitory" extends="default">
<action name="queryDormitoryAction" class="dormitoryAction"
method="queryDormitory">
<result name="dormitory_list">/page/dormitory/dormitory_list.jsp</result>
</action> <!-- /primer/helloWorldAction.action package:包 * name:包名,唯一的,必选项 * namespace:命名空间,唯一的,相当于房间号。可选项,省略情况下是"/"。页面中请求连接的前半部分
* extends:继承 * extends="struts-default":struts2框架底层提供的核心包struts2-core-2.3.3.jar下的struts-default.xml文件
* 为什么要继承这个struts-default.xml文件? * 因为struts2框架底层提供的struts-default.xml声明了所有的拦截器和拦截器栈,
知道在struts2框架运行时执行struts-default.xml文件中的拦截器栈。 * 如果不继承struts-default.xml文件,就没有办法使用struts2框架提供的所有拦截器 --> <action name="addDormitoryAction" class="dormitoryAction"
method="addDormitory" />
<action name="delDormitoryAction" class="dormitoryAction"
method="delDormitory" />
<action name="delDormitoryByArrayAction" class="dormitoryAction"
method="delDormitoryByArray" />
<action name="updateDormitoryAction" class="dormitoryAction"
method="updateDormitory" /> <!-- 如果找不到对应的action名的时候,配置默认要执行的action * name:指定action的名称 --> <action name="showAddDormitoryAction" class="dormitoryAction"
method="showAddDormitory">
<result name="dormitory_add">/page/dormitory/dormitory_add.jsp</result>
<!-- action: * name:对应页面中请求连接的后面半部分 * class:对应要执行的类的完整路径 -->
</action>
<!-- result:结果类型 * name:对应的是执行的类的方法的返回值 public String execute() throws
Exception { System.out.println("HelloWorldAction ************* execute()");
return "success"; } * 后半部分的文本内容:要转向到的页面 -->
<!-- 没有为action指定class * 在struts2框架底层的struts-default.xml文件中,配置了默认执行的类 com.opensymphony.xwork2.ActionSupport
public String execute() throws Exception { return SUCCESS; } * 实际上,默认执行的是底层提供的ActionSupport类的execute()方法
* result结果类型,默认是根据struts2框架底层提供的ActionSupport类的execute()方法返回值,进行跳转 --> <action name="showUpdateDormitoryAction" class="dormitoryAction"
method="showUpdateDormitory">
<result name="dormitory_update">/page/dormitory/dormitory_update.jsp</result>
</action>
</package>
</struts></span>

spring-dormitory.xml

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <jee:jndi-lookup jndi-name="DormitoryBeanImpl/remote"
id="dormitory-dormitorybean" lookup-on-startup="true" cache="true"
proxy-interface="mgr.uas.dormitory.service.IDormitoryBean"
environment-ref="evn">
</jee:jndi-lookup>
</beans> </span></span></span>

这里主要应用了Spring框架的IOC原理

IOC:控制反转,它是不是什么技术,它是一种设计模式。所谓控制反转就是由容器控制程序间的关系,而不是传统实现中,由编程代码直接操控。说白了就是由容器控制对象间的依赖关系。

DI:Dependency Injection依赖注入 ,即组件(对象)之间的依赖关系由容器在运行期间决定。其实依赖注入和控制反转是对同一概念的不同描述。

Spring通过这种控制反转(IoC)的设计模式促进了松耦合(其实也就是代理模式)。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。我们可以把IoC模式看做是工厂模式的升华(和学习三层时候的运用反射道理是一样的),可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。



个人理解

其实控制反转就是不需要我们手动new一个对象了,它把我们所要实例化的对象都写在了配置文件xml中了,一般这个类都是我们应用的业务类。框架内部已经将xml中配置的类自动实例化成对象,当我们调用某个类A,并且这个类中存在另一个类B时,我们就说A依赖于B,容器就会将B对象注入到A类中,大多数情况下都是通过A类中的setB()方法注入进来的。

以前是由类中的代码查找类并new对象,现在是xml文件控制的对象的生成,控制权由程序代码转移到了xml文件中。这样做还是有好处的,假如在A中需要5个对象,那么A类中就会new5个对象,不管以后A中用不用到这5个类,只要用到A类,就会把这5个类全部new出来。如果我们在xml文件中定义类的话,当类需要用到其中的三个类时,就会用对应的set类()方法将对象注入进来,不用的就不注入进来。

由此看来,第一个方法时将类A和5个类紧紧联系起来,不管用不用到5个类都new一下,真浪费,而第二个方法是第一个类你需要我得时候我就注入进来被你用,你不需要就和我没关系。这样类A和其中的5个类是分别独立的互不干预,当有关系的时候,容器自动注入关系。

总结

系统的效率和灵活性一直都是双向矛盾的,我们是在不断的寻找合适的平衡点,反转依赖注入的方式使程序的效率有些降低,但是系统的灵活性,可维护性大大的提高,在后者来说的利远远大于前者,在效率的方面我们可以提高服务器的性能与cpu、内存等等配置来解决这些不足。

Don't call us,we'll call you(用这句话来形容IoC十分贴切),生活中处处都有学习的影子。

内容未完,下篇继续……