一、國際化
1. 國際化_頁面中擷取國際化資源資訊
① 在頁面上能夠根據浏 覽器語言設定的情況對文本, 時間, 數值進行本地化處理
② 可以在 bean 中擷取國際化資源檔案 Locale 對應的消息
③ 可以通過超連結切換 Locale, 而不再依賴于浏覽器的語言設定情況
【1】解決:
①使用 JSTL 的 fmt 标簽
②在 bean 中注入 ResourceBundleMessageSource 的執行個體, 使用其對應的
getMessage 方法即可
③ 配置 LocalResolver 和 LocaleChangeInterceptor
【2】實驗代碼
①定義國際化資源檔案
②聲明國際化資源檔案
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
③配置視圖控制器
<!-- 測試國際化 -->
<mvc:view-controller path="/testI18N" view-name="i18n"/>
<mvc:view-controller path="/testI18N2" view-name="i18n2"/>
④首頁面連結
⑤頁面國際化
/views/i18n.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!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>
</head>
<body>
<fmt:message key="i18n.user"/>
<a href="testI18N2">test I18N2</a>
</body>
</html>
/views/i18n2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!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>
</head>
<body>
<fmt:message key="i18n.password"/>
<a href="testI18N">test I18N</a>
</body>
</html>
2. 國際化_控制器中擷取國際化資源資訊
①屏蔽視圖控制器,執行控制器中方法處理請求
<!-- 測試國際化
<mvc:view-controller path="/testI18N" view-name="i18n"/>
-->
<mvc:view-controller path="/testI18N2" view-name="i18n2"/>
②控制器方法
@Controller
public class I18NHandler {
@Autowired
private ResourceBundleMessageSource messageSource; //從IOC容器中擷取bean對象,進行依賴注入
@RequestMapping("/testI18N")
public String testI18N(Locale locale){
System.out.println(locale);
String user = messageSource.getMessage("i18n.user", null, locale);
System.out.println("i18n.user="+user);
return "i18n";
}
}
3. 國際化_通過超連結切換Locale
- 預設情況下,SpringMVC 根據 Accept-Language 參數判斷用戶端的本地化類型。
- 當接受到請求時,SpringMVC 會在上下文中查找一個本地化解析器(LocalResolver),找到後使用它擷取請求所對應的本地化類型資訊。
- SpringMVC 還允許裝配一個動态更改本地化類型的攔截器,這樣通過指定一個請求參數就可以控制單個請求的本地化類型。
- SessionLocaleResolver & LocaleChangeInterceptor 工作原理
②地化解析器和本地化攔截器
- AcceptHeaderLocaleResolver:根據 HTTP 請求頭的 Accept-Language 參數确定本地化類型,如果沒有顯式定義本地化解析器, SpringMVC 使用該解析器。
- CookieLocaleResolver:根據指定的 Cookie 值确定本地化類型
- SessionLocaleResolver:根據 Session 中特定的屬性确定本地化類型
- LocaleChangeInterceptor:從請求參數中擷取本次請求對應的本地化類型。
4. 實驗代碼:實作中英文語言切換
public class AcceptHeaderLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
return request.getLocale();
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
throw new UnsupportedOperationException(
"Cannot change HTTP accept header - use a different locale resolution strategy");
}
}
① 配置SessionLocaleResolver替換AcceptHeaderLocaleResolver****完成中英文切換
<!-- 配置SessionLocaleResolver對象
id必須是"localeResolver",否則,會報錯誤:
<bean id="sessionLocaleResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
-->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
② 配置
<!-- 配置LocaleChangeInterceptor攔截器 -->
<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
③頁面連結
/views/i18n.jsp 增加頁面連結
<!-- 切換語言 -->
<a href="testI18N?locale=zh_CN">中文</a> | <a href="testI18N?locale=en_US">英語</a>
5. 切換語言的原理:springmvc-i18n.bkpt
切換語言的參數名稱必須:locale
二、檔案上傳
1. 檔案上傳
- Spring MVC 為檔案上傳提供了直接的支援,這種支援是通過即插即用的 MultipartResolver 實作的。
- Spring 用 Jakarta Commons FileUpload 技術實作了一個 MultipartResolver 實作類:CommonsMultipartResovler
- Spring MVC 上下文中預設沒有裝配 MultipartResovler,是以預設情況下不能處理檔案的上傳工作,如果想使用 Spring 的檔案上傳功能,需現在上下文中配置 MultipartResolver
- 配置 MultipartResolver
defaultEncoding: 必須和使用者 JSP 的 pageEncoding 屬性一緻,以便正确解析表單的内容
為了讓 CommonsMultipartResovler 正确工作,必須先将 Jakarta Commons FileUpload 及 Jakarta Commons io 的類包添加到類路徑下。
2. 檔案上傳示例
① 拷貝jar包
commons-fileupload-1.2.1.jar
commons-io-2.0.jar
② 配置檔案上傳解析器
<!-- 配置檔案上傳解析器
id必須是"multipartResolver",否則,會報錯誤:
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="1024000"></property>
</bean>
③ 上傳頁面
<%@ 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>
</head>
<body>
<form action="testUpload" method="post" enctype="multipart/form-data">
檔案: <input type="file" name="file"/><br><br>
描述: <input type="text" name="desc"/><br><br>
<input type="submit" value="送出"/>
</form>
</body>
</html>
④ 控制器方法
@Controller
public class UploadHandler {
@RequestMapping(value="/testUpload",method=RequestMethod.POST)
public String testUpload(@RequestParam(value="desc",required=false) String desc, @RequestParam("file") MultipartFile multipartFile) throws IOException{
System.out.println("desc : "+desc);
System.out.println("OriginalFilename : "+multipartFile.getOriginalFilename());
InputStream inputStream = multipartFile.getInputStream();
System.out.println("inputStream.available() : "+inputStream.available());
System.out.println("inputStream : "+inputStream);
return "success"; //增加成功頁面: /views/success.jsp
}
}
3. 思考多個檔案上傳?
三、攔截器
1.自定義攔截器概述
- Spring MVC也可以使用攔截器對請求進行攔截處理,使用者可以自定義攔截器來實作特定的功能,**自定義的攔截器必須實作HandlerInterceptor接口 **
- preHandle():這個方法在業務處理器處理請求之前被調用,在該方法中對使用者請求 request 進行處理。如果程式員決定該攔截器對請求進行攔截處理後還要調用其他的攔截器,或者是業務處理器去進行處理,則傳回true;如果程式員決定不需要再調用其他的元件去處理請求,則傳回false。
- postHandle():這個方法在業務處理器處理完請求後,但是DispatcherServlet 向用戶端傳回響應前被調用,在該方法中對使用者請求request進行處理。
- afterCompletion():這個方法在 DispatcherServlet 完全處理完請求後被調用,可以在該方法中進行一些資源清理的操作。
2. 實驗代碼(單個攔截器)
① 自定義攔截器類
public class FirstHandlerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
System.out.println(this.getClass().getName() + " - afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
System.out.println(this.getClass().getName() + " - postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println(this.getClass().getName() + " - preHandle");
return true;
}
}
② 配置攔截器
<mvc:interceptors>
<!-- 聲明自定義攔截器 -->
<bean id="firstHandlerInterceptor"
class="com.atguigu.springmvc.interceptors.FirstHandlerInterceptor"></bean>
</mvc:interceptors>
③執行流程
3. 實驗代碼(多個攔截器)
① 自定義攔截器類(兩個)
1号攔截器:
public class FirstHandlerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println(this.getClass().getName() + " - afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
System.out.println(this.getClass().getName() + " - postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println(this.getClass().getName() + " - preHandle");
return true;
}
}
二号攔截器:
public class SecondHandlerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println(this.getClass().getName() + " - afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
System.out.println(this.getClass().getName() + " - postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println(this.getClass().getName() + " - preHandle");
return true;
}
}
② 配置自定義攔截器
<mvc:interceptors>
<!-- 聲明自定義攔截器 -->
<bean id="firstHandlerInterceptor"
class="com.atguigu.springmvc.interceptors.FirstHandlerInterceptor"></bean>
<!-- 配置攔截器引用 -->
<mvc:interceptor>
<mvc:mapping path="/empList"/>
<!-- <mvc:exclude-mapping path="/empList"/> -->
<bean id="secondHandlerInterceptor"
class="com.atguigu.springmvc.interceptors.SecondHandlerInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
③流程路徑
正常流程:
按配置順序依次執行preHandle(),再執行目标方法的擴充卡和處理器;
然後再按一開始倒序來執行postHandle(),再渲染視圖頁面;
然後再倒序執行afterCompletion()
如果流程出現異常的流程:
已執行過preHandle()的會直接跳到執行afterCompletion()