#Spring是什么
开源的,用来简化企业级应用开发的应用开发框架。
- 简化开发: Spring框架对常用的api都做了封装,比如对jdbc就做了一套封装(Spring Jdbc),使用SpringJdbc访问数据库,就不再需要考虑如何获取连接与关闭连接等操作了。
- 解耦: Spring帮我们管理对象之间的依赖关系(对象之间的耦合度降低了),这样软件的维护性得到提高。
- 集成其它框架:Spring可以很好地和其它的一些框架进行集成,这样,使用这些框架就更方便了。
#Spring容器
(1) 什么是Spring容器?
Spring框架中的一个核心模块,用来管理对象。
管理对象:对象的创建、销毁、初始化等等操作,以及对象之间的依赖关系。
(2) 如何启动Spring容器?
step1.导包。 spring-webmvc
step2.添加Spring配置文件。
step3.启动容器。
(3) 如何创建对象?
- 方式一 无参构造器
step1.为类添加无参构造器或者直接使用缺省构造器。
step2.在配置文件当中,添加bean元素。
<!-- 利用无参构造器创建对象 -->
<!-- bean: 被容器管理的对象。
id:bean的名称,要求唯一。
class:要写的类的完整的名字。
Spring容器利用java反射来查找类的字节码文件,然后完成类的加载。-->
<bean id="a1" class="first.Apple"/>
<bean id="date1" class="java.util.Date"/>
step3.启动容器,调用容器提供的一个方法(getBean)。
- 方式二 静态工厂方法
<!-- 利用静态工厂方法创建对象 -->
<!--
factory-method:指定一个静态方法。容器会调用该方法来创建对象。
Calendar c = Calendar.getInstance();
-->
<bean id="cal1" class="java.util.Calendar"
factory-method="getInstance"/>
- 方式三 实例工厂方法
<!-- 利用实例工厂方法来创建对象 -->
<!--
factory-bean:指定一个bean的id。
容器会调用该bean的实例方法来创建对象。
-->
<bean id="time1" factory-bean="cal1" factory-method="getTime"/>
(4) 作用域
- 默认情况下,对于某个bean元素,容器只会创建一个实例。
- 如果将作用域设置为"prototype",容器会创建多个实例。
<!--
scope:用来设置作用域。缺省值是singleton(单例),
如果值是prototype,则容器会创建多个实例。
-->
<bean id="eb1" class="basic.ExampleBean"
scope="prototype"/>
(5) 生命周期相关的两个方法
1)初始化
使用init-method属性指定初始化方法。
2)销毁
使用destroy-method属性指定销毁方法。
只有作用域为singleton时,销毁方法才会执行。
<!--
init-method:指定初始化方法名。
destroy-method:指定销毁方法名。
只有作用域为singleton时,销毁方法才会执行。
-->
<bean id="mb1" class="basic.MessageBean" init-method="init"
destroy-method="destroy" scope="singleton"/>
(6)延迟加载
1)默认情况下
容器启动之后,会将所有作用域为singleton的bean先创建好。
2)容器启动之后,对于作用域为singleton的bean,不再创建
(当调用getBean方法时才会创建)
<!-- lazy-init:如果值为true,表示延迟加载。-->
<bean id="sb1" class="basic.ScopeBean" lazy-init="true"/>
#IOC和DI
-
IOC (Inversion Of Controll 控制反转)
对象之间的依赖关系由容器来建立。 -
DI(Dependency Injection 依赖注入)
容器通过调用set方法或者构造器来建立对象之间的依赖关系。 -
IOC是目标,DI是手段。
-
依赖注入的两种方式
方式一 set方法注入
step1. 添加set方法。
step2. 在配置文件当中,使用<property>
来配置set方法注入。
step3. 启动容器,调用getBean方法。
<bean id="c1" class="ioc.C"/>
<!--
property: 配置set方法注入,其中
name属性指定调用的方法,而ref属性
指定被注入的bean的id。
-->
<bean id="a1" class="ioc.A">
<property name="b" ref="c1"/>
</bean>
方式二 构造器注入
step1. 添加相应的构造器
step2. 在配置文件当中,使用<constructor-arg>
来配置构造器注入。
step3. 启动容器,调用getBean方法。
<bean id="wt1" class="ioc.Waiter"/>
<!--
constructor-arg:配置构造器注入,index
属性用来指定参数的位置。
-->
<bean id="rest1" class="ioc.Restaurant">
<constructor-arg index="0" ref="wt1"/>
</bean>
4)自动装配
- 容器默认情况下,是不会自动装配的。
- 可以让容器依据某些规则,自动建立对象之间的依赖关系
(仍然需要调用set方法或者构造器)。 - 自动装配建议少用,如果要使用,建议使用byName。
<bean id="wt1" class="autowire.Waiter2"/>
<!--
autowire:配置自动装配。
byName: 容器依据属性名去查找对应的bean(即以属性名作为bean的id),
找到之后,调用对应的set方法。如果找不到对应的bean,不会注入。
byType:容器依据属性类型去查找对应的bean(即查找类型与属性类型一致的bean),
找到之后,调用对应的set方法。如果找到多个,会出错。
constructor:类似于byType,找到之后,会调用构造器来注入。
-->
<bean id="rest" class="autowire.Restaurant2" autowire="byType"/>
#注入基本类型的值
- 使用value属性
<bean id="stu1" class="value.Student">
<property name="name" value="楚荞"/>
<property name="age" value="22"/>
- 注入集合类型的值
List,Set,Map,Properties
(1)方式一 直接注入
<property name="interest">
<list>
<value>喝酒</value>
<value>抽烟</value>
<value>烫头</value>
<value>烫头</value>
</list>
</property>
<property name="city">
<set>
<value>北京</value>
<value>上海</value>
<value>深圳</value>
</set>
</property>
<property name="score">
<map>
<entry key="英语" value="59.5"/>
<entry key="math" value="80"/>
</map>
</property>
<property name="db">
<props>
<prop key="username">tom</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
(2)方式二 引用的方式注入
<!-- 引用的方式注入集合类型的值 -->
<util:list id="interestBean">
<value>钓鱼</value>
<value>国画</value>
<value>做饭</value>
</util:list>
<util:set id="cityBean">
<value>金陵</value>
<value>洛阳</value>
<value>北平</value>
</util:set>
<util:map id="scoreBean">
<entry key="english" value="90"/>
<entry key="math" value="80"/>
</util:map>
<util:properties id="dbBean">
<prop key="username">sally</prop>
<prop key="password">1234</prop>
</util:properties>
<bean id="stu2" class="value.Student">
<property name="interest" ref="interestBean"/>
<property name="city" ref="cityBean"/>
<property name="score" ref="scoreBean"/>
<property name="db" ref="dbBean"/>
</bean>
- 读取properties文件
<!-- 读取properties文件 -->
<!--
容器依据location所指定的位置读取properties文件的内容,并将这些 内容添加到Properties对象里面。 classpath:依据类路径去查找。
-->
<util:properties id="config" location="classpath:config.properties"/>
#Spring表达式
读取bean的属性值或者读取集合类型的值
<!-- 使用Spring表达式读取bean的属性值或者集合类型的值 -->
<bean id="sb1" class="value.SpelBean">
<property name="name" value="#{stu1.name}"/>
<property name="interest"
value="#{stu1.interest[1]}"/>
<property name="score"
value="#{stu1.score['英语']}"/>
<property name="pageSize"
value="#{config['biz1.pagesize']}"/>
</bean>
#注解
step1.使用注解简化配置文件
- 组件扫描
容器会扫描base-package指定的包及其子包下面所有的类,如果该类前面有一些特定的注解(比如 @Component),则纳入容器进行管理(相当于在配置文件当中有一个对应的bean元素一样)。 - 编程步骤
step1.在类前面添加一些特定的注解。
@Component 通用。
@Repository 持久层。
@Service 业务层。
@Controller 控制层。
step2.在配置文件当中,配置组件扫描。
<!-- 配置组件扫描 -->
<!--
容器会扫描base-package指定的包及其子包下面所有的类,如果该类前面有一些特定的注解(比如 @Component),则纳入容器进行管理(相当于在配置文件当中有一个对应的bean元素一样)。
-->
<context:component-scan base-package="annotation"/>
##几个注解
依赖注入相关的几个注解
@Autowired @Qualifier
- 支持set方法注入
- 支持构造器注入
@Resource(只支持set方法注入)
@Value
#SpringMVC
- SpringMVC
是一个用来简化基于MVC架构的web应用程序开发的应用开发框架。
SpringMVC是Spring框架的一部分。
##MVC
(Model 模型 View 视图 Controller 控制器)
-
MVC?
是一种软件架构思想,可以将软件划分成三种不同类型的模块,分别
是模型,视图和控制器。
模型用于封装业务逻辑的处理,视图用于数据展现和操作界面,
控制器用于协调模型和视图(视图将请求发送给控制器,由控制器选择对应的模型来处理;模型将处理结果交给控制器,由控制器选择合适的视图来展现处理结果)。 -
如何使用MVC?
- 优点
- 方便测试 (将业务逻辑写在servlet里面,需要部署之后才能测试,而写在java类里面,可以直接测试)。
- 方便代码的维护(修改模型不影响视图,反之也是如此)。
- 方便分工协作。
##五大组件 - DispatcherServlet 前端控制器
- HandlerMapping 映射处理器
- Controller 处理器
- ModelAndView 模型和视图
- ViewResolver 视图解析器
#基于XML配置的mvc应用
step1.导包。
导入Spring-webmvc.jar包(3.2.8)
step2.添加spring配置文件。
step3.配置DispatcherServlet。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!--
DispatcherServlet的初始化方法会启动Spring容器,所以,需要指定Spring配置文件的位置。
DispatcherServlet默认会查找/WEB-INF/springmvc-servlet.xml,以它作为spring的配置文件。其中,springmvc是DispatcherServlet的名字。
比如,将名字改为action,则查找action-servlet.xml。
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
step4.写Controller。
package controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller{
public ModelAndView handleRequest(
HttpServletRequest arg0,
HttpServletResponse arg1)
throws Exception {
System.out.println("handleRequest()");
/*
* ModelAndView有两个常用的构造器
* ModelAndView(String viewName)
* ModelAndView(String viewName,Map data)
* viewName:视图名
* data: 数据
*/
return new ModelAndView("hello");
}
}
step5.写jsp。
<%@page pageEncoding="utf-8"
contentType="text/html; charset=utf-8" %>
<html>
<head></head>
<body style="font-size:30px;">
Hello,SpringMVC!
</body>
</html>
step6.在spring配置文件中,配置HandlerMapping,Controller和ViewResolver。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- 配置HandlerMapping -->
<!--
告诉DispatcherServlet,请求路径与模型(Controller)的对应关系。
-->
<bean
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.do">helloController</prop>
</props>
</property>
</bean>
<!-- 配置Controller(处理器) -->
<bean id="helloController"
class="controller.HelloController"/>
<!-- 配置ViewResolver(视图解析器) -->
<!--
告诉DispatcherServlet,视图名与视图对象的对应关系。视图对象指的是不同的视图技术(比如jsp,freemarker等)。
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
#基于注解的配置的mvc应用
##编程步骤
step1.导包 (spring-webmvc)
step2.添加Spring配置文件。
step3.配置DispatcherServlet。
需要指定初始化参数(因为DispatcherServlet的初始化方法会启动Spring容器,所以,需要知道Spring配置文件的位置)。
step4.写Controller。
a. 不再需要实现Controller接口。
b.方法名不作要求,返回类型可以是ModelAndView,也可以是String。
c.可以有多个方法。
d.在Controller类前添加@Controller。该注解用于组件扫描。
e.使用@RequestMapping来代替HandlerMapping的配置。
该注解可以添加到类前面以及方法前面。
@Controller
//@RequestMapping("/demo")
public class HelloController {
@RequestMapping("/hello.do")
public String hello(){
System.out.println("hello()");
//返回视图名
return "hello";
}
step5.写jsp。
step6.在Spring的配置文件里面,添加:视图解析器,组件扫描,mvc注解扫描,要想让@RequestMapping起作用,需要配置mvc注解扫描。
<!-- 配置组件扫描 -->
<context:component-scan base-package="controller"/>
<!-- 配置MVC注解扫描 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
##读取请求参数值
方式一 通过request
@RequestMapping("/b.do")
/*
* DispatcherServlet利用java反射分析处理器的
* 方法签名(方法名,参数类型,返回类型),然后
* 将需要的对象作为参数传进来。
* 比如,这儿,需要有一个request对象,
* DispatcherServlet就会将request作为参数传进来。
*/
public String bmi(HttpServletRequest request){
System.out.println("bmi()");
String height = request.getParameter("height");
String weight = request.getParameter("weight");
System.out.println(height + " " + weight);
return "view";
}
方式二 通过@RequestParam
@RequestMapping("/b2.do")
/*
*
* DispatcherServlet利用java反射分析方法的签名,
* 会将参数值获得之后,赋给对应的形参。
* 注:
* 可以使用@RequestParam注解告诉DispatcherServlet,
* 形参名与请求参数名的对应关系。
*/
public String bmi2(@RequestParam("height") String height1,String weight){
System.out.println("bmi2()");
System.out.println(height1 + " " + weight);
return "view";
}
方式三 通过javabean
@RequestMapping("/b3.do")
/*
*
* DispatcherServlet通过反射分析方法的签名,
* 会将BmiPraram对象创建好之后传进来。
* 注:
* 会读取相应的请求参数值,并且,会做类型转换。
*/
public String bmi3(BmiParam bp){
System.out.println("b3()");
System.out.println(bp.getHeight()
+ " " + bp.getWeight());
return "view";
}
##向页面传值
方式一 绑订数据到request
@RequestMapping("/b4.do")
public String bmi4(HttpServletRequest request){
String status = "很帅";
request.setAttribute("status", status);
//默认就是转发
return "view";
}
方式二 返回ModelAndView
@RequestMapping("/b5.do")
public ModelAndView bmi5(){
String status = "很帅";
/*
* 将数据添加到ModelAndView。
* DispatcherServlet会将数据(data)取出来,
* 然后绑订到request上(以key作为绑订名)。
*/
Map<String,Object> data = new HashMap<String,Object>();
data.put("status", status);
ModelAndView mav = new ModelAndView("view",data);
return mav;
}
方式三 绑订数据到ModelMap
@RequestMapping("/b6.do")
public String bmi6(ModelMap mm){
double bmi = weight / height / height;
String status = "很帅";
/*
* DispatcherServlet从ModelMap中取出数据,
* 然后绑订到request上(以key作为绑订名)。
*/
mm.addAttribute("status", status);
return "view";
}
方式四 绑订数据到session
@RequestMapping("/b7.do")
public String bmi7HttpSession session){
String status = "很帅";
session.setAttribute("status", status);
return "view";
}
##重定向
情形一 方法的返回值是String
return "redirect:toIndex.do"
情形二 方法的返回值是ModelAndView
RedirectView rv = new RedirectView("toIndex.do");
ModelAndView mav = new ModelAndView(rv);
return mav;