一、国际化
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()