day64_SpringMVC學習筆記_02
1、springmvc對多檢視的支援
(1)匯入xml格式檢視支援的jar包

注意:springmvc本身就支援xml格式,所以不用匯入其他支援的jar包了。
(2)在springmvc.xml中配置支援多檢視
<!-- 配置支援多檢視 --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!-- 配置支援的媒體型別 --> <!-- spring3.2後改成如下配置 --> <property name="contentNegotiationManager"> <bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <!-- 指定多個媒體型別 --> <property name="mediaTypes"> <map> <entry key="json" value="application/json"></entry> <entry key="xml" value="application/xml"></entry> <!-- <entry key="pdf" value="application/pdf"></entry> 需要額外的jar包 --> </map> </property> </bean> </property> <!-- 指定預設的檢視 --> <property name="defaultViews"> <!-- 支援多個檢視 --> <list> <!-- 對json格式檢視的支援 --> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"></bean> <!-- 對xml格式檢視的支援,需要注入建構函式,需要一個jar包:spring-oxm-3.2.0.RELEASE.jar --> <bean class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <!-- 配置對哪些類進行xml轉換的支援,即繫結多個類,演示程式碼中我們只綁定了一個類 --> <property name="classesToBeBound"> <list> <!-- 注意:需要在繫結的類中加入對xml格式檢視轉換的註解:@XmlRootElement --> <value>com.itheima.domain.User</value> </list> </property> </bean> </constructor-arg> </bean> </list> </property> </bean>
小結: 通過以上配置,模擬了WebService對多檢視的支援的功能。
(3)配置javabean,即在繫結的類User中加入對xml格式檢視轉換的註解:@XmlRootElement

<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping>
(5)定義Controller
// 多檢視支援 // 返回的是物件,把返回的物件轉換成json格式檢視和xml格式的檢視 @RequestMapping("multiView") public User multiView() { User user1 = new User(); user1.setId(1); user1.setUsername("曉藝"); user1.setAge("26"); user1.setAddress("物資學院"); user1.setBirthday(new Date()); return user1; }
(6)訪問
根據官方文件約定:訪問的時候需要加上響應的副檔名。
即:訪問json格式的資料,需要加上json副檔名;訪問html格式的資料,需要加上html的副檔名;訪問xml格式的資料,需要加上xml的副檔名。
根據我們web.xml檔案的訪問約定:副檔名.do是訪問jsp頁面的。
我們約定rest目錄下所有以json和xml副檔名都支援相應的檢視。
我們訪問json格式資料的訪問形式如下:

我們訪問xml格式資料的訪問形式如下:

(7) <mvc:annotation-driven/>
<mvc:annotation-driven/> 預設建立:註解處理器對映器、註解處理器介面卡、並提供對json格式資料的支援。
在springmvc.xml中進行配置:
<!-- 表示預設建立:處理器對映器物件、處理器對映器物件,還表示預設啟動json格式資料的支援 --> <mvc:annotation-driven />
但是注意:此時javaBean不能添加註解@XmlRootElement了。@XmlRootElement表示提供對xml檢視支援。
2、SSM整合小案例
2.0、需求
- 實現商品查詢列表,從mysql資料庫中查詢商品資訊。
2.1、使用eclipse,建立一個動態web工程並匯入jar包
- 其中Dynamic web module version版本選擇 2.5,這樣相容性好一些;
- Default output folder設定為 WebRoot\WEB-INF\classes
- Content directory設定為 WebRoot
- 更改JRE System Library[J2SE-1.5]為 JRE System Library[jre1.7.0_80]
- 刪掉沒用的庫:EAR Libraries
- 增加伺服器執行環境庫 Server Runtime,不然jsp檔案會報錯。
- 建立完專案後,將整個專案的編碼改為UTF-8。
- 操作步驟:選中專案右鍵 --> Properties --> Resource --> Text file encoding --> Other中選擇UTF-8。
- 對於動態的java web專案,為了工程目錄結構的清爽,我們將引入的jar包放到“Web App Libraries”中,可以通過“小三角”選擇是否“Show 'Referenced Libraries' Node ”進行調節。
- 對於普通的java專案,為了工程目錄結構的清爽,我們將引入的jar包放到“Referenced Libraries”中,可以通過“小三角”選擇是否“Show 'Referenced Libraries' Node ”進行調節。
匯入jar包
包括:spring(包括springmvc)、mybatis、mybatis-spring整合包、資料庫驅動、第三方連線池、jstl、c3p0管理資料來源、log4j、junit。
參考:“mybatis與springmvc整合全部jar包”目錄。
本次案例共匯入28個jar包。如下圖所示:

2.2、web.xml配置檔案(入口)
web.xml
<?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"> <display-name>day63_SpringMVC_01</display-name> <!-- 配置spring編碼過濾器 --> <filter> <filter-name>characterEcoding</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> </filter> <filter-mapping> <filter-name>characterEcoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置前端控制器:DispatcherServlet --> <servlet > <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 顯示配置載入springmvc.xml檔案,即配置springmvc.xml檔案的初始化引數 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <!-- 配置servlet攔截副檔名 --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- 配置servlet攔截目錄 --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> <!-- 配置載入spring的配置檔案:beans.xml --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> <!-- 這兩種方式均可 --> <!-- <param-value>/WEB-INF/classes/beans.xml</param-value> --> </context-param> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
2.3、springmvc.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" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 配置掃描,把Controller交給spring管理 --> <context:component-scan base-package="com.itheima"></context:component-scan> <!-- 表示預設建立處理器對映器物件、處理器對映器物件,還表示預設啟動json格式資料的支援 --> <mvc:annotation-driven /> <!-- 配置jsp檢視解析器,InternalResourceViewResolver負責解析出真正的邏輯檢視 --> <!-- 後臺返回邏輯檢視:index,jsp檢視解析器解析出真正的物理檢視:字首+邏輯檢視+字尾 ==>/WEB-INF/jsps/index.jsp --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsps/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
2.4、bean.xml配置檔案(相當於applicationContext.xml)
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" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <context:component-scan base-package=""></context:component-scan> <!-- 1、配置資料來源 --> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 2、配置sqlSessionFactory,用於生產sqlSession --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:sqlMapConfig.xml"></property> </bean> <!-- 配置mybatis的Mapper介面代理開發,需要遵循的幾點規範 --> <!-- 1、mapper介面的全限定名要和mapper對映檔案的namespace的值相同。 2、mapper介面的方法名稱要和mapper對映檔案中的statement的id相同。 3、mapper介面的方法引數只能有一個,且型別要和mapper對映檔案中statement的parameterType的值保持一致。 4、mapper介面的返回值型別要和mapper對映檔案中statement的resultType的值或resultMap中的type的值保持一致。 5、mapper介面和mapper對映檔案必須在同一目錄下。 --> <!-- mapper代理開發方式之批量mapper配置,預設bean的id為類名首字母小寫 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 指定批量mapper配置的包名 --> <property name="basePackage" value="com.itheima.dao"></property> <!-- 當只有一個SqlSessionFactory時,預設是不需要配置SqlSessionFactory的 --> <!-- 當有多個SqlSessionFactory時,可以指定使用的SqlSessionFactory --> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!-- 3、配置事務管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置通知:管理事務的策略 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置攔截service:切面程式設計 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.*.*(..))"/> </aop:config> </beans>
2.6、編寫程式碼
mapper層(dao層):
mapper介面程式碼使用Mybatis的逆向工程生成的。
service層:
ItemsService.java
public interface ItemsService { public List<Items> findAll(); public Items findById(Integer id); public void saveOrUpdate(Items items); public void deleteById(Integer id); }
ItemsServiceImpl.java
@Service public class ItemsServiceImpl implements ItemsService { // 注入介面物件(Mapper介面使用代理類) @Resource private ItemsMapper itemsMapper; public List<Items> findAll() { List<Items> list = itemsMapper.findAll(); return list; } public Items findById(Integer id) { Items items = itemsMapper.selectByPrimaryKey(id); return items; } public void saveOrUpdate(Items items) { itemsMapper.updateByPrimaryKey(items); // 商品id通過頁面隱藏域傳過來的 } public void deleteById(Integer id) { itemsMapper.deleteByPrimaryKey(id); } }
controller層(web層/Action層):
ItemsController.java
@Controller @RequestMapping("/items") public class ItemsController { // 注入service物件 @Resource private ItemsService itemsService; // 查詢所有商品方法 @RequestMapping("list") // springmvc使用Model物件進行頁面資料回顯,Model物件相當於javaweb時所學的application物件(應用域物件),所以Model物件中的資料,在頁面上可以通過EL表示式進行獲取。 // 有了Model物件,才可以向物件中放值,那麼Model物件該如何建立呢? // 答:“由於springmvc中放到方法裡面的物件會自動被建立”,那麼我們就把Model物件放到方法裡面。 public String list(Model model) { List<Items> itemsList = itemsService.findAll(); model.addAttribute("itemsList", itemsList); return "itemsList"; } // 修改商品方法 @RequestMapping("editById") public String editById(Integer id, Model model) { // 跟據id查詢商品 Items items = itemsService.findById(id); model.addAttribute("items", items); return "editItems"; } // 修改後儲存方法 @RequestMapping("saveOrUpdate") public String saveOrUpdate(Items items) { itemsService.saveOrUpdate(items); // 商品id通過頁面隱藏域傳過來的 return "redirect:list.do"; } // 跟據id進行刪除 @RequestMapping("deleteById") public String deleteById(Integer id) { itemsService.deleteById(id); return "redirect:list.do"; } // 跟據ids進行批量刪除 @RequestMapping("deleteByIds") public String deleteByIds(Integer[] ids) { // 特別注意:標籤input的name的屬性值id要與方法的形式引數名稱id相同。形參名稱也可以起別名!但需要其他註解配合哦! for (Integer id : ids) { itemsService.deleteById(id); } return "redirect:list.do"; } }
2.7、springmvc檔案上傳
需求分析:
使用ajax,響應json格式資料的形式上傳圖片並立刻回顯。頁面不重新整理圖片回顯立刻。
ajax能不能提交表單? 答:ajax自己不能提交表單。要想ajax提交表單,需要藉助一個外掛。 為什麼我們要提交表單? 答:因為我們要提交一個檔案物件,需要將檔案物件關聯到表單裡面。 當我們點選一個按鈕的時候,這個被關聯到表單裡的物件,才會被提交。 虛擬碼示例如下: // 圖片回顯 <img src=“圖片路徑”/> // 把檔案關聯表單,觸發ajax事件 <input type="file" onchange="ajax事件"/> <input type="hidden" value="圖片相對路徑"/> // 本示例開始,我們不使用 enctype="multipart/form-data" 提交檔案物件了 // 我們直接使用ajax提交檔案物件,我們新增隱藏域,向後臺提交圖片相對路徑
(1)匯入跨伺服器上傳檔案的jar包、IO、fileupload

(2)模擬2臺伺服器
建立一個動態的java web專案:圖片伺服器專案,圖片伺服器專案的伺服器和上傳圖片專案的伺服器埠不一致即可。如下圖所示:

(3)springmvc支援檔案上傳,需要先在springmvc.xml配置檔案中開啟檔案上傳
在springmvc.xml配置檔案中新加入的內容如下:
<!-- 配置開啟檔案上傳,因為我們要跨伺服器上傳,需要寫上id,該id名稱固定 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 配置檔案上傳大小 --> <property name="maxUploadSize" value="1024000"></property> </bean>
(4)前臺頁面ajax
功能:傳送請求,請求上傳圖片,圖片需要被關聯在表單裡。

使用ajax提交form表單的外掛:jquery.form.js

(5)後臺程式碼
@Controller @RequestMapping("/upload") public class UploadController { @RequestMapping("uploadPic") public void uploadPic(HttpServletRequest request, String fileName, PrintWriter out) { // 1、準備檔案上傳流 // 由於上傳的圖片在請求裡面,它是流型別的,直接通過Request物件不能操作 // 所以先要把Request物件強轉成多部件請求物件 MultipartHttpServletRequest mhr = (MultipartHttpServletRequest) request; // 根據檔名稱獲取普通多部件檔案物件 CommonsMultipartFile cmFile = (CommonsMultipartFile) mhr.getFile(fileName); // 獲取檔案上傳流 byte[] fbytes = cmFile.getBytes(); // 2、準備檔名稱 // 檔名稱在伺服器有可能重複,我們使用時間來區分他們 String newFileName = ""; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); newFileName = sdf.format(new Date()); // 在毫秒的時候檔名也可能重複,我們再加點鹽 Random r = new Random(); // [0,1) for (int i = 0; i < 3; i++) { newFileName = newFileName + r.nextInt(10); } // 3、獲取副檔名 String originalFilename = cmFile.getOriginalFilename(); // int x = a.lastIndexOf(b); // 表示b字串在a字串中最後出現的位置,從0開始 String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); // 4、建立jesy伺服器,進行跨伺服器上傳 Client client = Client.create(); // 把檔案關聯到遠端伺服器 // 圖片檔案的完整路徑為:http://127.0.0.1:9005/day64_SSMImageServer/upload/20181027174523998.png WebResource resource = client.resource(Commons.PIC_HOST + "/upload/" + newFileName + suffix); // 上傳圖片檔案 resource.put(String.class, fbytes); // 5、ajax回撥函式需要回顯什麼東西呢? // 圖片需要回顯:需要圖片的完整路徑 // 資料庫儲存圖片:需要圖片的相對路徑 String fullPath = Commons.PIC_HOST + "/upload/" + newFileName + suffix; String relativePath = "/upload/" + newFileName + suffix; // json格式的資料:{"":"","":""} String result = "{\"fullPath\":\"" + fullPath + "\",\"relativePath\":\"" + relativePath + "\"}"; out.print(result); } }
(6)修改圖片伺服器檔案上傳許可權

(7)圖片上傳位置

(8)圖片列表回顯
回顯圖片需要使用<img/>標籤
itemsList.jsp
<c:set var="picPath" value="http://127.0.0.1:9090/day64_SSMImageServer"></c:set> ...... <td> <img id='imgSize1ImgSrc' src='${picPath}${items.pic}' height="100" width="100"/> </td>
editItems.jsp
<c:set var="picPath" value="http://127.0.0.1:9090/day64_SSMImageServer"></c:set> ...... <img id='imgSize1ImgSrc' src='${picPath}${items.pic}' height="100" width="100"/> ......
3、頁面快取
需求:使用頁面快取來提高使用者體驗度。
3.1、簡單理解快取原理
簡單理解快取原理圖解如下:

優點:提升效能。
缺點:不訪問資料庫,不是實時資料。
思考:怎麼樣能中和一下優缺點呢?
- 頁面靜態化:
- 靜態化技術連快取都不走了,直接給你一個HTML頁面,缺點更大。
- 分散式快取:
- 分散式快取能控制`顆粒的大小`,分散式快取使用的是redis,memcached等等
- 這相當於是資料庫,因為我們在任何一層都可以進行操作資料庫。所以可以進行顆粒大小的控制。
3.2、淺談網際網路架構
淺談網際網路架構圖解:

3.3、實現頁面快取
使用 Oscache
實現頁面快取。
(1)建立一個動態的java web專案,匯入所需的jar包

(2)測試:建立一個index.jsp頁面,使用時間來測試

(3)訪問測試
http://localhost:8080/day64_Oscache/index.jsp
http://localhost:8080/day64_Oscache/
分析:上面2個地址都訪問同一個頁面,為什麼快取會變化呢?
快取原理:
快取資料結構:是一個map集合。
key儲存的是瀏覽器訪問的url,上面2個url不一致,快取肯定變化。
value儲存的是快取頁面的資料。
(4)快取的儲存範圍
快取預設儲存在application域當中。
在不同的瀏覽器之間訪問同一地址,快取時間不會發生變化。
(5)改變快取的儲存範圍
改變快取的儲存範圍為session域中。在不同的瀏覽器之間訪問同一地址,快取時間會發生變化。

(6)固定快取的key

由於固定了快取的key,所以以下2個地址訪問同一個頁面,快取時間不會發生變化。
http://localhost:8080/day64_Oscache/index.jsp
http://localhost:8080/day64_Oscache/
(7)要求每隔4秒快取同步(重新整理)一次

(8)要求快取持久化到磁碟或者儲存到redis快取伺服器中
建立oscache.properties,這個配置檔案必須在classpath下面,檔案內容如下:
oscache.properties
cache.memory=false// 不使用快取記憶體 cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener// 持久化類 cache.path=E:\\oscache// 持久化到E盤oscache目錄下
檢視持久化檔案

3.4、在SSM專案中使用Oscache
約定:假如商品頁面訪問量特別大,我們給商品頁面使用快取。即:約定items路徑下所有請求都快取。
(1)將oscache-2.4.1.jar拷貝至專案lib目錄下,並新增至構建路徑
(2)在web.xml中配置快取過濾器

(3)測試快取
打一個斷點(給商品查詢列表),第一次斷點必須走,第二次斷點不走,走快取頁面。
(4)配置快取的持久化
將配置檔案oscache.properties拷貝至專案的config目錄下即可。
4、使用springmvc的其他檢視
4.1、整合freemarker檢視
- 需求:使用springmvc本身的檢視解析器來解析頁面靜態化。
(1)匯入所需要的jar包
com.springsource.freemarker-2.3.15.jar和spring-context-support-3.2.0.RELEASE.jar
(2)在springmvc.xml中配置對freemarker檢視的支援
配置對freemarker檢視的支援後,我們發現我們可以不使用jsp來開發了,我們可以直接使用freemarker檢視來開發。
即:我們可以刪除掉在springmvc.xml中配置的jsp檢視解析器了。

(3)編寫freemarker的頁面
WebRoot/WEB-INF/jsps/ftl.ftl

@Controller @RequestMapping("/ftl") public class FtlController { @RequestMapping("hello") public String hello(Model model) { model.addAttribute("hello","頁面靜態化技術之freemarker"); return "ftl"; } }
(5)修改itemsList.jsp頁面為靜態化頁面itemsList.ftl
itemsList.ftl
<#assign picPath="http://127.0.0.1:9090/day64_SSMImageServer"/> <#assign projectName="day64_SpringMVC_02"/> <!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>查詢商品列表</title> </head> <body> <form action="${projectName}/items/deleteByIds.do" method="post"> 查詢條件: <table width="100%" border=1> <tr> <td><input type="submit" value="查詢"/></td> <td><input type="submit" value="批量刪除"/></td> </tr> </table> 商品列表: <table width="100%" border=1> <tr> <td>商品ID</td> <td>商品名稱</td> <td>商品圖片</td> <td>商品價格</td> <td>生產日期</td> <td>商品描述</td> <td>操作</td> </tr> <#list itemsList as items> <tr> <!-- 新增複選框 --> <td><!-- 特別注意:標籤input的name的屬性值id要與方法的形式引數名稱id相同。 --> <input type="checkbox" name="ids" value="${items.id}"><!-- 複選框中的值需要提交表單才能傳遞給後臺 --> </td> <td>${items.name}</td> <td> <img id='imgSize1ImgSrc' src='${picPath}${items.pic}' height="100" width="100"/> </td> <td>${items.price}</td> <td>${items.detail}</td> <td> <a href="${projectName}/items/editById.do?id=${items.id}">修改</a> <a href="${projectName}/items/deleteById.do?id=${items.id}">刪除</a> </td> </tr> </#list> </table> </form> </body> </html>
(6)訪問測試
訪問地址:http://localhost:8080/day64_SpringMVC_02/items/list.do
訪問測試沒有問題,以上演示就是springmvc對freemarker的支援。
5、攔截器
定義:
Spring Web MVC 的處理器攔截器類似於Servlet開發中的過濾器Filter,用於對處理器進行預處理和後處理。
5.1、區域性攔截器
針對某個HandlerMapping進行配置,只對當前HandlerMapping有效。即針對單個處理器對映器,稱為區域性攔截器。
在springmvc.xml中的配置示例如下:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="handlerInterceptor1"/> <ref bean="handlerInterceptor2"/> </list> </property> </bean> <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/> <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
攔截器程式碼編寫:需要實現HandlerInterceptor介面
public class HandlerInterceptor1 implements HandlerInterceptor { /** * controller執行前呼叫此方法 * 返回true表示繼續執行,返回false中止執行 * 這裡可以加入登入校驗、許可權攔截等 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return false; } /** * controller執行後但未返回檢視前呼叫此方法 * 這裡可在返回使用者前對模型資料進行加工處理,比如這裡加入公用資訊以便頁面顯示 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** * controller執行後且檢視返回後呼叫此方法 * 這裡可得到執行controller時的異常資訊 * 這裡可記錄操作日誌,資源清理等 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
5.2、全域性攔截器
攔截所有請求。
在springmvc.xml中的配置示例如下:
<!--配置全域性攔截器 --> <mvc:interceptors> <!--配置多個攔截器,順序執行 --> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.HandlerInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
攔截器程式碼編寫:需要實現HandlerInterceptor介面
HandlerInterceptor1.java
// 攔截器程式碼編寫:需要實現HandlerInterceptor介面 public class HandlerInterceptor1 implements HandlerInterceptor { /** * controller執行前呼叫此方法,即在處理器對映器之前執行 * 返回true表示繼續執行,返回false中止執行 * 這裡可以加入登入校驗、許可權攔截等 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("這是第1個攔截器的preHandle()方法"); return false; } /** * controller執行後但未返回檢視前呼叫此方法,即呼叫Controller了,還沒返回ModelAndView執行 * 這裡可在返回使用者前對模型資料進行加工處理,比如這裡加入公用資訊以便頁面顯示 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("這是第1個攔截器的postHandle()方法"); } /** * controller執行後且檢視返回後呼叫此方法,即返回ModelAndView之後執行 * 這裡可得到執行controller時的異常資訊 * 這裡可記錄操作日誌,資源清理等 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("這是第1個攔截器的afterCompletion()方法"); }
HandlerInterceptor2.java
// 攔截器程式碼編寫:需要實現HandlerInterceptor介面 public class HandlerInterceptor2 implements HandlerInterceptor { /** * controller執行前呼叫此方法 * 返回true表示繼續執行,返回false中止執行 * 這裡可以加入登入校驗、許可權攔截等 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("這是第2個攔截器的preHandle()方法"); return false; } /** * controller執行後但未返回檢視前呼叫此方法 * 這裡可在返回使用者前對模型資料進行加工處理,比如這裡加入公用資訊以便頁面顯示 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("這是第2個攔截器的postHandle()方法"); } /** * controller執行後且檢視返回後呼叫此方法 * 這裡可得到執行controller時的異常資訊 * 這裡可記錄操作日誌,資源清理等 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("這是第2個攔截器的afterCompletion()方法"); }
5.3、測試
(1)第1個攔截器放行,第2個攔截器也放行。
即兩個攔截器的preHandle()方法都返回true。
測試結果如下:
這是第1個攔截器的preHandle()方法 這是第2個攔截器的preHandle()方法 這是第2個攔截器的postHandle()方法 這是第1個攔截器的postHandle()方法 這是第2個攔截器的afterCompletion()方法 這是第1個攔截器的afterCompletion()方法
(2)第1個攔截器放行,第2個攔截器不放行。
即第一個攔截器的preHandle()方法返回true,第二個攔截器的preHandle()方法返回false。
springmvc規定:凡是方法preHandle()返回true,則方法afterCompletion()必須執行。
測試結果如下:
這是第1個攔截器的preHandle()方法 這是第2個攔截器的preHandle()方法 這是第1個攔截器的afterCompletion()方法
(3)第1個攔截器不放行,第2個攔截器不放行。
即兩個攔截器的preHandle()方法都返回false。
測試結果如下:
這是第1個攔截器的preHandle()方法
5.4、攔截器應用:使用者身份認證
示例程式碼如下:
public class LoginInterceptor implements HandlerInterceptor{ /** * controller執行前呼叫此方法,即在處理器對映器之前執行 * 返回true表示繼續執行,返回false中止執行 * 這裡可以加入登入校驗、許可權攔截等 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 如果是登入頁面則放行 if (request.getRequestURI().indexOf("login.action") >= 0) { return true; // 放行 } HttpSession session = request.getSession(); // 如果使用者已登入也放行 if (session.getAttribute("user") != null) { return true; // 放行 } // 使用者沒有登入跳轉到登入頁面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; // 不放行 } /** * controller執行後但未返回檢視前呼叫此方法,即呼叫Controller了,還沒返回ModelAndView執行 * 這裡可在返回使用者前對模型資料進行加工處理,比如這裡加入公用資訊以便頁面顯示 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** * controller執行後且檢視返回後呼叫此方法,即返回ModelAndView之後執行 * 這裡可得到執行controller時的異常資訊 * 這裡可記錄操作日誌,資源清理等 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
6、springmvc整合Hibernate
未完待續……