MVC(model-view-controller)是一种软件设计典范,它分离了表现与交互,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
三个核心部件:模型model、视图view、控制器controller
视图:用户看到并与之交互的界面
模型:表示业务数据,并提供数据给视图
控制器:接受用户的输入并调用模型和视图去完成用户的需求
MVC控制流程:
所有的终端用户请求被发送到控制器;控制器依赖请求去选择加载哪个模型,并把模型附加到对应的视图;附加了模型数据的最终视图作为响应发送给终端用户。
Struts2是一个基于MVC设计模式的web应用框架,本质上相当于一个servlet。在MVC设计模式中,Struts2作为控制器层(Controller)来建立模型与视图的数据交互。以webwork为核心,采用拦截器的机制来处理用户请求,核心控制器是FilterDispatcher。
在使用Struts2框架的过程中,需要两个配置文件web.xml和struts.xml,服务器一启动就加载web.xml的配置,web.xml启动时,在StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文件struts.xml完成初始化操作;struts2读取到struts.xml后,以javabean形式存放在内存中,以后struts2对用户的每次请求处理将使用内存中的数据,而不是每次都读取struts.xml文件。
访问流程:
(1)客户端提交请求
(2)请求被提交到一系列过滤器(先ActionContentCleanUp,然后其他过滤器,最后FilterDispatcher)
(3)FilterDispatcher咨询ActionMapper是否需要调用某个Action来处理这个请求,如果ActionMapper决定调用某个Action,FilterDispatcher则把请求的处理交给ActionProxy。
(4)ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类。
(5)ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过代理模式调用Action,但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor(拦截器)
(6)一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result
struts2中Action是核心内容。struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里应该包含与请求参数对应的属性,并提供setter,getter方法。
1、结构更加清晰,地址和类之间的映射都配置在struts.xml中,struts2内部按照MVC设计模式设计,并且作为web开发中MVC设计模式中的Controller层。
2、在操作Action时,可以直接使用参数,不需要考虑request和response,struts2也提供了ServletActionContext对象,通过方法ServletActionContext.getRequest()获得当前请求的对象request(response对象)。
3、Action获得页面bean.属性拼装的实体Bean;页面直接获得Action中的属性。
对象关系映射(Object Relational Mapping,简称ORM)。是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。ORM解决的主要问题是对象关系的映射,主要目的是通过类和对象来操作数据库。简单来说,我们使用ORM可以将我们的对象(或类)去进行映射,使得我们可以去操作对象就能完成对表的操作。
ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
Hibernate是一个对象关系映射框架,它对JDBC(Java DataBase Connectivity,java数据库连接)进行了非常轻量级的对象封装,它将POJO(Plain Ordinary Java Object简单的Java对象,实际就是普通JavaBeans)与数据库表建立映射关系,是一个全自动的orm框架,是一个持久层框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用。Hibernate是一个轻量级的JDBC封装,我们可以使用Hibernate来完成原来我们使用JDBC完成的操作,也就是与数据库的交互操作。它是在dao层去使用的。Hibernate是连接应用程序和数据库的一个中间件,在应用程序中通过创建持久化类来使用Hibernate,这样应用程序不再关心后台所使用的是什么数据库,实现了应用程序的业务逻辑与数据库之间的解耦。
原因如下:
总结:Hibernate是企业级开发中的主流框架,映射的灵活性很出色。它支持很多关系型数据库。
在Hibernate框架内需要两个文件:
hibernate.cfg.xml:用于配置Hibernate和数据库的连接信息。
xxx.hbm.xml(XML映射文件):用来描述持久化类和数据库表、数据列之间的对应关系。
Configuration接口:
Hibernate应用通过创建Configuration实例来指定对象-关系映射文件的位置或者动态配置Hibernate的属性,然后创建SessionFactory实例。
Configuration类:用来加载默认文件路径下的配置文件(hibernate.properties)。调用configure()方法会加载默认文件路径下的xml格式
的配置文件(hibernate.cfg.xml)推荐使用。
如果配置文件在不默认文件路径下或者配置文件名不符合默认规则,可以使用
new Configuration().configure(file)加载指定文件
new Configuration().configure(path) 加载指定路径下的文件
如果使用properties格式的配置文件,可以使用addClass(实体类名.class)方法可以加载映射文件。
一个SessionFactory实例对应一个数据库连接,应用从SessionFactory中获得Session实例。
SessionFactory特点:
(1)它是线程安全的,实例可以被多个应用的线程共享。
(2)它是重量级的,不能随意创建或销毁它的实例。如果应用只访问一个数据库,只需要创建一个SessionFactory实例,在应用初始化的时候创建该实例。如果应用同时访问多个数据库,则需要为每个数据库创建一个单独的SessionFactory实例。
SessionFactory对象:
SessionFactory代表数据库存储源。根据Hibernate配置文件创建对应的数据库存储源。
SessionFactory对象创建后,和Configuration对象再无关联。修改Configuration包含的配置文件信息,不会对SessionFactory有任何影响。
获取SessionFactory对象:new Configuration().configure().buildSessionFactory();
对象的缓存很大,就称为重量级对象。SessionFactory存放了Hibernate配置信息,映射元数据信息等。是重量级对象。
Session接口是Hibernate应用中使用最多的接口。Session也被称为持久化管理器,它提供了和持久化相关的操作,例如数据库的添加、删除、更新、加载和查询。
Session特点:
(1)不是线程安全的,应该避免多个线程共享同一个Session实例。
(2)Session实例是轻量级的,所谓轻量级是指它的创建和销毁不需要耗费太多的资源。意味着在程序中可能经常创建或销毁Session对象,例如可以为每个请求分配单独的一个Session实例。
Session有一个缓存,称为Hibernate的第一级缓存,它存放被当前工作单元加载的对象。每个Session实例都有自己的缓存,这个Session实例的缓存只能被当前工作单元访问。
Session对象:
代表程序和数据库的会话。Session提供了操作数据库的各种方法。是轻量级对象。
获取Session对象
factory.openSession(): 获取新的Session实例。
factory.getCurrentSession():采用该方法创建的Session会取出当前线程中的Session,底层使用ThreadLocal进行存取
save()方法:把Java对象保存到数据库中。
Transaction ts=session.beginTransaction();
User u=new User();
u.setName("赵六");
u.setPassword("123456");
//将对象保存到数据库
session.save(u);
ts.commit();
update()方法:更新数据库的方法
Transaction ts=session.beginTransaction();
//先查出要修改的对象,根据主键值
User user=session.get(User.class, 1);
user.setName("jery");
//将对象更新到数据库,根据OID
session.update(user);
ts.commit();
delete()方法:删除方法
底层根据OID进行删除。有两种方式
(1)
Transaction ts=session.beginTransaction();
User user=session.get(User.class, 1);
//删除指定对象
session.delete(user);
ts.commit();
(2)
Transaction ts=session.beginTransaction();
User user=new User();
user.setId(2);
session.delete(user);
ts.commit();
load()或get()方法:从数据库查找指定对象
session.get(实体类名.class,OID);或session.load(实体类名.class,OID);
如果找不到符合条件的记录,get方法将返回null,而load方法将会抛出ObjectNotFoundException异常。
我们使用get查询时发现控制台会立马打出查询语句。使用load查询时控制台不会打印查询语句。
get方法被调用时立刻发送sql语句到数据库进行查询。
load方法被调用时并没有查询数据库,当我们需要使用查询的对象时,才去查询,所以当我们打印对象时,才会在控制台打印sql语句。
get()的原理
程序调用get方法,Hibernate发送sql语句到数据库
数据库返回结果,Hibernate将结果封装成对象,返回对象到程序。
load()的原理
程序调用load方法,Hibernate使用代理技术,创建一个代理对象,属性只有ID值。
然后返回代理对象给程序,我们使用对象时,代理对象调用Hibernate查询数据库,初始化其他属性。
load方法,返回一个代理对象,获取其属性时,会查询数据库,每次访问属性都会查询数据库么?
答:不是。代理对象中有一个标识是否被初始化的boolean类型变量,记录是否被初始化。
Transaction接口是Hibernate的数据库事务接口,它对底层的事务接口做了封装,底层事务接口包括:JDBC API、JTA(Java Transaction API)、CORBA(Common Object Request Broker Architectture)API。Hibernate应用可通过一致的Transaction接口来声明事务边界,这有助于应用在不同的环境或容器中移植。
封装了事务的操作。我们做增删改查等操作时,必须开启事务.
因为session是线程不安全的,这样主要是为了线程安全。保证数据的正确性。
开启事务: Transaction ts=session.beginTransaction();
提交事务:ts.commit();
回滚事务:ts.rollback();
当通过getCurrentSession获取当前线程绑定的Session时,事务关闭时,会自动把Session关闭并删除。
Query和Criteria接口是Hibernate的查询接口,主要用于数据库对象查询以及控制执行查询的过程。Query实例包装了一个HQL(Hibernate Query Language)查询语句,HQL查询语句是面向对象的,它引用类名及类的属性名,而不是表名及表的字段名。Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更加面向对象,Criteria接口擅长执行动态查询。
Query封装HQL语句的对象。
返回一个对象的方法 query.uniqueResult();
分页相关
query.setFirstResult(index):从第几个取
query.setMaxResults(count):指定取几行记录
使用HQL语言,HQL语言是面向对象的
Query query=session.createQuery("from User");
第二种方式
Criteria c=session.createCriteria(User.class);
List l=c.list();
第三种方式,使用原生sql语句进行查询
SQLQuery query=session.createSQLQuery("select * from user");
List l=query.list();
持久化类是指需要被Hibernate持久化到数据库中的实例所对应的类。
(1)必须有一个无参的构造方法。因为程序运行时,Hibernate会运用java的反射机制,创建实体类的实例。
(2)必须有一个唯一标识属性。在面向对象术语中,这个唯一标识属性被称为对象标识符(OID),这个属性通常映射为数据库的主键。
(3)所有属性必须提供public访问控制符的set get方法。
Session具有一个缓存,是一块内存空间,存放了相互关联的Java对象,这种位于Session缓存内的对象也称为持久化对象,Session负责根据持久
化对象的状态变化来同步更新数据库。Session缓存是内置的,不能被卸除,也被称为Hibernate的第一级缓存。在Session接口的实现类
sessionImpl中定义了一系列Java集合属性,这些Java集合属性构成了Session的缓存。
当Session的save()方法持久化一个Department对象时,Department对象被加入到Session的缓存中,此后即使应用程序中的引用变量不再引用
Department对象,只要Session的缓存还没有被清空,Department对象仍然处于生命周期中。当Session的load()方法试图从数据库中加载一个
Department对象时,Session先判断缓存中是否已经存在这个Department对象,如果存在,就不需要再到数据库中检索。
(1)减少数据库访问频率:应用程序从内存中读取持久化对象的速度显然比到数据库中查询数据要快得多。所以,使用Session的缓存可以提高数据访问性能。
(2)保证缓存中对象与数据库中的数据同步:位于缓存中的对称为持久化对象,当缓存中持久化对象的状态发生了变换时,Session并不会立即执行
相关的SQL语句,这使得Session能够把几条相关的SQL语句合并成一条SQL语句,以便减少数据库访问次数,提高访问效率。
(3)当缓存中的持久化对象之间存在循环关联关系时,Session会保证不出现访问对象图的死循环,以及由死循环引起的JVM堆栈溢出异常。
Session清理缓存的时间点:
(1)应用程序调用Transaction的commit()方法的时候,commit()方法先清理缓存,然后再向数据库提交事务。
(2)应用程序调用Session的find()或者iterate()时,如果缓存中持久化对象的属性发生了变化,就会先清理缓存,以保证查询结果能反映持
久化对象的最新状态。
(3)应用程序显式调用Session的flush()方法的时候。
Hibernate一级缓存又称为“Session的缓存”,它是内置的,不能被卸载。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,
因此它的缓存是事务范围的缓存。第一级缓存是必需的,不允许而且事实上也无法卸除。在第一级缓存中,持久化类的每个实例都具有唯一的OID。
Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是
进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是
可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。
什么样的数据适合存放到第二级缓存中?
1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 常量数据
不适合存放到第二级缓存的数据?
1经常被修改的数据
2 .绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发
3 与其他应用共享的数据。
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;如果都查不到,再查
询数据库,把结果按照ID放入到缓存。删除、更新、增加数据的时候,同时更新缓存。
在管理Hibernate缓存(Managing the caches)时,当你给save()、update()或saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、
iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。
当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你
可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。
(1)瞬态:对象由new操作符创建,且尚未与Hibernate Session关联的对象被认为处于瞬态。瞬态对象不会被持久化到数据库中,也不会被赋予持
久化标识。如果程序中失去了瞬态对象的引用,瞬态对象将会被自动回收。使用Hibernate Session可以将其变为持久化状态。
(2)持久化:持久化实例在数据库中有对应的记录,并拥有一个持久化标识。持久化实例可以是刚刚保存的,也可以是刚被加载的。无论哪一种,持
久化对象都必须与指定的Hibernate Session关联。Hibernate会检测到处于持久化状态对象的改变,在对象操作完成时会将对象数据
自动写回数据库。
(3)脱管:某个实例曾经处于持久化状态,但随着与之关联的Session被关闭,该对象变成了脱管状态。脱管对象的引用依然有效,对象可继续被修
改。如果重新让脱管对象与某个Session关联,这个脱管对象会重新转换为持久化状态,而脱管期间的改动也不会丢失,也可写入数据库。
数据库表与表之间的关联关系一般有3种,即一对一、一对多和多对多关联。其中一对多关联包括单向多对一关联和双向一对多关联。
Spring框架为J2EE平台的开发者提供了一种“对象管理”技术,也就是解决对象的生命周期、对象之间依赖关系的建立、对象的缓存实现等问题的管理
技术。
Sping框架是一个轻量级的控制反转(IoC)技术和面向切面编程(AOP)技术的容器框架,IoC技术可以实现由容器实现对象的生命周期管理,AOP技术
可以实现分离应用系统中的业务逻辑组件和通用的技术服务组件。应用Spring框架能够达到“解耦”和“脱离容器”的设计和实现目的。采用的是分层架构
设计和组件化实现。
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理
bean 的方式。
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
(1)核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory
,它是工厂模式的实现。
BeanFactory
使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
(2)Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,
例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
(3)Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,
可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事
务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
(4)Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商
抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。
Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
(5)Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、
Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
(6)Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。
所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的
工作。
(7)Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成
为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
是spring的核心,是一种设计思想。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。Ioc意味着将你设计好的
对象交给容器控制,而不是传统的在你的对象内部直接控制。所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后
spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象
生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。有
了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能
复用,更重要的是使得程序的整个体系结构变得非常灵活。由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由
Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,
而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定
目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
依赖注入主要有两种注入方式:构造器注入和Setter注入。
AOP主要用于横切关注点分离和织入。
利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所
谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,
并有利于未来的可操作性和可维护性。
使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。
横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的
各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的
商业逻辑同对其提供支持的通用服务进行分离。”
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态
织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
Spring进行bean配置的方式:
Bean注入的方式有两种,一种是在XML中配置,此时分别有属性注入、构造函数注入和工厂方法注入;另一种则是使用注解的方式注入 @Autowired,@Resource,@Required。
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。
属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
@Autowired就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
当Spring发现@Autowired注解时,将自动在代码上下文中找到和其匹配(默认是类型匹配)的Bean,并自动注入到相应的地方去。
@Resource的装配顺序:
(1)、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
(2)、指定了name或者type则根据指定的类型去匹配bean
(3)、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错
@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配。
在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。而bean的定义以及bean相互间的依赖关系将通过配置元数据来描述。Spring中的bean默认都是单例的。
作用域 | 描述 |
---|---|
单例(singleton) | (默认)每一个Spring IoC容器都拥有唯一的一个实例对象 |
原型(prototype) | 一个Bean定义,任意多个对象 |
请求(request) | 一个HTTP请求会产生一个Bean对象,也就是说,每一个HTTP请求都有自己的Bean实例。只在基于web的Spring ApplicationContext 中可用 |
会话(session) | 限定一个Bean的作用域为HTTPsession 的生命周期。同样,只有基于web的Spring ApplicationContext 才能使用 |
全局会话(global session) | 限定一个Bean的作用域为全局HTTPSession 的生命周期。通常用于门户网站场景,同样,只有基于web的Spring ApplicationContext 可用 |
应用(application) | 限定一个Bean的作用域为ServletContext 的生命周期。同样,只有基于web的Spring ApplicationContext 可用 |
request、session和global session三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。
原型的Bean指的就是每次请求Bean实例的时候,返回的都是新实例的Bean对象。也就是说,每次注入到另外的Bean或者通过调用getBean()
来获得的Bean都将是全新的实例。 Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。
请求作用域:
表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。
会话作用域:
表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
全局会话作用域:
表示在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。Servlet是sun公司提供的一门用于开发动态web资源的技术。
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:
Servlet 执行以下主要任务:
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
①Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
②装载并创建该Servlet的一个实例对象。
③调用Servlet实例对象的init()方法。
④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
javaBean在MVC设计模型中是model,又称模型层,在一般的程序中,我们称它为数据层,就是用来设置数据的属性和一些行为,然后我会提供获取属性和设置属性的get/set方法
位于业务逻辑和持久化数据之间,实现对持久化数据的访问。
DAO模式的作用
1隔离业务逻辑代码和数据访问代码
2.隔离不同数据库的实现
业务逻辑层,数据访问层(Oracle,SQLServer,MySQL)
1、session在服务器端,cookie在客户端(浏览器)。
2、session没有大小限制,cookie有大小限制。
3、session默认被存在服务器的一个文件里(不是内存)。
4、session的运行依赖session id,而session id是存在cookie中的,也就是说,如果浏览器禁用了cookie,同时session也会失效(但是可以通过其他方式实现,比如在URL中传递session_id)。
5、session可以放在文件、数据库、或内存中。
6、用户验证这种场合一般会用session。
Session分布式处理方式:
第一种:粘性session
粘性session是指将用户锁定到某一个服务器上,比如用户第一次请求时,负载均衡器将用户的请求转发到了A服务器上,如果负载均衡器设置了粘性session的话,那么用户以后的每次请求都会转发到A服务器上,相当于把用户和A服务器粘到了一块,这就是粘性session机制。
第二种:服务器session复制
任何一个服务器上的session发生改变(增删改),该节点会把这个session的所有内容序列化,然后广播给所有其他节点,不管其他服务器需不需要session,以此来保证session同步。
第三种:session共享机制
使用分布式缓存方案比如memcached、Redis,但是要求memcached或Redis必须是集群。
第四种:session持久化到数据库
拿出一个数据库专门用来存储session信息。保证session的持久化。
第五种:terracotta实现session复制
Terracotta的基本原理是对于集群间共享的数据,当在一个节点发生变化的时候,Terracotta只把变化的部分发送给Terracotta服务器,然后由服务器把他转发给真正需要这个数据的节点。可以看成是对第二种方案的优化。
根据HTTP协议,GET是安全的,也是幂等的,而POST既不是安全的,也不是幂等的。
- 缓存是针对URL来进行缓存的,GET请求由于其参数是直接加在URL上-的,一种参数组合就有一种URL的缓存,可以根据参数来进行一一对应,重复请求是幂等的(不论请求多少次,结果都一样);
- 而POST请求的URL没有参数,每次请求的URL都相同,数据体(HTTPBody)可能不同,无法一一对应,所以缓存没有意义
POST的安全是相对的,对于普通用户来说他们看不到明文,数据封装对他们来说就是屏障。但是对于专业人士,它们会抓包会分析,没有加密的数据包对他们来说也是小case。所以POST仅仅是相对安全,唯有对数据进行加密才会更安全。当然加密也有被破解的可能性,理论上所有的加密方式都可以破解,只是时间长短的问题。而加密算法要做的就是使得破解需要的时间尽量长,越长越安全。由于我们也需要解密,加密算法太过复杂也并非好事,这就要结合使用情况进行折中或者足够实际使用即可。绕的有点远,具体的话,我将在后续的文章之中介提及,并介绍一些常用的加密算法。
HTTP协议中均没有对GET和POST请求的数据大小进行限制,但是实际应用中它们通常受限于软硬件平台的设计和性能。
超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。
HTTP 的工作方式是客户机与服务器之间的请求-应答协议。
web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。
举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。
在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。
请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:
/test/demo_form.asp?name1=value1&name2=value2
有关 GET 请求的其他一些注释:
请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的:
POST /test/demo_form.asp HTTP/1.1 Host: w3schools.com name1=value1&name2=value2
有关 POST 请求的其他一些注释:
下面的表格比较了两种 HTTP 方法:GET 和 POST。
根据HTTP协议,GET是安全的,也是幂等的,而POST既不是安全的,也不是幂等的。GET | POST | |
---|---|---|
后退按钮/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
书签 | 可收藏为书签 | 不可收藏为书签 |
缓存 | 能被缓存 | 不能缓存 |
编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 |
历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。 在发送密码或其他敏感信息时绝不要使用 GET ! |
POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中 |