SpringMVC
一、概述
(一)MVC
组成:
Model:数据模型,用于封装数据
View:页面视图,用于展示数据
Controller:处理用户交互的调度器,用于根据用户需求处理程序逻辑
(二)SpringMVC
基于Java实现MVC模型的轻量级web框架
二、RequestMapping注解
(一)功能
将请求与处理请求的控制器方法关联
(二)位置
标识在类上:设置映射请求路径的初始信息,就是多加一层访问路径
标识在方法上:设置映射请求路径的具体信息
注意: 多个控制器中的请求地址一样,则会报错,利用表示在类上的RequestMapping注解可以解决该问题
(三)value属性
**作用:**根据请求地址匹配请求映射
**取值:**字符串类型的数组(满足数组中的一个即可,用,连接)
(四)method属性
作用: 通过请求方式匹配映射请求
取值: RequestMethod类型的数组(满足数组中的一个即可,用,连接)
注意:
1. get请求:将内容拼接在请求中
post请求:将内容放在请求体
2. 若value属性匹配,method属性不匹配,报错:405
3. springMVC提供了@RequestMapping的派生注解:
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping
4. 常用的方式为:get、post、put、delete
(五)params属性
作用: 通过请求参数匹配请求映射,必须同时满足
类型:
- param
- !param
- param=value
- param!=value
(六)headers属性(了解)
作用: 通过请求头信息匹配映射
(七)ant风格路径
- ?:表示任意单个字符
- :表示任意的0个或多个字符
- **:表示任意的一层或多层目录
(八)rest风格路径(重要)
原始: /deleteUser?id=1
rest: /deleteUser/1
将参数以请求路径的方式传输到服务器
三、获取请求参数
(一)通过ServletAPI获取
将HttpServletRequest 作为控制器方法的形参,HttpServletRequest 类型的参数封装了当前请求的请求报文对象
@RequestMapping("/testParamServletAPI")
public String testParamServletAPI(HttpServletRequest request){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+"--"+password);
return "success";
}
(二)通过控制器方法的形参获取
在控制器方法的形参位置设置与请求参数同名的形参,浏览器发送请求时,在DispatcherServlet中会将请求参数赋值给响应的形参
@RequestMapping("/testParam")
public String testParam(String username, String password){
System.out.println(username+"--"+password);
return "success";
}
注意:
1. 若请求参数中出现多个同名的参数,可以在控制器方法的形参位置设置字符串类型或字符串数组接收
2. 若设置为字符串类型的形参,最终结果为请求参数的每一个值,值与值之间用逗号连接
3. 若设置为字符串数组类型的形参,数组包含了每一个数据
(三)@RequestParam
将请求参数与控制方法的形参创建映射关系
属性:
value属性:指定为形参赋值的请求参数的参数名
required属性:设置是否必须传输此请求参数,默认值为true
defaultValue属性:当value所指定的请求参数没有传输或传输为“”时,使用默认值为形参赋值
(四)@RequestHeader
将请求头信息和控制方法的形参创建映射关系
属性:
value属性
required属性
defaultValue属性
(五)@CookieValue
将cookie数据和控制方法的形参创建映射关系
属性:
value属性
required属性
defaultValue属性
(六)通过POJO获取
在控制器方法的形参位置设置实体类型,若浏览器传输的请求参数的参数名与实体类中的属性名一致,请求参数会为此属性赋值
(七)解决请求参数乱码
使用SpringMVC提供的编码过滤器CharacterEncodingFilter,须在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>
四、域对象共享数据
(一)使用ServletAPI向request域对象共享数据(不推荐)
@RequestMapping("/testRequestByServletAPI")
public String testRequestByServletAPI(HttpServletRequest request){
request.setAttribute("testRequestScope","hello");
return "success";
}
(二)使用ModelAndView向request域对象共享数据(建议)
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mav = new ModelAndView();
//处理模型数据,即向请求域request共享数据
mav.addObject("testRequestScope","hello model and view");
//设置视图名称
mav.setViewName("success");
return mav;
}
(三)使用Model向request域对象共享数据
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("testRequestScope","hello model");
return "success";
}
(四)使用map向request域对象共享数据
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
map.put("testRequestScope","hello map");
return "success";
}
(五)使用ModelMap向request域对象共享数据
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("testRequestScope","hello modelMap");
return "success";
}
(六)Model、ModelMap、map关系
本质上都是BindingAwareModelMap类型
(七)向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
视图名称拼接视图前缀和视图后缀得到最终路径,通过转发的方式实现跳转
(二)转发视图(InternalResourceView)
控制器方法中设置的视图名以**forward:**为前缀时,创建InternalResourceView视图,此时视图名不会被springMVC配置文件中所配置的视图解析器解析,而是将前缀去掉,剩余部分作为最终路径,通过转发的方式实现跳转
@RequestMapping("/testForwardView")
public String testForwardView(){
return "forward:/testThymeleafView";
}
(三)重定向视图(RedirectView)
控制器方法中设置的视图名以**redirect:**为前缀时,创建RedirectView视图,此时视图名不会被springMVC配置文件中所配置的视图解析器解析,而是将前缀去掉,剩余部分作为最终路径,通过重定向的方式实现跳转
@RequestMapping("/testRedirectView")
public String testRedirectView(){
return "redirect:/testThymeleafView";
}
注意:
转发 | 重定向 |
---|---|
浏览器发送了一次请求 | 浏览器发送了两次请求 |
request使用的是同一个 | request使用的不是同一个 |
不可以跨域 | 可以跨域 |
地址栏与页面的请求不同 | 地址栏和页面的请求相同 |
(四)视图控制器view-controller
用于实现页面跳转
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
path属性:设置处理的请求地址
view-name属性:设置请求地址所对应的视图名称
当springMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,需要开启mvc注解驱动标签
<mvc:annotation-driven></mvc:annotation-driven>
六、RESTFul
(一)实现
操作 | 传统方式 | REST方式 | 作用 |
---|---|---|---|
查询 | getUserBy?id=1 | user/1 ->get请求 | 获取资源 |
保存 | saveUser | user->post请求 | 新建资源 |
删除 | deleteUser?id1 | user/1->delete请求 | 删除资源 |
更新 | updateUser | user->put请求 | 更新资源 |
(二)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>
七、HttpMessageConverter
报文信息转换器:将请求报文转换为java对象,或将java对象转换为响应报文
(一)@RequestBody
作用: 获取请求体,需在控制器方法上设置形参,并用@RequestBody进行标识。当前请求的请求体就会为当前标注的形参赋值
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody){
System.out.println(requestBody);
return "success";
}
(二)RequestEntity
**作用:**封装请求保温,在控制器方法的形参中设置该类型的参数,当前的请求报文就会从整体上服赋给形参,可借助getHealders()获取请求头信息
public String testRequestEntity(RequestEntity<String> requestEntity){
System.out.println(requestEntity.getHeaders());
System.out.println(requestEntity.getBody());
return "success";
}
(三)@ResponseBody
@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody(){
return "success";
}
(四)@ResponseBody处理json
需要导入jackson依赖
@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser(){
return new User("zhangsan","123","5006@qq.com");
}
将java对象直接作为控制器方法的返回值返回,会自动转换为json格式的字符串
(五)处理ajax
(六)@RestController
复合注解----@ResponseBody与@Controller
(七) ResponseEnity
用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文
八、文件上传与下载
(一)文件上传
(二)文件下载
九、拦截器
(一)拦截器的配置
请求 ->过滤器->前端控制器->控制器
拦截器负责在控制器方法的前后进行一系列操作
配置步骤:
1.实现HandlerInterceptor接口
public class FirstInterceptor implements HandlerInterceptor {...}
2.文件配置
<bean class="com.ht.interceptors.FirstInterceptor"></bean>
<ref bean="firstInterceptor"></ref>
上述两种配置方式对前端控制器所处理的所有请求进行拦截
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/testRequestEntity"/>
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
该配置方式通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过mvc:exclude-mapping设置需要排除的请求
(二)方法
preHandle: 控制器方法执行之前执行,boolean返回值表示是否拦截或放行,true为放行,false为拦截,不调用控制器方法
postHandle: 控制器方法执行之后执行
afterCompletion: 处理完视图和模型数据,渲染视图完毕后执行
(三)多个拦截器的执行顺序
preHandle根据配置的顺序执行
postHandle与afterCompletion根据配置的顺序
十、异常处理器
(一)基于配置的异常处理
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<property name="exceptionAttribute" value="ex">
</property>
</bean>
(二)基于注解的异常处理
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
public String testException(Exception ex, Model model){
model.addAttribute("ex",ex);
System.out.println(ex);
return "error";
}
}