Spring框架
DI
Spring作为一款DI(依赖注入)框架,为了能让它完成依赖注入,程序员需要要编写特定的set方法或者是构造方法,这是最为基本的注入代码准备,Spring1.0版本就支持这两种方式,从2.5版本开始可以通过Autowired注解进行注入。
DI配置
使用Spring,程序几乎将所有对象的创建工作移交给Spring,并配置如何注入依赖,配置的方法支持XML或注解的方式。创建一个ApplicationContext对象,代表一个Spring控制反转(IOC)容器,org.springframework.context.ApplicationContext接口有多个实现,其中ClassPathXmlApplicationContext和FileSystemXmlApplicationContext。这两个实现都需要至少一个包含beans信息的XML文件。ClassPathXmlApplicationContext尝试在类路径中加载配置文件,而FileSystemXmlApplicationContext则从文件系统加载(即C://,D盘之类的路径加载)。
一个spring配置文件可以是一份,也可以是多份,以支持模块化配置。ApplicationContext的实现类支持读取多份配置文件。
ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"config1.xml","config2.xml"});
另一种选择是,通过一份主配置文件,将其他文件导入,在XML中使用<import>:
<import resource="config1.xml"/>
Spring控制反转容器的使用
通过默认构造器创建一个bean实例
前面说将对象的创建交给spring,那么如何获得对象呢?
使用的就是ApplicationContext的getBean方法获得对象。
Product product=context.getBean("product",Product.class);
getBean方法会查询id/name为prouct的bean对象(Spring管理的对象称为一个bean)
对了,这个bean对象是需要在XML文件中配置的:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd "> <bean name="product" class="cn.lynu.Product"></bean> </beans>
推荐使用默认的schema(不带版本号的约束),以便升级spring版本时无需修改配置文件。
该bean的定义告诉spring,通过默认无参的构造器来初始化Product类。如果不存在该构造器(即重写了构造器,但是没有声明默认构造器),则spring会抛出一个异常。使用getBean方法就是根据bean标签的id/name属性去调用该类的无参构造。
通过工厂方法创建一个bean实例
Spring还支持通过调用一个工厂的方法初始化类,使用的是bean标签的factory-method属性。
例如通过工厂方式实例化java.time.LocalDate类.
<bean id="localDate" class="java.time.LocalDate" factory-method="now"/>
表明初始化LocalDate对象使用的是now方法,而不是默认的构造。
ApplicationContext context=new ClassPathXmlApplication(new String[]{"spring-config.xml"}); LocalDate localdate=context.getBean("localDate",LocalDate.class);
销毁前调用的方法
可以在bean标签配置destroy-method属性,来指定在销毁前需要执行的方法。
<bean id="executorService" class="java.util.concurrent.Executors" factory-method="newCachedThreadPool" destroy-method="shutdown" />
创建executorService实例使用newCachedThreadPool 方法,而销毁之前会调用shutdown 方法。
通过调用有参构造来实例化对象
<bean name="featuredProduct" clasa="cn.lynu.Product"> <constructor-arg name="name" value="xxx"/> <constructor-arg name="description" value="xxx"/> <constructor-arg name="price" value="xxx"/> </bean>
使用constructor-arg给构造函数传值,实际上就是调用有参构造:
public Product(String name,String description,float price)
constructor-arg除了可以通过name来匹配,还可以通过指数的方式(index-value)来传递参数,从0开始。
<constructor-arg name="0" value="xxx"/>
但是这种方式,对应构造器所有参数都必须传递,缺一不可。
Setter方式依赖注入
在一个类中依赖其他类,我们无需new其他类的实例,这种依赖关系交给Spring吧。我们则需要声明其引用,并写一个对应的setter方法,并在XML文件中将这两个类的bean配置好,通过property标签的ref来引用。
<bean id="simpleAddress" class="cn.lynu.Address"/> <bean id="employeel" class="cn.lynu.Employee"> <property name="address" ref="simpleAddress"/> </bean>
property标签就是用来调用setter方法设置值的,被引用对象的配置定义无需早于引用其对象的定义。其实constructor-arg 也有ref属性来引用其他的元素,可以通过有参构造器的方式依赖注入。
模式2和MVC
Java Web应用开发有两种设计模型,可以称为Model-1和Model-2,模型1是以页面为中心的,适合小应用开发。而模型2基于MVC模式,是Java Web应用的推荐架构。
在模型2中,Servlet和Filter都可以充当控制器,几乎所有现代的Web应用都是模型2的实现。Struts1,Spring MVC和JavaServer Faces使用一个Servlet作为控制器,而Struts2使用Filter作为控制器.使用Servlet作为前端控制器有一个优点是可以将servlet配置为欢迎页。
可以通过如下几种方式避免用户直接访问JSP 页面:
- 将JSP放到WEB-INF目录下,WEB-INF目录下的所有文件或子目录都无法通过浏览器直接访问,但是控制器可以转发请求到这些页面。
- 利用一个Filter过滤JSP页面。
- 在部署描述符中为JSP页面配置安全限制。
建议:即使可以使用前端HTML5或Javascript进行校验,但是不要因此依赖,因为用户可能会绕过前端校验。始终需要执行服务器端校验。