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>
    
    
    <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>
    
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>
 
完成以上步骤即可开始编写代码
 
二、注释的使用
 
private static final String SUCCESS 
= "success";
 
1、@RequestMapping映射信息
 
    
    @RequestMapping(path 
= "hello")
    public String 
sayHello(){
        System
.out
.println("HelloWorld");
        return SUCCESS
;
    }
 
2、使用Method的方式来决定请求方式
 
    
    @RequestMapping(value
="/testMethod",method
= RequestMethod
.POST
)
    public String 
testMethod(){
        System
.out
.println("testMethod");
        return SUCCESS
;
    }
    
 
3、可以使用params和headers来精确的映射请求
 
    
    @RequestMapping(value
="testParamsAndHeaders",params 
= {"username","password!=1234"},headers 
= {})
    public String 
testParamsAndHeaders(){
        System
.out
.println("testParamsAndHeaders");
        return SUCCESS
;
    }
    
 
4、@RequestMapping支持Ant风格的URL
 
    
    @RequestMapping("/testAntPath/*/abc")
    public String 
testAntPath(){
        System
.out
.println("testAntPath");
        return SUCCESS
;
    }
    
 
5、@PathVariable的应用
 
    
    @RequestMapping("/testPathVariable/{id}")
    public String 
testPathVariable(@PathVariable("id")String url
){
        System
.out
.println("testPathVariable"+"---"+url
);
        return SUCCESS
;
    }
    
 
6、Rest风格的URL
 
    
    @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
 
    
    @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
 
    
    @RequestMapping("/testRequestHeader")
    public String 
testRequestHeader(@RequestHeader(value 
= "Accept-Language") String al
){
        System
.out
.println("testRequestHeader: Accept-Language = "+al
);
        return SUCCESS
;
    }
 
3、@CookieValue
 
    
    @RequestMapping("/testCookieValue")
    public String 
testCookieValue(@CookieValue("JSESSIONID")String sessionId
){
        System
.out
.println("testCookieValue: JSESSIONID = "+sessionId
);
        return SUCCESS
;
    }
 
4、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作为参数
 
    
    @RequestMapping("/testServletApi")
    public String 
testServletApi(HttpServletRequest httpServletRequest
, HttpServletResponse httpServletResponse
, Writer out
){
        System
.out
.println("testServletApi");
        return SUCCESS
;
    }
 
四、处理模型数据
 
1、ModelAndView
 
    
    @RequestMapping("/testModelAndView")
    public ModelAndView 
testModelAndView(){
        String view 
= SUCCESS
;
        ModelAndView modelAndView 
= new ModelAndView(view
);
        modelAndView
.addObject("time" ,new Date());
        return modelAndView
;
    }
 
结果 
 
2、Map
 
    
    @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 {
    
    @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
 
分析ModelAttribute笔记
 
    
    @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
);
        }
    }
    
    @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>
        
        <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标签
 
    
    
    <mvc:view-controller path="/success" view-name="success"/>
    
    
    <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配置文件中配置视图解析器
 
    
    
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="100"></property>
    </bean>
 
3)结果 
 
4、重定向
 
    
    @RequestMapping("/testRedirect")
    public String 
testRedirect(){
        System
.out
.println("testRedirect");
        return "redirect:/index.jsp";
    }
 
六、利用HiddenHttpMethodFilter模拟CRUD操作
 
1、在web.xml中配置HiddenHttpMethodFilter拦截器
 
  
  <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拦截器修改编码方式
 
  
  <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、页面中表单回显
 
    
    
    <form:form action="${pageContext.request.contextPath}/stu" method="post" modelAttribute="student">
        
        <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配置文件中配置类型转换器
 
    
    <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("-");
            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注解
 
 
2、数据格式化
 
1、配置mvc:annotation-driven 2、表明注解
 
    @DateTimeFormat(pattern 
= "yyyy-MM-dd")
    private Date brith
;
    @NumberFormat(pattern 
= "#.##m")
    private Float high
;
 
3、数据校验
 
JSR 303标准注解说明
 
1)步骤
 
   ①使用JSR 303验证标准
   ②加入 hibernate validator验证框架
   ③在springmvc配置文件中加入<mvc:annotation-driven/>
            <mvc:annotation-driven/> 会默认装配好一个LocalValidatorFactoryBean
   ④需要在bean的属性上配置对应的注解
   ⑤在目标方法bean类型的前面添加@Valid注解
 
2)maven配置
 
    
    <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)错误消息显示
 
<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包
 
    
    
    <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
    @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)配置国际化资源文件
 
 
    
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"></property>
        
        <property name="cacheSeconds" value="0"/>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
 
2)界面
 
    <fmt:message key="i18n.user"></fmt:message>
    <br><br>
    <a href="i18n2">i18n2
</a>
	<fmt:message key="i18n.password"></fmt:message>
    <br><br>
    <a href="i18n">i18n
</a>
 
3)界面效果
 
语言首选项zh-CN 
 
显示界面1  显示界面2  语言首选项en-US  显示1 
 
显示2 
 
4)补充:不想通过控制器直接访问配置
 
	
    
    <mvc:view-controller path="/i18n2" view-name="i18n2"></mvc:view-controller>
 
3、通过超链接改变Locale
 
1)控制器
 
    
    @Autowired
    ResourceBundleMessageSource messageSource
;
    
    
    @RequestMapping("/i18n")
    public String 
testI18n(Locale locale
){
        String message 
= messageSource
.getMessage("i18n.user",null
,locale
);
        System
.out
.println(message
);
        return "i18n";
    }
 
2)配置SessionLocaleResolver
 
    
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
    <mvc:interceptors>
        
        <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>
        
 
3)界面超链接
 
	
    <br><br>
    <a href="i18n?locale=zn_CH">中文
</a>
    <br><br>
    <a href="i18n?locale=en_US">英文
</a>
 
4)界面效果
 
待补充
 
十、文件上传
 
需要导入的包
 
    
    <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)控制器
 
    
    @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 {
    
    @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>
        
        <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>
 
3、拦截器的执行顺序
 
1)拦截器1为true的时候
 
 
2)拦截器1为false的时候
 
 
十二、异常处理
 
1、ExceptionHandler注解处理异常
 
1)代码
 
    
    @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 
= HttpStatus
.FORBIDDEN
,reason 
= "测试异常对象@ResponseStatus注释,我的异常")
public class MyException extends RuntimeException{
}
  
2)效果
 
 修饰方法 
  修饰类 
  
3、SimpleMappingExceptionResolver处理异常
 
1)配置SimpleMappingExceptionResolver
 
    
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        
        <property name="exceptionAttribute" value="exception"></property>
        
        <property name="exceptionMappings">
            <props>
                
                <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