目录
配置springMVC
1.创建maven工程
- 添加web模块
- 打包方式:war
- 引入依赖<dependencies>
配置pom.xml
<packaging>war</packaging>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</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>
<!--文件上传组件-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
2.配置web.xml的两个过滤器一个控制器
<!--配置编码过滤器-->
<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>forceResponseEncoding</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的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>
<!--配置springMVC的前端控制器DispatcherServlet-->
<servlet>
<servlet-name>DispatcherServlet</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>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.resources文件夹下创建springMVC.xml文件
4.创建springMVC的配置文件
<!--开启扫描-->
<context:component-scan base-package="com.gr"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!--
配置默认的servlet处理静态资源
当前工程的web.xml配置的前端控制器DispatcherServlet的url-pattern是/
tomcat的wbe.xml配置的DefaultServlet的url-pattern是/
此时,浏览器发送的请求会优先被DispatcherServlet进行处理,但是DispatcherServlet无法处理静态资源
若配置了<mvc:default-servlet-handler/>,此时浏览器发送的所有请求都会被DispatcherServlet处理
若配置了<mvc:default-servlet-handler/>和<mvc:annotation-driven/>
浏览器发送的请求会先被DispatcherServlet处理,无法处理再交给DefaultServlet处理
-->
<mvc:default-servlet-handler/>
<!--开启mvc的注解驱动-->
<mvc:annotation-driven/>
<!--配置视图控制器-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
@RequestMapping注解
标记的位置:
@RequestMapping标识一个类:设置映射请求的请求路径的初始信息,相当于添加一层路径
@RequestMapping标识一个方法:设置映射请求请求路径的具体信息
例:
@Controller
@RequestMapping("/test")
public class RequestMappingController {
//此时请求映射所映射的请求的请求路径为:/test/testRequestMapping
@RequestMapping("/testRequestMapping")
public String testRequestMapping(){}
}
属性:
value:通过请求的请求地址匹配请求映射(数组多选一)
method:通过请求的请求方式(get或post)匹配请求映射(数组多选一)
处理指定请求方式的控制器方法,SpringMVC中提供了@RequestMapping的派生注解:
处理get请求的映射-->@GetMapping
处理post请求的映射-->@PostMapping
处理put请求的映射-->@PutMapping
处理delete请求的映射-->@DeleteMapping
params:通过请求的请求参数匹配请求映射,若不满足报400(多满足)
headers:通过请求的请求头信息必须满足headers属性的设置,若不满足报404(多满足)
常用设置:
@RequestMapping(
value = {"/testRequestMapping", "/test"},
method = {RequestMethod.GET, RequestMethod.POST},
//params = {"username","password!=123456"}
)
SpringMVC支持ant风格的路径
?:表示任意的单个字符
*:表示任意的0个或多个字符
**:表示任意层数的任意目录
注意:在使用**时,只能使用/**/xxx的方式
例如:
//<a th:href="@{/aaa/test/ant}"></a>
@RequestMapping("a*/**/a?t")
public String testAnt(){
return "success";
}
SpringMVC支持路径中的占位符
//<a th:href="@{/testRest/1/admin}"></a>
@RequestMapping("/testRest/{id}/{username}")
public String testRest(@PathVariable("id") String id, @PathVariable("username")String username){
System.out.println("id:"+id+",username:"+username);
return "success";
}
//最终输出的内容为-->id:1,username:admin
SpringMVC获取请求参数
通过控制器方法的形参获取请求参数
在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在 DispatcherServlet中就会将请求参数赋值给相应的形参
//<a th:href="@{/testParam(username='admin',password='123456')}"></a>
@RequestMapping("/testParam")
public String testParam(String username, String password){
System.out.println("username:"+username+",password:"+password);
return "success";
}
若前端请求参数与控制器方法名不同,则需要使用以下注解:
@RequestParam 是将请求参数和控制器方法的形参绑定
@RequestHeader 是将请求头信息和控制器方法的形参绑定
@CookieValue 是将cookie数据和控制器方法的形参绑定
以上三个注解都具有以下三个属性:
value:设置和形参绑定的请求参数的名字
required:设置是否必须传输value所对应的请求参数(参数是否可以为null),默认值为true 若设置为true时,则当前请求必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置 defaultValue 属性,则页面报错400:Required String parameter 'xxx' is not present;若设置为 false,则当前请求不是必须传输value所指定的请求参数,若没有传输,则注解所标识的形参的值为 null
defaultValue:设置默认值;不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值 为""时,则使用默认值为形参赋值
//<a th:href="@{/testParam(userName='admin',password='123456')}"></a>
@RequestMapping("/testParam")
public String testParam(
@RequestParam(value = "userName",required = false,defaultValue = "hehe")
String username, String password
@RequestHeader("referer") String referer,
@CookieValue("JSESSIONID") String jsessionId){
System.out.println("username:"+username+",password:"+password);
return "success";
}
通过POJO获取请求参数
创建User类(属性名要与请求参数名字一致)
html文件内:
<form th:action="@{/testpojo}" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
性别:<input type="radio" name="sex" value="男">男
<input type="radio" name="sex" value="女">女<br>
年龄:<input type="text" name="age"><br>
邮箱:<input type="text" name="email"><br>
<input type="submit" value="使用实体类接受请求参数">
</form>
@RequestMapping("/testpojo")
public String testPOJO(User user){
System.out.println(user);
return "success";
}
域对象共享数据
向request域对象共享数据
ModelAndView
Model:向请求域中共享数据
view:设置逻辑视图实现页面跳转
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mav = new ModelAndView();
//处理模型数据,即向请求域request共享数据
mav.addObject("testRequestScope","hello,ModelAndView");
//设置视图名称
mav.setViewName("success");
return mav;
}
Model
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("testRequestScope","hello,Model");
return "success";
}
map
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
map.put("testRequestScope","hello,Map");
return "success";
}
ModelMap
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("testRequestScope","hello,ModelMap");
return "success";
}
向session域共享数据
@RequestMapping("/testSession")
public String testSession(HttpSession session){
session.setAttribute("testSessionScope", "hello,session");
return "success";
}
向application域共享数据
@RequestMapping("/testApplication")
public String testApplication(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("testApplicationScope", "hello,application");
return "success";
}
SpringMVC的视图
无前缀:ThymeleafView
以"forward:"为前缀: InternalResourceView 转发视图
以"redirect:"为前缀: RedirectView 重定向视图
例如:
@RequestMapping("/testForward")
public String testForward(){
return "forward:/testHello";
}
视图控制器view-controller
<!--path:设置处理的请求地址 view-name:设置请求地址所对应的视图名称-->
<mvc:view-controller path="/testView" view-name="success"></mvc:view-controller>
当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需 要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签:
<mvc:annotation-driven />
RESTful
根据请求方式不同分为各种功能:
GET 用来获取资源
POST 用来新建资源
PUT 用来更新资源
DELETE 用来删除资源
发送get和post请求:
查询所有用户信息:
//<a th:href="@{/user}">查询所有的用户信息</a><br>
@GetMapping("/user")
public String getAllUser(){
System.out.println("查询所有的用户信息 -->/user-->get");
return "success";
}
跟据id查询用户信息:
//<a th:href="@{/user/1}">查询id为1的用户信息</a><br>
@GetMapping("/user/{id}")
public String getUserById(@PathVariable("id") Integer id){
System.out.println("根据id查询用户信息 -->/user/"+id+"-->get");
return "success";
}
添加用户信息:
/*
<form th:action="@{/user}" method="post">
<input type="submit" value="添加用户信息">
</form>
*/
@PostMapping("/user")
public String insertUser(){
System.out.println("添加用户信息-->/user-->post");
return "success";
}
发送put和delete请求的方式
在web.xml中配置HiddenHttpMethodFilter过滤器:
<!--配置处理请求方式put和delete的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>
当前请求的请求方式必须为post
当前请求必须传输请求参数_method
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="修改用户信息">
</form>
修改用户信息
@PutMapping("/user")
public String updateUser(){
System.out.println("修改用户信息-->/user-->put");
return "success";
}
删除用户信息
/*
<form th:action="@{/user/1}" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="删除用户信息">
</form>
*/
@DeleteMapping("/user/{id}")
public String deleteUser(@PathVariable("id") Integer id){
System.out.println("删除用户信息-->/user/"+id+"-->delete");
return "success";
}
RESTful 实例
查询: 显示所有员工
<table>
<tr>
<th colspan="5">employee_list</th>
</tr>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>options(<a th:href="@{/to/add}">add</a> )</th>
</tr>
<tr th:each="employee : ${allEmployee}">
<td th:text="${employee.id}"></td>
<td th:text="${employee.email}"></td>
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.gender}"></td>
<td>
<a @click="deleteEmployee()" th:href="@{|/employee/${employee.id}|}">delete</a>
<a th:href="@{|/employee/${employee.id}|}">update</a>
</td>
</tr>
</table>
@GetMapping("/employee")
public String getAllEmployee(Model model){
//获取所有员工信息
Collection<Employee> allEmployee = employeeDao.getAll();
//将所有的员工信息在请求域中共享
model.addAttribute("allEmployee",allEmployee);
return "employee_list";
}
添加: 添加员工界面
<body>
<form th:action="@{/employee}" method="post">
<table>
<tr>
<th colspan="2">add employee</th>
</tr>
<tr>
<td>lastName</td>
<td>
<input type="text" name="lastName">
</td>
</tr>
<tr>
<td>email</td>
<td>
<input type="text" name="email">
</td>
</tr>
<tr>
<td>gender</td>
<td>
<input type="radio" name="gender" value="1">male
<input type="radio" name="gender" value="0">female
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="add">
</td>
</tr>
</table>
</form>
</body>
@PostMapping("/employee")
public String insertEmployee(Employee employee){
//保存员工信息
employeeDao.save(employee);
//重定向到列表功能:/employee
return "redirect:/employee";
}
修改: 获取要修改对象信息,放入请求域中
@GetMapping("/employee/{id}")
public String getEmployeeById(@PathVariable("id") Integer id,Model model){
Employee employee = employeeDao.get(id);
model.addAttribute("employee",employee);
return "employee_update";
}
修改界面:
<body>
<form th:action="@{/employee}" method="post">
<input type="hidden" name="_method" value="put">
<input type="hidden" name="id" th:value="${employee.id}">
<table>
<tr>
<th colspan="2">update employee</th>
</tr>
<tr>
<td>lastName</td>
<td>
<input type="text" name="lastName" th:value="${employee.lastName}">
</td>
</tr>
<tr>
<td>email</td>
<td>
<input type="text" name="email" th:value="${employee.email}">
</td>
</tr>
<tr>
<td>gender</td>
<td>
<input type="radio" name="gender" value="1" th:field="${employee.gender}">male
<input type="radio" name="gender" value="0" th:field="${employee.gender}">female
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="update">
</td>
</tr>
</table>
</form>
</body>
@PutMapping("/employee")
public String updateEmployee(Employee employee){
employeeDao.save(employee);
return "redirect:/employee";
}
删除: 使用vue将超链接get请求与form表单的delete请求绑定
<body>
<div id="app">
<table>
<tr>
<th colspan="5">employee_list</th>
</tr>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>options(<a th:href="@{/to/add}">add</a> )</th>
</tr>
<tr th:each="employee : ${allEmployee}">
<td th:text="${employee.id}"></td>
<td th:text="${employee.email}"></td>
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.gender}"></td>
<td>
<a @click="deleteEmployee()" th:href="@{|/employee/${employee.id}|}">delete</a>
<a th:href="@{|/employee/${employee.id}|}">update</a>
</td>
</tr>
</table>
<form method="post">
<input type="hidden" name="_method" value="delete">
</form>
</div>
<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el: "#app",
methods: {
deleteEmployee() {
//获取form表单
var form = document.getElementsByTagName("form")[0];
//将超链接的href属性值赋值给form表单的action属性
//event.target表示当前触发事件的标签
form.action = event.target.href;
//表单提交
form.submit();
//阻止超链接的默认行为
event.preventDefault();
}
}
});
</script>
</body>
@DeleteMapping("/employee/{id}")
public String deleteEmployee(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/employee";
}
SpringMVC处理ajax请求
@RequestBody
@RequestBody可以获取请求体信息,使用@RequestBody注解标识控制器方法的形参,当前请求的请 求体就会为当前注解所标识的形参赋值
<!--此时必须使用post请求方式,因为get请求没有请求体-->
<form th:action="@{/test/RequestBody}" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
</form>
@RequestMapping("/test/RequestBody")
public String testRequestBody(@RequestBody String requestBody){
System.out.println("requestBody:"+requestBody);
return "success";
}
//输出结果:requestBody:username=admin&password=123456
@RequestBody获取json格式的请求参数
在使用了axios发送ajax请求之后,浏览器发送到服务器的请求参数有两种格式:
1、name=value&name=value...,此时的请求参数可以通过request.getParameter()获取,对应 SpringMVC中,可以直接通过控制器方法的形参获取此类请求参数
2、{key:value,key:value,...},此时无法通过request.getParameter()获取,之前我们使用操作 json的相关jar包gson或jackson处理此类请求参数,可以将其转换为指定的实体类对象或map集合。在SpringMVC中,直接使用@RequestBody注解标识控制器方法的形参即可将此类请求参数转换为java对象
使用@RequestBody获取json格式的请求参数的条件:
1、导入jackson的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
2、SpringMVC的配置文件中设置开启mvc的注解驱动
<!--开启mvc的注解驱动-->
<mvc:annotation-driven />
3、在控制器方法的形参位置,设置json格式的请求参数要转换成的java类型(实体类或map)的参 数,并使用@RequestBody注解标识
<input type="button" value="测试@RequestBody获取json格式的请求参数" @click="testRequestBody()"><br>
<script type="text/javascript" th:src="@{/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/js/axios.min.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el:"#app",
methods:{
testRequestBody(){
axios.post(
"/SpringMVC/test/RequestBody/json",
{username:"admin",password:"123456"}
).then(response=>{
console.log(response.data);
});
}
}
});
</script>
//将json格式的数据转换为map集合
@RequestMapping("/test/RequestBody/json")
public void testRequestBody(@RequestBody Map<String, Object> map,HttpServletResponse response) throws IOException {
System.out.println(map);
//{username=admin, password=123456}
response.getWriter().print("hello,axios");
}
//将json格式的数据转换为实体类对象
@RequestMapping("/test/RequestBody/json")
public void testRequestBody(@RequestBody User user, HttpServletResponse response) throws IOException {
System.out.println(user);
//User{id=null, username='admin', password='123456', age=null,gender='null'}
response.getWriter().print("hello,axios");
}
@ResponseBody
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到 浏览器
@RequestMapping("/testResponseBody")
public String testResponseBody(){
//此时会跳转到逻辑视图success所对应的页面
return "success";
}
@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody(){
//此时响应浏览器数据success
return "success";
}
@ResponseBody响应浏览器json数据
服务器处理ajax请求之后,大多数情况都需要向浏览器响应一个java对象,此时必须将java对象转换为 json字符串才可以响应到浏览器,之前我们使用操作json数据的jar包gson或jackson将java对象转换为 json字符串。在SpringMVC中,我们可以直接使用@ResponseBody注解实现此功能
@ResponseBody响应浏览器json数据的条件:
1、导入jackson的依赖
2、SpringMVC的配置文件中设置开启mvc的注解驱动
3、使用@ResponseBody注解标识控制器方法,在方法中,将需要转换为json字符串并响应到浏览器 的java对象作为控制器方法的返回值,此时SpringMVC就可以将此对象直接转换为json字符串并响应到 浏览器
<input type="button" value="测试@ResponseBody响应浏览器json格式的数据"@click="testResponseBody()"><br>
<script type="text/javascript" th:src="@{/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/js/axios.min.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el:"#app",
methods:{
testResponseBody(){
axios.post("/SpringMVC/test/ResponseBody/json").then(response=>{
console.log(response.data);
});
}
}
});
</script>
//响应浏览器list集合
@RequestMapping("/test/ResponseBody/json")
@ResponseBody
public List<User> testResponseBody(){
User user1 = new User(1001,"admin1","123456",23,"男");
User user2 = new User(1002,"admin2","123456",23,"男");
User user3 = new User(1003,"admin3","123456",23,"男");
List<User> list = Arrays.asList(user1, user2, user3);
return list;
}
//响应浏览器map集合
@RequestMapping("/test/ResponseBody/json")
@ResponseBody
public Map<String, Object> testResponseBody(){
User user1 = new User(1001,"admin1","123456",23,"男");
User user2 = new User(1002,"admin2","123456",23,"男");
User user3 = new User(1003,"admin3","123456",23,"男");
Map<String, Object> map = new HashMap<>();
map.put("1001", user1);
map.put("1002", user2);
map.put("1003", user3);
return map;
}
//响应浏览器实体类对象
@RequestMapping("/test/ResponseBody/json")
@ResponseBody
public User testResponseBody(){
return user;
}
@RestController注解
@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了 @Controller注解,并且为其中的每个方法添加了@ResponseBody注解
文件上传和下载
文件下载
@Controller
public class FileUpAndDownController {
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.png");
//创建输入流
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=1.png");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
文件上传
文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"
SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息
<form th:action="@{/test/up}" method="post" enctype="multipart/form-data">
头像:<input type="file" name="photo"><br>
<input type="submit" value="上传">
</form>
上传步骤:
1.添加依赖:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2.在SpringMVC的配置文件中添加配置:
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
3.控制器方法:
@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//getOriginalFilename():获取上传文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题
//获取上传的文件的后缀名
String hzName = fileName.substring(fileName.lastIndexOf("."));
//UUID中”-”替换为””,拼接为新的文件名
fileName = UUID.randomUUID().toString().replaceAll("-","") + hzName;
//通过ServletContext获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
//判断photoPath所对应的路径是否存在
if (!file.exists()) {
//若不存在则创建目录
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//实现上传功能
photo.transferTo(new File(finalPath));
return "success";
}
拦截器
以下两种配置方式都是对DispatcherServlet所处理的所有的请求进行拦截
<mvc:interceptors>
<bean class="com.gr.controller.FirstInterceptor"></bean>
</mvc:interceptors>
引用一个类作为拦截器,可配置也在类名上加@Component注解.以配置为例:
<bean id="firstInterceptor" class="com.gr.controller.FirstInterceptor"></bean>
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
以下配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过
mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求
<mvc:interceptors>
<mvc:interceptor>
<!--配置需要拦截的请求的请求路径,/**表示所有请求-->
<mvc:mapping path="/**"/>
<!--配置需要排除拦截的请求的请求路径-->
<mvc:exclude-mapping path="/"/>
<!--配置拦截器-->
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>
SpringMVC中的拦截器需要实现HandlerInterceptor,实现拦截器的三个抽象方法:
preHandle:控制器方法执行之前执行,其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
postHandle:控制器方法执行之后执行
afterComplation:处理完视图和模型数据,渲染视图完毕之后执行
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor-->preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor-->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor-->afterCompletion");
}
}
多个拦截器的执行顺序:
①若每个拦截器的preHandle()都返回true 此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关: preHandle()会按照配置的顺序执行,而postHandle()和afterCompletion()会按照配置的反序执行
②若某个拦截器的preHandle()返回了false preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false 的拦截器之前的拦截器的afterCompletion()会执行
异常处理器配置(基于注解):
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
public String testException(Exception ex, Model model){
model.addAttribute("ex",ex);
return "error";
}
}
前端显示异常信息:
<p th:text="${ex}"></p>
注解配置SpringMVC
1.配置资源
2.注解配置SpringMVC
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
//设置一个配置类,代替Spring的配置文件
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
//设置一个配置类,代替SpringMVC的配置文件
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
//设置SpringMVC的前端控制器DispatcherServlet的url-pattern
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
//设置当前的过滤器
protected Filter[] getServletFilters() {
//创建编码过滤器
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceResponseEncoding(true);
//创建处理请求方式的过滤器
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
}
}
3.创建SpringConfig配置类,代替spring的配置文件
@Configuration
public class SpringConfig {
//ssm整合之后,spring的配置信息写在此类中
}
4.创建WebConfig配置类,代替SpringMVC的配置文件
@Configuration
//扫描组件
@ComponentScan("com.gr.controller")
//开启mvc的注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//默认的Servlet处理静态资源
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//配置视图控制器
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
//文件上传解析器
@Bean
//@Bean注解可以将表示的方法的返回值作为Bean进行管理,Bean的id为方法的方法名
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
//拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
FistInterceptor fistInterceptor = new FistInterceptor();
registry.addInterceptor(fistInterceptor).addPathPatterns("/**").excludePathPatterns("/");
}
//配置异常解析器
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties prop = new Properties();
prop.setProperty("java.lang.ArithmeticException", "error");
exceptionResolver.setExceptionMappings(prop);
exceptionResolver.setExceptionAttribute("ex");
resolvers.add(exceptionResolver);
}
//配置生成模板解析器
@Bean
public ITemplateResolver templateResolver() {
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
//生成模板引擎并为模板引擎注入模板解析器
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
return templateEngine;
}
//生成视图解析器并未解析器注入模板引擎
@Bean
public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setCharacterEncoding("UTF-8");
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
}
SpringMvc完整执行流程
浏览器发送请求,被DispatcherServlet处理.
DispatcherServlet处理请求时要找到请求对应的请求映射,这时就有两种情况:存在或者不存在
不存在的话再去找有没有配置默认的servlet,如果也没有则直接报404错误
有配置了的话则直接交给默认的servlet继续来处理.
默认的servlet也找不到的话页面也是报404错误
找到了这个请求映射的话就通过HandlerMapping去匹配当前的控制器方法
匹配到之后再由HandlerAdapter调用执行控制器方法
在执行控制器方法之前会按照配置的拦截器顺序去执行拦截器的preHandler方法
接着再调用控制器方法
控制器方法执行之后调用拦截器的postHandle方法
postHandle方法执行之后就要来处理ModelAndView,来渲染视图
渲染视图之后执行拦截器的afterCompletion方法
最终将结果相应到浏览器