springmvc学习
一、springmvc的配置步骤(通过maven)
1、新建项目
File ->newProject
设置项目属性
最后点击Finish
2、配置pox.xml获取所需的jar包
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
若嫌弃下载太慢可通过在maven->conf->setting.xml
的mirrors标签中添加国内镜像即可。
3、新建目录
等所需jar包都通过maven下载好后
在main目录下新建java文件加和resources文件夹,并设置通过鼠标右击文件夹mark Directory as
选择对应功能的文件夹。java文件夹用于存放代码,resources文件夹用于存放配置文件
4、配置springmvc配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 注解扫描 -->
<context:component-scan base-package="com.test.springnvc"></context:component-scan>
<!-- 视图解析器 -->
<!-- 处理方式
/WEB-INF/views/+index+.jsp
-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 开启springmvc框架的支持 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
完成以上步骤即可开始编写代码
二、注释的使用
private static final String SUCCESS = "success";
1、@RequestMapping映射信息
/**
* 1、@RequestMapping 除了可以用来修饰方法还可以用来修饰类
* 2、类定义处:提供初步的请求映射信息。相对于web应用的根目录
* 方法处:提供进一步细分映射信息。相对于类定义处的URL。
* 若类定义处未标注@RequestMapping,则方法处标记的URL相对于web应用的根目录
* @return
*/
@RequestMapping(path = "hello")
public String sayHello(){
System.out.println("HelloWorld");
return SUCCESS;
}
2、使用Method的方式来决定请求方式
/**
* 使用Method的方式来决定请求方式
* @return
*/
@RequestMapping(value="/testMethod",method= RequestMethod.POST)
public String testMethod(){
System.out.println("testMethod");
return SUCCESS;
}
/*
接受请求必须使用post方式
*/
3、可以使用params和headers来精确的映射请求
/**
* 可以使用params和headers来更加精确的映射请求,
* params和headers 支持简单的表达式
* @return
*/
@RequestMapping(value="testParamsAndHeaders",params = {"username","password!=1234"},headers = {})
public String testParamsAndHeaders(){
System.out.println("testParamsAndHeaders");
return SUCCESS;
}
/*
接受请求必须满足所带参数包含username,以及password,并且password不能为1234
若headers有条件同理
*/
4、@RequestMapping支持Ant风格的URL
/**
* -@RequestMapping支持Ant风格的URL
* * 匹配文件名中的任意字符
* ** 匹配多层路径
* ? 匹配文件名中的一个字符
* @return
*/
@RequestMapping("/testAntPath/*/abc")
public String testAntPath(){
System.out.println("testAntPath");
return SUCCESS;
}
/*
可以通过http://localhost:8080/springmvc_test/testAntPath/asdas/abc
或者是http://localhost:8080/springmvc_test/testAntPath/asdqweqas/abc等请求
*/
5、@PathVariable的应用
/**
* -@PathVariable 可以映射URL中的占位符到目标方法的参数中
* @return
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id")String url){
System.out.println("testPathVariable"+"---"+url);
return SUCCESS;
}
/*
即假如URL为 http://localhost:8080/springmvc_test/testPathVariable/123
则控制台会输出 testPathVariable---123
*/
6、Rest风格的URL
/**
* Rest风格的URL
* 以CRUD 为例:
* 新增: /order POST
* 修改: /order/1 PUT update?id=1
* 获取: /order/1 GET get?id=1
* 删除: /order/1 DELETE delete?id=1
*
* 如何发送 PUT 请求和 DELETE 请求呢?
* 1、需要配置HiddenHttpMethodFilter
* 2、需要发送 POST 请求
* 3、需要在发送 POST 请求时携带一个 name="_method" 的隐藏域,value要等于 DELETE 或 PUT
*
*/
@RequestMapping(value = "/testRestPUT/{id}",method = RequestMethod.PUT)
public String testRestPUT(@PathVariable("id") String id){
System.out.println("testRest PUT: " + id);
return SUCCESS;
}
@RequestMapping(value = "/testRestDelete/{id}",method = RequestMethod.DELETE)
public String testRestDelete(@PathVariable("id") String id){
System.out.println("testRest DELETE: " + id);
return SUCCESS;
}
@RequestMapping(value = "/testRestPost",method = RequestMethod.POST)
public String testRestPost(){
System.out.println("testRest POST: ");
return SUCCESS;
}
@RequestMapping(value = "/testRestGet/{id}",method = RequestMethod.GET)
public String testRestGet(@PathVariable("id") String id){
System.out.println("testRest GET: " + id);
return SUCCESS;
}
三、参数的使用
1、@RequestParam
/**
* -@RequestParam 来映射请求参数
* value 请求参数参数名
* required 该请求参数是否是必须的,默认为true
* defaultValue 请求参数默认值
*
*/
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(value = "username")String username
,@RequestParam(value = "age",required = false,defaultValue = "0") int age){
System.out.println("testRequestParam:username = "+username+",age = "+age);
return SUCCESS;
}
2、@RequestHeader
/**
* -@RequestHeader 映射请求头文件信息
*/
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept-Language") String al){
System.out.println("testRequestHeader: Accept-Language = "+al);
return SUCCESS;
}
3、@CookieValue
/**
* -@CookieValue 映射一个cookie值
* 属性同@RequestParam
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID")String sessionId){
System.out.println("testCookieValue: JSESSIONID = "+sessionId);
return SUCCESS;
}
4、POJO类作为参数
/**
* SpringMvc会按参数名和POJO属性名进行自动匹配,自动为该对象填充属性值。
* 支持级联属性。
*/
@RequestMapping("/testPOJO")
public String testPOJO(User user){
System.out.println("testPOJO: " + user);
return SUCCESS;
}
<form action="springmvc/testPOJO" method="post">
username:<input type="text" name="username"/><br>
password:<input type="password" name="password"/><br>
age:<input type="text" name="age"/><br>
city:<input type="text" name="address.city"/><br>
province:<input type="text" name="address.province"/><br>
<input type="submit" value="submit"/>
</form>
user类
Address类
5、使用Servlet原生API作为参数
/**
* 可以使用Servlet原生api作为目标放大和参数
* 具体支持一下类型:
* HttpServletRequest
* HttpServletResponse
* HttpSession
* java.security.Principal
* Locale InputStream
* OutputStream
* Reader
* Writer
*/
@RequestMapping("/testServletApi")
public String testServletApi(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Writer out){
System.out.println("testServletApi");
return SUCCESS;
}
四、处理模型数据
1、ModelAndView
/**
* 目标的返回值可以是ModelAndView类型
* 其中可以包含视图和模型信息
* SpringMvc会把ModelAndView的model中数据放到request域对象中
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String view = SUCCESS;
ModelAndView modelAndView = new ModelAndView(view);
modelAndView.addObject("time" ,new Date());
return modelAndView;
}
结果
2、Map
/**
* 目标方法可以添加map类型(实际也可以是model类型或者modelmap类型)的参数
*/
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("zhangsan","lisi","wangwu"));
return SUCCESS;
}
结果
3、@SessionAttributes
@SessionAttributes(value = {"user"},types = {String.class})
@Controller
public class HelloWorldController {
/**
* -@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(value)
* 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(types)
*
* 注意:改注解只能放在类的上面。而不能修饰方法。
*/
@RequestMapping("/testSessionAtrribute")
public String testSessionAtrribute(Map<String,Object> map){
map.put("user" ,new User("zhangsan","12345",12,new Address("xiamen","fujian")));
map.put("string","abcdef");
return SUCCESS;
}
}
结果
4、ModelAttribute
/**
* 1、-@ModelAttribute 被这个标记的方法,会在每一个目标方法执行之前被SpringMvc调用!
* 2、@ModelAttribute 注解也可以来修饰目标方法POJO类型的入参,其value属性值有如下作用:
* 1).SpringMVC会使用value属性值在implicitModel中查找对应的对象,若存在则会直接传入到目标方法的入参当中
* 2).SpringMVC会以value为key,POJO类型对象为value,存入到request中
*/
@ModelAttribute
public void getStu(@RequestParam(value = "id",required = false) Integer id,Map<String,Object> map){
System.out.println("modelAttribute method");
if(id != null){
//模拟从数据库中获取对象
Student student = new Student(1,"zhangsan","123456",12);
System.out.println("从数据库中获取对象"+student);
map.put("stu",student);
}
}
/** -@ModelAttribute运行流程
* 1、执行@ModelAttribute注解修饰的方法:从数据库取出对象,把对象放入到了Map中。键为student
* 2、SpringMVC 从Map中取出Student对象,并把表单参数赋值给该Student对象的对应属性。
* 3、SpringMVC 把上述对象传入目标方法的参数。
*
* 注意:在@ModelAttribute修饰的方法中,放入到Map时的键需要和目标方法入参类型的第一个字母小写的字符串一致
*
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("stu") Student student){
System.out.println("testModelAttribute update :"+student);
return SUCCESS;
}
前端视图
<form action="springmvc/testModelAttribute" method="post">
<input type="hidden" name="id" value="1"/>
name:<input type="text" name="name" value="zhangsan"/><br>
age:<input type="text" name="age" value="12"/><br>
<input type="submit" value="submit"/>
</form>
输入
结果
五、其他
1、SpringMVC国际化
1)写好国际化的properties文件
2)用ResourceBundleMessageSource在spring配置文件中配置国际化资源文件
<!-- 配置国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
<!-- 支持UTF-8的中文 -->
<property name="cacheSeconds" value="0"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
3)jsp页面使用fmt标签
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>>
<html>
<head>
<title>Title</title>
</head>
<body>
<fmt:message key="i18n.username"></fmt:message>
<br><br>
<fmt:message key="i18n.password"></fmt:message>
</body>
</html>
4)结果
乱码的解决方式
i18n_zh_CN
i18n.username = 用户名
i18n.password = 密码
i18n_en_US
i18n.username = username
i18n.password = password
2、mvc:view-controller标签
<!-- 配置直接转发页面 -->
<!-- 可以直接转发相应的页面,而无需通过handler的方法 -->
<mvc:view-controller path="/success" view-name="success"/>
<!-- 在实际开发中通常都需配置mvc:annotation-driven 标签 -->
<!-- 开启springmvc框架的支持 -->
<mvc:annotation-driven></mvc:annotation-driven>
3、自定义视图
1)java类实现View
@Component
public class HelloView implements View {
/**
* 返回内容类型
*/
@Override
public String getContentType() {
return "text/html";
}
/**
* 渲染视图
*/
@Override
public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.getWriter().println("Hello view, time : " + new Date());
}
}
2)在Spring配置文件中配置视图解析器
<!-- 通过配置BeanNameViewResolver解析器:使用视图名字来解析视图 -->
<!-- 通过order属性来定义视图解析器的优先级,order值越小优先级越高 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
3)结果
4、重定向
/**
* 如果返回字符串中带 forward: 或 redirect: 前缀时SpringMVC会对他们进行特殊处理
* forward: 转发
* redirect: 重定向
*/
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "redirect:/index.jsp";
}
六、利用HiddenHttpMethodFilter模拟CRUD操作
1、在web.xml中配置HiddenHttpMethodFilter拦截器
<!-- 配置org.springframework.web.filter.HiddenHttpMethodFilter:可以把POST请求转为DELETE或PUT请求 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2、配置对应的控制器
@Controller
public class StudentController {
@Autowired
StudentDAO studentDAO;
@Autowired
TeacherDAO teacherDAO;
@ModelAttribute
public void getStudent(@RequestParam(value = "sno",required = false) String sno,Map<String,Object> map){
if(sno != null){
map.put("student",studentDAO.getStuBySno(sno));
}
}
//更新学生数据操作
@RequestMapping(value = "/stu",method = RequestMethod.PUT)
public String update(Student student){
studentDAO.saveStu(student);
return "redirect:/stus";
}
//进入编辑学生界面
@RequestMapping(value = "/stu/{sno}",method = RequestMethod.GET)
public String input(@PathVariable("sno") String sno,Map<String,Object> map){
map.put("student",studentDAO.getStuBySno(sno));
map.put("teachers",teacherDAO.getTeachers());
return "input";
}
//所有学生列表
@RequestMapping("/stus")
public String list(Map<String, Object> map){
map.put("students",studentDAO.getAllStu());
return "list";
}
//进入添加页面
@RequestMapping(value="/stu",method = RequestMethod.GET)
public String input(Map<String,Object> map){
map.put("teachers",teacherDAO.getTeachers());
map.put("student",new Student());
return "input";
}
//添加学生操作
@RequestMapping(value="/stu",method = RequestMethod.POST)
public String insertStu(Student student){
studentDAO.addStu(student);
return "redirect:/stus";
}
//删除学生操作
@RequestMapping(value = "/stu/{sno}",method = RequestMethod.DELETE)
public String deleteStu(@PathVariable("sno") String sno){
studentDAO.deleteStuBySno(sno);
return "redirect:/stus";
}
}
3、解决中文乱码问题
在web.xml中配置CharacterEncodingFilter拦截器修改编码方式
<!--springmvc提供的解决post/get请求参数中文乱码问题-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4、页面中表单回显
<!--
1、为什么使用form(springmvc)标签呢?
可以更快速的开发出表单页面,而且可以更方便的进行表单回显
2、注意:
可以通过ModelAttribute属性指定绑定的模型属性
若没有指定该属性,则默认request域对象中读取command的表单bean,如果该属性值也不存在,则会发生错误。
-->
<!-- springmvc表单标签默认回显 -->
<form:form action="${pageContext.request.contextPath}/stu" method="post" modelAttribute="student">
<!-- path属性对应html表单标签的name属性值 -->
<c:if test="${student.sno == null}">
name:<form:input path="name"/><br>
</c:if>
<c:if test="${student.sno != null}">
<form:hidden path="sno"/><br>
<input type="hidden" name="_method" value="PUT"/>
</c:if>
age:<form:input path="age"/><br>
mark:<form:input path="mark"/><br>
teacher:
<form:select path="teacherno" items="${teachers}" itemLabel="name" itemValue="teacherno"></form:select><br>
<input type="submit" value="submit"/><br>
</form:form>
七、数据操作
1、数据类型转换
必做操作
配置mvc:annotation-driven
<mvc:annotation-driven></mvc:annotation-driven>
前端界面(包括输入)
1)在spring配置文件中配置类型转换器
<!-- 配置ConversionService类型转换器
所有注册的Converter实例对象都可以在RequestParamMethodArgumentResolverd的binder属性中的conversionServices属性中查看到
用FormattingConversionServiceFactoryBean
既可以添加自定义的类型转换器,又可以使用springmvc提供的格式化作用
-->
<bean id="conversionService2" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="studentServiceConverer"></ref>
</set>
</property>
</bean>
2)自定义类型转换器
@Component
public class StudentServiceConverer implements Converter<String, Student> {
/**
* 将输入数据转化为学生类
*/
@Override
public Student convert(String source) {
if(source != null){
String[] vals = source.split("-");
// T003-2116062-王五-11-66
if(vals.length == 5){
String teacherno = vals[0];
String sno = vals[1];
String name = vals[2];
Integer age = Integer.parseInt(vals[3]);
Integer mark = Integer.parseInt(vals[4]);
Student student = new Student(teacherno,sno,name,age,mark);
return student;
}
}
return null;
}
}
3)将刚刚配置的类型转换器配置到注解驱动中
<mvc:annotation-driven conversion-service="conversionService2"></mvc:annotation-driven>
4)InitBinder注解
// @InitBinder
// public void initBinder(WebDataBinder binder){
// //设置在表单对javabean进行赋值时那个值不进行赋值
// binder.setDisallowedFields("name");
// }
2、数据格式化
1、配置mvc:annotation-driven
2、表明注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date brith;
@NumberFormat(pattern = "#.##m")
private Float high;
3、数据校验
1)步骤
①使用JSR 303验证标准
②加入 hibernate validator验证框架
③在springmvc配置文件中加入<mvc:annotation-driven/>
<mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean
④需要在bean的属性上配置对应的注解
⑤在目标方法bean类型的前面添加@Valid注解
2)maven配置
<!-- JSR 303 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.1.GA</version>
</dependency>
</dependencies>
3)注解配置
@NotEmpty
private String name;
@Max(100)
@Min(0)
private Integer mark;
@Past
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date brith;
在目标方法bean类型前添加@Valid
public String insertStu(@Valid Student student, BindingResult bindingResult,Map<String,Object> map)
4)运行效果
4、错误消息显示及国际化
1)错误消息显示
<!-- 用于在页面上显示错误消息的信息
path属性 对应的错误信息,*代表显示全部错误信息
-->
<form:errors path="*"></form:errors>
2)配置国际化properties文件
#注解类型(要与数据校验中的注释配置对应).目标方法的类名(在request中的类名,或者被modelAttribute修饰的类名).对象属性名
NotEmpty.student.name = name不存在
Max.student.mark = mark不能大于100
Min.student.mark = mark不能小于0
Past.student.birth = birth不能是未来日期
#typeMismatch 在数据绑定时,数据类型不匹配时发生错误
#methodInvocation springmvc在调用处理方法时发生错误
typeMismatch.student.birth = 不是一个日期
typeMismatch.student.high = 不是一个升高
3)结果
八、返回数据处理
1、返回Json
1)导入jackson相关jar包
<!--Jackson required包-->
<!-- jackson包可能不兼容会导致 Servlet.init() for servlet DispatcherServlet threw exception -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
2)配置@ResponseBody注解
@ResponseBody
@RequestMapping("testJson")
public Collection<Student> testJson(){
return studentDAO.getAllStu();
}
3)返回结果
2、HttpMessageConverter
1)原理图
通过HttpMessageConverter转化为对应的对象然后转化为对应的输入输出流
2)使用
下载文件效果
httpHeader详解
/**
* 文件下载效果
*/
@ResponseBody
@RequestMapping("testResponseEntity")
public ResponseEntity<byte[]> testResponseEntity(HttpSession httpSession) throws IOException {
byte[] body = null;
ServletContext servletContext = httpSession.getServletContext();
InputStream in = servletContext.getResourceAsStream("/files/abc.txt");
body = new byte[in.available()];
in.read(body);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Content-Disposition","attachment;filename=abc.txt");
HttpStatus httpStatus = HttpStatus.OK;
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(body,httpHeaders,httpStatus);
return responseEntity;
}
读取文件内容效果
java代码:
/**
* @ResponseBody 目标方法的返回值
* @RequestBody 目标方法的入参
*/
@ResponseBody
@RequestMapping("testHttpMessageConverter")
public String testHttpMessageConverter(@RequestBody String body){
System.out.println(body);
return "Hello world" + new Date();
}
jsp代码:
<form action="testHttpMessageConverter" method="post" enctype="multipart/form-data">
File:<input type="file" name="file">
Desc:<input type="text" name="desc">
<input type="submit" value="submit">
</form>
结果:
下载文件效果
选择文件读取
九、国际化
1、国际化的方式
关于国际化
1、在页面上能够根据浏览器语言设置情况对文本(不是内容),时间,数值进行本地化处理
2、可以在bean中获取国际化资源文件Locale 对应的消息
3、可以通过超链接切换Locale,而不再依赖于浏览器的语言设置情况
解决:
1、使用jstl的fmt标签
2、在bean中注入ResourceBundleMessageSource 的实例,使用其对应的getMessage方法即可
3、配置LocalResolver和LocaleChangeInterceptor
2、时间,数值进行本地化处理
1)配置国际化资源文件
<!-- 配置国际化资源文件ResourceBundleMessageSource -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
<!-- 支持UTF-8的中文 -->
<property name="cacheSeconds" value="0"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
2)界面
<!-- 界面i18n -->
<fmt:message key="i18n.user"></fmt:message>
<br><br>
<a href="i18n2">i18n2</a>
<!-- 界面i18n2 -->
<fmt:message key="i18n.password"></fmt:message>
<br><br>
<a href="i18n">i18n</a>
3)界面效果
语言首选项zh-CN
显示界面1
显示界面2
语言首选项en-US
显示1
显示2
4)补充:不想通过控制器直接访问配置
<!-- spring配置文件配置 -->
<!-- 不通过控制器直接访问 -->
<!-- <mvc:view-controller path="/i18n" view-name="i18n"></mvc:view-controller>-->
<mvc:view-controller path="/i18n2" view-name="i18n2"></mvc:view-controller>
3、通过超链接改变Locale
1)控制器
/**
* 用于获取国际化资源文件对应的消息
*/
@Autowired
ResourceBundleMessageSource messageSource;
/**
* 通过超链接修改locale,国际化
*/
@RequestMapping("/i18n")
public String testI18n(Locale locale){
String message = messageSource.getMessage("i18n.user",null,locale);
System.out.println(message);
return "i18n";
}
2)配置SessionLocaleResolver
<!-- 国际化页面配置(通过超链接选择语言那种)
配置SessionLocaleResolver用于将Locale对象存储于Session中供后续使用(这里的Id只能用这个:localeResolver,否则会出问题) 第一步:
-->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<mvc:interceptors>
<!-- 配置国际化页面拦截器(通过超链接选择语言那种)配置LocaleChangeInterceptor
主要用于获取请求中的locale信息,将期转为Locale对像,获取LocaleResolver对象 第二步:
-->
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
<!-- SessionLocaleResolver & LocaleChangeInterceptor工作原理
LocaleChangeInterceptor
1、获取name=locale的请求参数
2、把第一步的locale请求对象参数解析为Locale对象
3、获取LocaleResolver对象
SessionLocaleResolver
4、把Locale对象设置为Session属性
5、从Session中获取Locale对象
应用程序
6、使用Locale对象
-->
3)界面超链接
<!-- 通过locale属性传递locale参数,后面会通过LocaleChangeInterceptor将其封装为Locale对象 -->
<br><br>
<a href="i18n?locale=zn_CH">中文</a>
<br><br>
<a href="i18n?locale=en_US">英文</a>
4)界面效果
待补充
十、文件上传
需要导入的包
<!-- 文件上传的jar包 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
1、单个文件上传
1)控制器
/**
* 文件上传
* 文件被封装为MultipartFile
*/
@RequestMapping("testFileUpload")
public String testFileUpload(@RequestParam("desc") String desc, @RequestParam("file") MultipartFile file) throws IOException {
System.out.println("desc:" + desc);
//获取文件原始的名字
System.out.println("OriginalFilename" + file.getOriginalFilename());
//获取文件所对应的输入流
System.out.println("InputStream" + file.getInputStream());
return "success";
}
2)页面
<h4>文件上传</h4>
<form action="testFileUpload" method="post" enctype="multipart/form-data">
File:<input type="file" name="file">
Desc:<input type="text" name="desc">
<input type="submit" value="submit">
</form>
3)效果
2、多个文件上传
1)控制器
/**
* 多文件上传
*/
@RequestMapping("testFilesUpload")
public String testFilesUpload(@RequestParam("files") MultipartFile[] files) throws IOException {
for (MultipartFile file:files){
System.out.println("OriginalFilename:" + file.getOriginalFilename());
System.out.println("InputStream:" + file.getInputStream());
}
return "success";
}
2)页面
<h4>多个文件上传</h4>
<form action="testFilesUpload" method="post" enctype="multipart/form-data">
File1:<input type="file" name="files">
File2:<input type="file" name="files">
<input type="submit" value="submit">
</form>
3)效果
十一、自定义拦截器
1、继承HandlerInterceptor
public class MyFirstInterceptor implements HandlerInterceptor {
/**
* 该方法在目标方法之前被调用
* 若返回true,则继续调用后续的拦截器和目标方法
* 若返回false,则不会再调用后续的拦截器和目标方法
*
* 用处:
* 可以考虑做权限,日志,事物等
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyFristInterceptor preHandle");
return true;
}
/**
* 调用在目标方法之后,但在渲染视图之前
*
* 用处:
* 可以对请求域中的属性或者视图做出修改
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyFristInterceptor postHandle");
}
/**
* 渲染视图之后被调用
*
* 用处:
* 释放资源
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyFristInterceptor afterCompletion");
}
}
2、在配置文件中注册拦截器
<mvc:interceptors>
<bean id="myFirstInterceptor" class="com.test.springmvc.crud.interceptor.MyFirstInterceptor"></bean>
<!-- 配置拦截器作用的路径或不作用于那个路径 -->
<mvc:interceptor>
<mvc:mapping path="/stus"/>
<bean id="mySecondInterceptor" class="com.test.springmvc.crud.interceptor.MySecondInterceptor"></bean>
</mvc:interceptor>
<!-- 配置国际化页面拦截器(通过超链接选择语言那种)配置LocaleChangeInterceptor
主要用于获取请求中的locale信息,将期转为Locale对像,获取LocaleResolver对象 第二步:
-->
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
3、拦截器的执行顺序
1)拦截器1为true的时候
2)拦截器1为false的时候
十二、异常处理
1、ExceptionHandler注解处理异常
1)代码
/**
* 1、在 @ExceptionHandler 方法的入参中可以加入 Exception 类型的参数,该参数即对应发生的异常对象
* 2、@ExceptionHandler 方法的入参不能传入Map。若希望把一场信息传导到页面上,需要使用 ModelAndView 作为返回值
* 3、@ExceptionHandler 方法标记的异常优先级问题
* 精度越高优先级越高
* 例如:ArithmeticException和RuntimeException,抛出异常为ArithmeticException ,优先执行被@ExceptionHandler({ArithmeticException.class})修饰的方法
* 4、@ControllerAdvice 如果在当前Handler中找不到 @ExceptionHandler 修饰的方法来处理当前出现的异常
* ,则将会去@ControllerAdvice 标记的类中查找 @ExceptionHandler 修饰的方法来处理异常。
*/
@ExceptionHandler({ArithmeticException.class})
public ModelAndView handleArithmeticException(Exception ex){
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception",ex);
return mv;
}
<body>
<h4>Error</h4>
${exception}
</body>
2)效果
2、ResponseStatusExceptionResolver处理异常
1)@ResponseStatus注解
- 修饰方法
@ResponseStatus(value = HttpStatus.NOT_FOUND,reason = "测试方法@ResponseStatus注解") @RequestMapping("testResponseStatusExceptionResolver") public String testResponseStatusExceptionResolver(@RequestParam("i") Integer i){ if (i==13){ throw new MyException(); } System.out.println("testResponseStatusExceptionResolver"); return "success"; }
- 修饰类
/** * -@ResponseStatus * value返回的状态码 * reason返回的异常原因 */ @ResponseStatus(value = HttpStatus.FORBIDDEN,reason = "测试异常对象@ResponseStatus注释,我的异常") public class MyException extends RuntimeException{ }
2)效果
-
修饰方法
-
修饰类
3、SimpleMappingExceptionResolver处理异常
1)配置SimpleMappingExceptionResolver
<!-- 配置使用 SimpleMappingExceptionResolver 来映射异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 配置异常的映射名 -->
<property name="exceptionAttribute" value="exception"></property>
<!-- 要处理的异常映射全部在其中配置 -->
<property name="exceptionMappings">
<props>
<!--
key 异常的全类名
prop内容 出现该异常跳转的页面
-->
<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
</props>
</property>
</bean>
2)运行触发异常效果
控制器尝试触发下标越界异常
@RequestMapping("testSimpleMappingExceptionResolver")
public String testSimpleMappingExceptionResolver(@RequestParam("i") Integer i){
String[] vals = new String[10];
System.out.println(vals[i]);
return "success";
}
注:若未设置exceptionAttribute属性则默认映射名未exception