1) Spring是一個IOC(DI)和AOP容器框架。javascript
1) Spring的優良特性html
依賴注入:DI——Dependency Injection,反轉控制(IOC)最經典的實現。前端
面向切面編程:Aspect Oriented Programming——AOPjava
一站式:在IOC和AOP的基礎上能夠整合各類企業應用的開源框架和優秀的第三方 類庫(實際上Spring 自身也提供了表述層的SpringMVC和持久層的Spring JDBC)。mysql
應用程序中的組件須要獲取資源時,傳統的方式是組件主動的從容器中獲取所須要的資源;jquery
反轉控制的思想徹底顛覆了應用程序組件獲取資源的傳統方式:反轉了資源的獲取方向——改由容器主動的將資源推送給須要的組件,開發人員不須要知道容器是如何建立資源對象的,只須要提供接收資源的方式便可web
IOC的另外一種表述方式:即組件以一些預先定義好的方式(例如:setter 方法)接受來自於容器的資源注入。相對於IOC而言,這種表述更直接。spring
IOC 描述的是一種思想,而DI 是對IOC思想的具體實現. sql
<bean>: 讓IOC容器管理一個具體的對象.數據庫
id: 惟一標識
class: 類的全類名. 經過反射的方式建立對象.
Class cls = Class.forName("com.atguigu.spring.helloWorld.Person");
Object obj = cls.newInstance(); 無參數構造器
<property>: 給對象的屬性賦值.
name: 指定屬性名 ,要去對應類中的set方法.
value:指定屬性值
1) 從IOC容器中獲取bean時,除了經過id值獲取,還能夠經過bean的類型獲取。但若是同一個類型的bean在XML文件中配置了多個,則獲取時會拋出異常,因此同一個類型的bean在容器中必須是惟一的。
//1.建立IOC容器 ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml"); //2.獲取HelloWorld對象;惟一標示的id爲「Hi」 HelloWorld bean = (HelloWorld) ioc.getBean("Hi"); 或者這種方式來獲取Bean: HelloWorld helloWorld = ioc.getBean(HelloWorld. class); 或者可使用另一個重載的方法,同時指定bean的id值和類型 HelloWorld helloWorld = cxt.getBean(「helloWorld」,HelloWorld. class); //3.調用HelloWorld中的方法 bean.sayHello();
<!-- 給bean的屬性賦值,(普通類型的值、引用類型的值) 1.經過vlaue屬性或vlaue子標籤(瞭解) 2.經過ref屬性或ref子標籤(瞭解) --> <bean id="employee" class="com.atguigu.spring.entities.Employee"> <property name="id" value="1"></property> <property name="lastName"> <value>kk</value> 可以使用<value>子標籤來賦值; </property> <property name="email" value="kk@qq.com"> </property> <property name="salary" value="10000"> </property> <!-- <property name="deptId" value="2"> </property> --> <property name="dept" ref="department"></property> 有引用數據類型的值 </bean> 配置Department,再將配置好的Department注入到Employee中(使用ref) <bean id="department" class="com.atguigu.spring.entities.Department"> <property name="id" value="2"></property> <property name="name" value="設計"></property> </bean>
引用外部屬性文件 <!-- 方式一:直接配置數據源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="root"></property> <property name="password" value="123456"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> </bean> <!-- 方式二: 引入外部屬性文件以properties的格式 --> <context:property-placeholder location="classpath:druid.properties"/> <!-- 經過引入外部配置文件引入數據源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <property name="url" value="${jdbc.url}"></property> <property name="driverClassName" value="${jdbc.driverClassName}"></property> <property name="initialSize" value="${jdbc.initialSize}"></property> <property name="minIdle" value="${jdbc.minIdle}"></property> <property name="maxActive" value="${jdbc.maxActive}"></property> <property name="maxWait" value="${jdbc.maxWait}"></property> </bean>
建立properties屬性文件(位於src/main/resources);
<!-- 指定properties屬性文件的位置 --> <!-- classpath:xxx 表示屬性文件位於類路徑下 --> <context:property-placeholder location="classpath:jdbc.properties"/>
1) 手動裝配:以value或ref的方式明確指定屬性值都是手動裝配。
2) 自動裝配:根據指定的裝配規則,不須要明確指定,Spring自動將匹配的屬性值注入bean中。
相對於XML方式而言,經過註解的方式配置bean更加簡潔和優雅,並且和MVC組件化開發的理念十分契合,是開發中經常使用的使用方式。
1) 普通組件:@Component
標識一個受Spring IOC容器管理的組件
2) 持久化層組件:@Repository
標識一個受Spring IOC容器管理的持久化層組件
3) 業務邏輯層組件:@Service
標識一個受Spring IOC容器管理的業務邏輯層組件
4) 表述層控制器組件:@Controller
標識一個受Spring IOC容器管理的表述層控制器組件
5) 組件命名規則
①默認狀況:使用組件的簡單類名首字母小寫後獲得的字符串做爲bean的id
②使用組件註解的value屬性指定bean的id
注意:事實上Spring並無能力識別一個組件究竟是不是它所標記的類型,即便將@Respository註解用在一個表述層控制器組件上面也不會產生任何錯誤,因此 @Respository、@Service、@Controller這幾個註解僅僅是爲了讓開發人員本身明確當前的組件扮演的角色。
Spring MVC 經過一套 MVC 註解,讓 POJO 成爲處理請求的控制器,而無須實現任何接口
C(controler ,處理用戶請求的,與servlet功能是同樣的,請求先到達C層;)
M(model模型控制器(業務模型和數據模型))
V(View視圖,視圖解析器來渲染視圖)
請求到達C以後要去拿Model,它再返回給C數據,C再找View(數據以什麼方式進行呈現給用戶),V處理完以後把頁面給C,最後它給用戶。
表現層(出來用戶請求的)、業務邏輯層(出來業務邏輯的)、持久化層(DAO鏈接數據庫)。
SpringMVC在這個基礎上又加了一個前端控制器(配置在web.xml中);它負責分配,讓哪一個C去處理請求;
請求先到前端控制器它先攔截,由它來分配。
) 在web.xml中配置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" id="WebApp_ID" version="2.5"> <!-- 配置前端控制器|核心控制器 DispatcherServlet --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> 文件位置,服務器解析xml時來造這個對象, </init-param> <load-on-startup>1</load-on-startup> 服務器一啓動就把對象造好了,不用發請求 </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> /是爲了覆蓋tomcat服務器中的xml,爲了替代default它攔截的請求(/它是除了jsp不攔截其餘都攔截後交給它處理); </servlet-mapping> //替換它,替換它攔截的請求交給我處理; jsp有專門的jsp處理 <!-- 經過過濾方式配置中文,後端顯示中文不會亂碼 --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
<?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:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 設置自動掃描的包 --> <context:component-scan base-package="com.atguigu.springmvc"></context:component-scan> <!-- 配置視圖解析器來渲染視圖 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置前綴 --> <property name="prefix" value="/WEB-INF/views/"></property> <!-- 配置後綴 --> <property name="suffix" value=".jsp"></property> </bean> <!-- 處理靜態資源,如加載juqery等 --> <mvc:default-servlet-handler/> <!-- 配置了處理靜態資源以後,Handler中的@RequestMapping註解就失效了,此時必須配置如下標籤 --> <mvc:annotation-driven></mvc:annotation-driven> </beans>
前綴 + 返回值 + 後綴,拼接起來 /WEB-INF/views/success.jsp
建立處理器(讓當前類成爲處理器,加@Controller註解)
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="${pageContext.request.contextPath}/script/jquery-1.7.2.js"></script> <script type="text/javascript"> /* alert($); */ </script> </head> <body> <a href="${pageContext.request.contextPath }/hello">Hello SpringMVC</a> <br> <a href="${pageContext.request.contextPath }/testValue">testValue</a> <br> <a href="${pageContext.request.contextPath }/testMethod">testMethod</a> <form action="${pageContext.request.contextPath}/testMethod" method="post"> <input type="submit" value="提交"> </form> <a href="${pageContext.request.contextPath}/testRequestParam?username=admin">test RequestParam</a> <h2>測試入參POJO</h2> <form action="${pageContext.request.contextPath }/testPOJO"> 員工編號:<input type="text" name="id"><br> 員工姓名:<input type="text" name="lastName"><br> 員工郵箱:<input type="text" name="email"><br> 員工薪水:<input type="text" name="salary"><br> 部門編號:<input type="text" name="dept.id"><br> 部門名字:<input type="text" name="dept.name"><br> <input type="submit" value="TestPOJO提交"> </form> <h3>測試入參爲原生SevletAPI</h3> <form action="${pageContext.request.contextPath}/testServletAPI" method="post"> 員工姓名:<input type="text" name="username"> <input type="submit" value="TesetServletAPI"> </form> <!-- 轉發 --> <a href="${pageContext.request.contextPath }/testModelAndView">ModelView</a><br> <a href="${pageContext.request.contextPath }/testMap">Map</a><br> <!-- 重定向 --> <a href="${pageContext.request.contextPath }/testRedirect">Redirect</a> </body> </html>
@Controller public class SpringMVCHandler { public static final String SUCCESS = "success"; /* @RequestMapping處理請求映射;註解中的屬性 * 1.value -用來設置要映射的請求地址 -該屬性的類型是一個String類型的數組,若是映射的請求地址(必須攜帶請求參數params)只有一個那麼大括號能夠省略, 並且value屬性名也能夠省略不寫 2.method -用來設置要映射的請求方式 -若是沒有指定改屬性如post,那麼只看處理的請求地址,無論請求方式,不是默認出來get請求*/ //測試value @RequestMapping(value={"/testValue", "testValue2"}) public String testValue() { System.out.println("測試value"); return SUCCESS; } //測試method @RequestMapping(value="/testMethod" ) 可加請求參數params={"username=admin", "age=18"} public String testMethod() { System.out.println("測試method"); return SUCCESS; /*點擊超連接是get請求*/ } //測試post請求 @RequestMapping(value= "/testMethod", method=RequestMethod.POST) public String testPost() { System.out.println("測試post"); return SUCCESS; } /* @RequestParam註解 -用來映射請求參數,若是Handler方法的入參的參數名和請求參數的參數名一致,那麼該註解能夠不寫(不建議這樣) value屬性: -用來設置請求參數的參數名 required屬性: -用來設置該請求參數是不是必須的,默認是true,是必須的 defaultValue屬性: -用來設置一個默認值,若是沒有攜帶該請求參數那麼將使用此默認值*/ @RequestMapping("/testRequestParam") public String testRequestParam(@RequestParam("username") String username, @RequestParam(value="age", required=false, defaultValue="0") int age) { //或者Integer System.out.println("用戶名是:" + username); System.out.println("年齡是:" + age); return SUCCESS; } //Spring MVC 會按請求參數名和 POJO 屬性名進行自動匹配, 自動爲該對象填充屬性值,支持級聯屬性 @RequestMapping("/testPOJO") public String testPOJO(Employee employee) { System.out.println("員工信息爲:" + employee); return SUCCESS; } /*SpringMVC 的 Handler 方法能夠接受如下ServletAPI 類型的參數 1) ★HttpServletRequest 2)* ★HttpServletResponse
3) ★HttpSession */ @RequestMapping("/testServletAPI") public String testSevletAPI(HttpServletRequest request, HttpServletResponse response) { String username = request.getParameter("username"); System.out.println("用戶名是:" + username); return SUCCESS; } //處理響應數據方法一:將Handler的方法的返回值設置爲ModelAndView @RequestMapping("/testModelAndView") public ModelAndView testModelAndView() { //①建立對象 ModelAndView mv = new ModelAndView(); Employee employee = new Employee(2, "嘿嘿", "hei@qq.com", 20000.3, null); //②添加數據模型 mv.addObject("emp", employee); //③設置視圖名 mv.setViewName("success"); return mv; } //處理響應數據二: /*方法的返回值仍是String類型,在Handler的方法入參中傳入Map、Model或ModelMap 無論在Handler的方法中傳入Map、Model仍是ModelMap,SpringMVC都會轉換爲一個ModelAndView對象*/ @RequestMapping("/testMap") public String testMap(Map<String, Object> map) { Employee employee = new Employee(1, "smile", "sl@126.com", 20000.01, null); map.put("emp", employee); //將模型數據放到map中,最終會放到request域中 return SUCCESS; } //重定向 @RequestMapping("/testRedirect") public String testRedict() { System.out.println("開始重定向"); return "redirect:/redirect.jsp"; } }
Spring與SpringMVC需不須要整合? * 不整合 * 1.將全部的配置都配置到SpringMVC的配置文件中 * 2.將Spring的配置文件經過import標籤引入到SpringMVC的配置文件中 * ★整合 * Spring的配置文件中管理Service、Dao、數據源、事務以及與其餘框架的整合 * SpringMVC的配置文件管理Handler、視圖解析器、處理靜態資源等 * 問題一: * IOC容器如何初始化? * Java工程:new ClassPathXmlApplicationContext("beans.xml"); * Web工程:在web.xml文件中配置ContextLoaderListener這個監聽器 * 問題二: * Handler和Service被建立了兩次? * 讓Spring不掃描Handler * 讓SpringMVC只掃描Handler
springmvc.xml
<!-- 組件掃描 --> <!-- 子標籤context:include-filter:用來設置只掃描那個包下的類 -要讓此標籤生效,必須將父標籤的use-default-filters的屬性值改成false --> <context:component-scan base-package="com.atguigu.ss" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean>
beans.xml
<!-- 設置自動掃描的包 --> <context:component-scan base-package="com.atguigu.ss"> <!-- 子標籤context:exclude-filter:用來設置不掃描那個包下的類 若是type的值是annotation,那麼expression的值是註解的全類名 若是type的值是assignable,那麼expression的值是接口或實現類的全類名 --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan >
web.xml
<!-- 前端控制器 --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 配置ContextLoaderListener監聽器; Web工程--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <!-- Bootstraps the root web application context before servlet initialization --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>