SpringMVC
导入依赖
<!--SpringMVC依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
<!--jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.0</version>
</dependency>
<!--上传文件依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置UTF-8编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--解决表单不能使用put,delete方式提交-->
<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>
<!--配置springmvc的前端控制器,对浏览器发送的请求统一进行处理-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置error-page-->
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/exception/404.html</location>
</error-page>
</web-app>
配置spring-mvc配置文件
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描controller注解-->
<context:component-scan base-package="com.zhanggang">
<!--只扫描controller-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--配置thymeleaf视图解析器-->
<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".html"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="order" value="1"/>
<property name="templateMode" value="HTML5"/>
<property name="cacheable" value="false"/>
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
</bean>
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
<!--配置上传文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置字符集-->
<property name="defaultEncoding" value="UTF-8"/>
<!--上传文件大小设置最大为50M 单位为byte-->
<property name="maxUploadSize" value="52428800"/>
<!--设置内存大小 40k-->
<property name="maxInMemorySize" value="4096"/>
</bean>
<!--配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--键表示处理器方法执行过程中出现的异常;值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面-->
<prop key="java.lang.ArithmeticException">exception/error</prop>
</props>
</property>
<!--这句话可以将异常信息保存到request域中,键为value值,值为异常名称.前端用thymeleaf接收即可(th:text="${exception}")-->
<property name="exceptionAttribute" value="exception"/>
</bean>
<!--开启注解驱动-->
<mvc:annotation-driven/>
<!--静态文件映射,mapping映射路径,location文件存放的真实路径-->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
<!--默认的servlet,DispatcherServlet处理不了的请求交给defaultServlet来处理-->
<mvc:default-servlet-handler/>
</beans>
常用注解
@RequestMapping
- 作用:可以用在类上也可以用在方法上,最终跳转的路径是二者拼接起来的路径;用在类上常表示不同的模块.
- 注意:请求映射路径必须唯一,不然根本起不来
- 属性:属性越多匹配越精准,常用value和method
value属性
- 通过请求的请求地址匹配请求映射;
- 是一个字符串数组,表示该请求映射能够匹配多个请求地址所对应的请求
- 必须设置,至少通过请求地址匹配请求映射
- 仅有value属性时,value=可以省略
@RequestMapping(value = {"/index","/"})
@RequestMapping({"/index","/"})
method属性
- 通过请求的请求方式(get/post)匹配请求映射
- 是一个RequestMethod类型的数组,表示该请求映射能够匹配多种请求方式的请求
- 若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报405错误
@RequestMapping(value = {"/index"},method = {RequestMethod.GET,RequestMethod.POST})
目前浏览器只支持get/post请求,若在form表单提交时,为method设置了其他请求方式的字符串(delete/put),则按照默认的请求方式get处理。
如要发送put或delete请求,则需要通过spring提供的HiddenHttpMethodFilter
springmvc提供了@RequestMapping的派生注解
- @GetMapping:处理get请求
- @PostMapping:处理post请求
- @DeleteMapping:处理delete请求
- @PutMapping:处理put请求
params属性
- 通过请求的请求参数匹配请求映射
- 是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系
- 若当前请求满足@RequestMapping注解的value属性和method属性,但是不满足params属性时,此页面会报400错误
//1.客户端发送请求时,必须携带key为name的参数
@RequestMapping(value = "/login",method = {RequestMethod.GET},params = {"name"})
//2.客户端发送请求时,不能携带key为name的参数,否则报400错误
@RequestMapping(value = "/login",method = {RequestMethod.GET},params = {"!name"})
//3.客户端发送请求时,必须携带key为name的参数并且参数值必须为zhangsan,否则报400错误
@RequestMapping(value = "/login",method = {RequestMethod.GET},params = {"name=zhangsan"})
//4.客户端发送请求时,必须携带key为name的参数,但是参数值不能为zhangsan,否则报400错误
@RequestMapping(value = "/login",method = {RequestMethod.GET},params = {"name!=zhangsan"})
headers属性
- 通过请求的请求头信息匹配请求映射
- 是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系
- 请求头,如Host、Cookie、User-Agent等
- 若当前请求满足@RequestMapping注解的value和method属性,但是不满足headers属性,此时页面显示404错误,即资源未找到
//要求请求映射所匹配的请求必须携带Host信息
@RequestMapping(value = "/login", method = {RequestMethod.GET}, params = {"name"}, headers = {"Host"})
//要求请求映射所匹配的请求不能携带Host信息
@RequestMapping(value = "/login", method = {RequestMethod.GET}, params = {"name"}, headers = {"!Host"})
//要求请求映射所匹配的请求必须携带Host信息,且Host值必须为localhost:8080
@RequestMapping(value = "/login", method = {RequestMethod.GET}, params = {"name"}, headers = {"Host=localhost:8080"})
//要求请求映射所匹配的请求必须携带Host信息,但是Host值不能为localhost:8080
@RequestMapping(value = "/login", method = {RequestMethod.GET}, params = {"name"}, headers = {"Host!=localhost:8080"})
@PathVariable
- 此注解是用来获得请求url中的动态参数的;
- 通过@PathVariable可以将url中的占位符参数绑定到控制器处理方法的入参中:url中的{xxx}占位符可以通过 @PathVariable("xxx")绑定到操作方法的入参中
@RequestParam
- 是将请求参数和控制方法的形参创建映射关系
- 一共有三个属性:
- value:指定为形参赋值的请求参数的参数名
- required:设置是否必须传输此请求参数,默认值为true
- defauleValue:不管required属性值为true还是fasle,当value所指定的请求参数没有传输或传输的值为“”时,则使用默认值为形参赋值
- 若required设置为true时,则请求参数必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置defaultValue属性,则页面报400错误,如设置为false,则当前请求不是必须传输value所指定的请求参数,若没有传输,则注解所标识的形参的值为null
- @PathVariable和@RequestParam区别:@PathVariable必须传,@RequestParam可传可不传
@RequestHeader
用来获取请求头信息
@RequestHeader(value = "Host") String host
- @RequestHeader是将请求头信息和控制器方法的形参创建映射关系
- @RequestHeader注解一共有三个属性:value、required、defaultValue,用法同@RequestParam
@CookieValue
用来获取cookie值
@CookieValue(value = "JSESSIONID") String jsessionid
- @CookieValue是将cookie数据和控制器方法的形参创建映射关系
- @CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam
@RequestBody
@RequestBody可以获取请求体信息,使用@RequestBody注解标识控制方法的形参,当前请求的请求体就会为当前注解所标识的形参赋值
<!--此时的请求方式必须为post,因为get请求没有请求体-->
<form th:action="@{/api/login}" method="post" >
账号:<input type="text" name="username" ><br>
密码:<input type="password" name="password" ><br>
<input type="submit" value="登录">
</form>
@RequestMapping(value = "/login")
public String login(@RequestBody String params) {
System.out.println(params);
return "success";
}
//输出结果:username=admin&password=123456
@RequestBody获取json格式的请求参数
在使用axios发送ajax请求之后,浏览器发送到服务器的请求参数有两种格式:
- name=value&name=value...,此时的参数可以通过request.getParameter()获取,对应的springmvc中,可以直接通过控制器方法的形参获取此类请求参数
- {key:value,key:value,...}此时是无法通过request.getParameter()获取,之前我们使用操作json的相关jar包gson或jackson处理此类请求参数,可以将其转换为指定的实体类对象或map集合。在springmvc中,直接使用@RequestBody注解标识控制器方法的形参即可将此类请求参数转换为java对象
使用@RequestBody获取json格式的请求参数的条件:
- 导入jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
- springmvc的配置文件中设置开启mvc的注解驱动
<mvc:annotation-driven/>
- 在控制器方法的形参位置,设置json格式的请求参数要转换成java类型(实体类或map)的参数,并使用@RequestBody注解标识
@ResponseBody
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为相应报文的响应体响应到浏览器
@RequestBody响应浏览器json数据,服务器处理ajax请求之后,大多数情况都需要向浏览器响应一个java对象,此时必须将java对象转化为json字符串才可以响应到浏览器,之前我们使用操作json数据的jar包gson或jackson将java对象转换为json字符串。在springmvc中,我们可以直接使用@ReponseBody注解实现此功能
条件:需要导入依赖并且开启驱动
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<mvc:annotation-driven/>
@RestController
@RestController注解是springmvc提供的一个复合注解,标识在控制器类上,就相当于为类添加上了@Controller注解,并且为其中的每一个方法添加了@ResponseBody注解
springmvc支持ant风格的路径
- ?:表示任意的单个字符
- *:表示任意的0个或多个字符
- ** :表示任意一层或多层目录
注意:在使用* *时,只能使用/**/xxx的方式
获取请求参数
ServletAPI
将HttpServletRequest作为控制器方法的形参,此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象
request.getParameter("参数名");
通过控制器方法的形参获取请求参数
在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在DispatcherServlet中就会将请求参数赋值给相应的形参。
注意:
- 若请求所传输的请求参数中有多个同名的请求参数,此时可以在控制器方法的形参中设置字符串数组或字符串类型的形参来接收此请求参数
- 若使用字符串数组类型的形参,此参数的数组中包含了每一个数据
- 若使用字符串类型的形参,此参数的值为每个数据中间使用逗号拼接的结果
通过pojo的形参获取请求参数
可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋值
解决获取请求参数的乱码问题
get方式:
- 方式一:修改tomcat的server.xml文件,添加URIEncoding="UTF-8"
- 方式二:先打散再重组,即使用String的getBytes("ISO-8859-1") 方法, 先转换为byte[],再创建一个String
post方式:
解决获取请求参数的乱码问题,可以使用springmvc提供的编码过滤器CharacterEncodingFilter,但是必须在web.xml中设置,并且这个编码过滤器一定要配置在其他过滤器之前,否则无效。
<!--配置UTF-8编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
域对象共享数据
使用ServletAPI向request域对象共享数据
@RequestMapping(value = "/share")
public String share(HttpServletRequest request) {
request.setAttribute("name", "zhangsan");
return "show";
}
使用ModelAndView向request域对象共享数据
@RequestMapping(value = "/share")
public ModelAndView share(ModelAndView modelAndView) {
modelAndView.addObject("name", "zhangsan");
modelAndView.setViewName("show");
return modelAndView;
}
使用Model向request域对象共享数据
@RequestMapping(value = "/share")
public String share(Model model) {
model.addAttribute("name", "zhangsan");
return "show";
}
使用Map向request域对象共享数据
@RequestMapping(value = "/share")
public String share(Map<String, Object> map) {
map.put("name", "zhangsan");
return "show";
}
使用ModelMap向域对象共享数据
@RequestMapping(value = "/share")
public String share(ModelMap modelMap) {
modelMap.addAttribute("name", "zhangsan");
return "show";
}
ModelAndView、Model、ModelMap、Map的关系
这四个类型的参数其实本质上都是BindingAwareModelMap类型的
向session域对象共享数据
@RequestMapping(value = "/share")
public String share(HttpSession session) {
session.setAttribute("name", "zhangsan");
return "show";
}
向application域对象共享数据
@RequestMapping(value = "/share")
public String share(HttpSession session) {
ServletContext servletContext = session.getServletContext();
servletContext.setAttribute("name", "zhangsan");
return "show";
}
视图
springmvc的视图是View接口,视图的作用就是渲染数据,将模型Model中的数据展示给用户,springmvc的视图的种类很多,默认有转发视图和重定向视图,当工程引入jstl的依赖,转发视图会自动转换为JstlView
若使用的技术为Thymeleaf,在springmvc的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView
ThmeleafView
当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被springmvc配置文件所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转。
转发视图
springmvc中默认的转发视图是InternalResourceView
springmvc中创建转发视图的情况: 当控制器方法中所设置的视图名为“forward:”为前缀时,创建InternalResourceView视图,此时的视图名称不会被springmvc配置文件中所配置的视图解析器解析,而是会将前缀“forward:”去掉,剩余部分作为最终路径通过转发的方式实现跳转
重定向视图
springmvc默认的重定向视图是RedirectView
当控制器的方法所设置的视图名称为“redirect:”为前缀时,创建RedirectView视图,此时的视图名称不会被springmvc配置文件中所配置的视图解析器解析,而是会将前缀“redirect:”去掉,剩余部分作为最终路径通过重定向的方式实现跳转
重定向视图解析时,会先将redirect:前缀去掉,然后会判断剩余部分是否以/开头,若是则会自动拼接上下文路径
转发与重定向
- 转发:一次请求;地址栏不变;可以携带参数.可以访问WEB-INF下的资源;不能跨域;
- 重定向:两次请求,地址栏改变;不可以携带参数;不可以访问WEB-INF下的资源;可以跨域
视图控制器view-controller
当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示
<!--配置视图控制器,path设置处理的请求地址,view-name设置请求地址所对应的视图名称;
当springmvc中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在springmvc的核心配置文件中设置开启
mvc注解驱动的标签 <mvc:annotation-driven/>
-->
<mvc:view-controller path="/index" view-name="index"/>
RESTful风格
是一种软件架构风格
Rest是面向资源的,每个资源都有一个唯一的资源定位符(URI),每个URI代表一种资源,所以URI中不能有动词,只能有名词,而且所用的名词往往与数据库的表名相对应.一般来说,数据库中的表都是同种记录的集合,所以URI中的名词也应该使用复数
请求方式:
| 请求方式 | 含义 |
|---|---|
| GET | 从服务器取出资源 |
| POST | 在服务器新建一个资源 |
| DELET | 从服务器删除资源 |
| PUT | 在服务器更新资源(更新完整资源) |
| PATCH | 在服务器更新资源,更新个别属性 |
HiddenHttpMethodFilter
由于浏览器只支持发送get/post方式的请求,那么该如何发送put和delete请求呢?
springmvc提供了HiddenHttpMethodFilter帮助我们将post请求转换为delete或put请求HiddenHttpMethodFilter处理put和delete请求的条件:
- 当前请求方式必须是post
- 当前请求必须传输请求参数_method
满足以上条件,HiddenHttpMethodFilter过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式。在web.xml中注册HiddenHttpMethodFilter
<input type="hidden" name="_method" value="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>
注意:目前为止springmvc提供了两个过滤器,CharacterEncodingFilter和HiddenHttpMethodFilter,在web.xml中注册时,必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter。原因是:
- 在CharacterEncodingFilter中是通过request.setCharacterEncoding(encoding)方法设置字符集的
- 在request.setCharacterEncoding(encoding)方法要求前面不能有任何获取请求参数的操作
- 而HiddenHttpMethodFilter恰恰有一个获取请求方式的操作:
- String paramValue=request.getParameter(this.methodParam)
处理静态资源
建议静态资源放在webapp目录下,可以直接访问
如果静态资源放在WEB-INF下面,解决静态资源404问题
<!--开启注解驱动-->
<mvc:annotation-driven/>
<!--静态文件映射,mapping映射路径,location文件存放的真实路径-->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
<!--默认的servlet,DispatcherServlet处理不了的请求交给defaultServlet来处理-->
<mvc:default-servlet-handler/>
文件的上传下载
文件下载
ResponseEntity用于控制器方法返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文,使用ResponseEntity实现文件的下载功能
@RequestMapping(value = "/down")
public ResponseEntity down(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/8.jpg");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[]bytes = new byte[is.available()];
//将流读取到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String,String> headers = new HttpHeaders();
//设置要下载的方式以及下载文件的名字
headers.add("Content-Disposition","attachment;filename=8.jpg");
//设置响应状态码
HttpStatus ok = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,headers,ok);
//关闭输入流
is.close();
return responseEntity;
}
文件上传
文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data",springmvc中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关的信息
上传步骤:
- 添加依赖
<!--上传文件依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 在springmvc中的配置文件中添加配置:
<!--配置上传文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置字符集-->
<property name="defaultEncoding" value="UTF-8"/>
<!--上传文件大小设置最大为50M 单位为byte-->
<property name="maxUploadSize" value="52428800"/>
<!--设置内存大小 40k-->
<property name="maxInMemorySize" value="4096"/>
</bean>
- 控制器方法
@RequestMapping("/up")
@ResponseBody
public String up(MultipartFile upFile, HttpSession session) throws IOException {
ServletContext servletContext = session.getServletContext();
//获取文件夹的真实路径
String realPath = servletContext.getRealPath("/static/img");
String suffix = "";
if (!upFile.isEmpty() && upFile.getSize() > 0) {
String filename = upFile.getOriginalFilename();
//截取文件名称
suffix = filename.substring(filename.lastIndexOf("."));
} else {
return "error";
}
File file = new File("realPath");
if (!file.exists()) {
file.mkdirs();
}
String fileName = UUID.randomUUID().toString();
String finalFilePath = realPath + File.separator + fileName + suffix;
upFile.transferTo(new File(finalFilePath));
return "success";
}
拦截器
- springmvc的拦截器用于拦截控制器方法的执行
- springmvc的拦截器需要实现HandlerInterceptor
- springmvc的拦截器必须在springmvc的配置文件中进行配置:
<mvc:interceptors>
<!--第一种方式-->
<!--<bean class="com.zhanggang.interceptor.AuthInterceptor"/>-->
<!--第二种方式,前提是AuthInterceptor类上面要交给spring容器进行管理-->
<!--<ref bean="authInterceptor"/>-->
<!--第三种方式,mvc:mapping可以设置需要拦截的请求,mvc:exclude-mapping设置需要排除的请求-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/api/form"/>
<!--<bean class="com.zhanggang.interceptor.AuthInterceptor"/>-->
<ref bean="authInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
springmvc的拦截器有三个抽象方法:
- preHandle:控制器方法执行前执行,其boolean类型的返回值表示是否拦截或放行,返回值为true为放行,即调用控制器方法;放回false表示拦截,即不调用控制方法
- postHandle:控制器方法执行后执行
- afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行
多个拦截器的执行顺序:
- 若每个拦截器的preHandle()都返回true,此时多个拦截器的执行顺序和拦截器在springmvc的配置文件的配置顺序有关,preHandle()会按照配置的顺序执行,而postHandle()和afterCompletion()会按照配置的反序执行
- 若某个拦截器的preHandle()返回了false,preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterCompletion()会执行
异常处理器
- springmvc提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver
- HandlerExceptionResolver接口的实现类有:DefaultExceptionResolver和SimpleMappingExceptionResolver
- springmvc提供了自定义的异常处理器SimpleMappingExceptionResolver
基于springmvc配置文件配置:
<!--配置异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--键表示处理器方法执行过程中出现的异常;值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面-->
<prop key="java.lang.ArithmeticException">exception/500</prop>
</props>
</property>
<!--这句话可以将异常信息保存到request域中,键为value值,值为异常名称.前端用thymeleaf接收即可(th:text="${exception}")-->
<property name="exceptionAttribute" value="exception"/>
</bean>
基于注解配置:
package com.zhanggang.exception;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* @author : zhanggang
* @version : v1.0
* @description TODO 统一异常处理器
* @date : 2023/5/24 16:55
*/
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
public String serverException(Exception ex, Model model) {
model.addAttribute("exception", ex);
return "exception/500";
}
}
页面取出请求域中的共享信息:
<p th:text="${exception}"></p>
配置error-page
<!--配置error-page-->
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/exception/404.html</location>
</error-page>