1 异步调用
1.1 发送异步请求
/**
* 注意:
* '{name:"张三",age:23}' json字符串
* {name:"张三",age:23} json对象
*/
$.ajax({
type:"POST",
url:"ajaxController",
data:'{name:"张三",age:23}',
contentType:"application/json;charset=utf-8" //参数是json字符串(如果是json对象时,不需要指定该参数)
success:function(result){
alert(result);
}
});
1.2 接受异步请求参数
//接收整体参数
@RequestMapping("/ajaxController")
public String ajaxController(@RequestBody String message){
System.out.println(message);
return "page.jsp";
}
//如果,前台发送过来的参数是"json字符串",则需要在后台加上@RequestBody来接收并解析参数
//在服务器集群情况下,服务器之间只能收发字符串数据,所以在那种情况下,使用比较多
@RequestMapping("/ajaxPojoToController")
public String ajaxPojoToController(@RequestBody User user){
System.out.println("controller pojo :"+user);
return "page.jsp";
}
@RequestMapping("/ajaxListToController")
public String ajaxListToController(@RequestBody List<User> userList){
System.out.println("controller list :"+userList);
return "page.jsp";
}
注意:
1 @RequestBody注解使用时,要求前台的请求必须是POST请求
2 异步请求所发送的数据必须是json字符串,才能使用@RequestBody注解解析
2 跨域访问
2.1 跨域访问介绍
- 当通过域名A下的操作访问域名B下的资源时,称为跨域访问
- 跨域访问时,会出现无法访问的现象
2.2 跨域访问支持
@RequestMapping("/cross")
@ResponseBody
//使用@CrossOrigin开启跨域访问
//标注在处理器方法上方表示该方法支持跨域访问
//标注在处理器类上方表示该处理器类中的所有处理器方法均支持跨域访问
@CrossOrigin
public User cross(HttpServletRequest request){
System.out.println("controller cross..."+request.getRequestURL());
User user = new User();
user.setName("Jockme");
user.setAge(39);
return user;
}
3.SpringMVC的拦截器
3.1 拦截器概述
3.1.1 概述
Spring MVC 的拦截器类, 似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
3.1.2 拦截器VS过滤器
- 归属不同: Filter属于Servlet技术, Interceptor属于SpringMVC技术
- 拦截内容不同: Filter对所有访问进行增强, Interceptor仅针对SpringMVC的访问进行增强
3.2 拦截器使用
3.2.1 创建自定义拦截器
定义一个类,实现HandlerInterceptor接口,重写preHandle方法
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("MyInterceptor拦截器执行了...");
//返回true表示放行,返回false表示不放行
return true;
}
}
3.2.2 配置自定义拦截器
在springmvc配置文件中.配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--设置拦截器的拦截路径,支持*通配-->
<!--/** 表示拦截所有映射-->
<!--/* 表示拦截所有/开头的映射-->
<!--/user/* 表示拦截所有/user/开头的映射-->
<!--/user/add* 表示拦截所有/user/开头,且具体映射名称以add开头的映射-->
<!--/user/*All 表示拦截所有/user/开头,且具体映射名称以All结尾的映射-->
<!--拦截所有请求-->
<mvc:mapping path="/**"/>
<!--放行"/user/login",也可以使用通配符-->
<mvc:exclude-mapping path="/user/login"/>
<!--配置拦截器类-->
<bean class="com.itheima.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
3.2.3 注意事项
1.拦截器的拦截规则,针对的进入springmvc流程的那些请求.
2.HandlerInterceptor接口中有三个方法:
preHandler 在目标方法执行之前执行
postHandle 在目标方法执行之后,视图对象返回之前执行
afterCompletion 在流程都执行完毕后执行
3.拦截器可以有多个,组成拦截器链
4. SpringMVC异常处理机制
4.1 异常处理的思路
系统的Dao、Service、Controller在出现异常时,都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理
4.2 异常处理两种方式
① 简单异常处理器SimpleMappingExceptionResolver
② 自定义自己的异常处理器,实现HandlerExceptionResolver接口
A. 简单异常处理器
简单异常处理器,是springmvc提前做好的处理器接口, 直接配置即可使用
<!--配置简单映射异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--默认错误视图-->
<property name="defaultErrorView" value="forward:/error/errorMsg.jsp"/>
<property name="exceptionMappings">
<map>
<!--除零异常视图-->
<entry key="ArithmeticException" value="forward:/error/arithmetic.jsp"/>
<!--类型转换异常视图-->
<entry key="ClassCastException" value="forward:/error/classCast.jsp"/>
</map>
</property>
</bean>
B. 自定义异常处理器
① 定义一个类,实现HandlerExceptionResolver接口,重写方法
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex) {
ModelAndView modelAndView = new ModelAndView();
//判断出现的异常是什么异常
if (ex instanceof ArithmeticException){
//如果是除零异常
//跳转到"forward:/error/arithmetic.jsp"
modelAndView.setViewName("forward:/error/arithmetic.jsp");
}else if (ex instanceof ClassCastException){
//如果类型转换异常
//跳转到"forward:/error/classCast.jspp"
modelAndView.setViewName("forward:/error/classCast.jsp");
}else{
//其他异常
//就跳转到exceptionPage页面
modelAndView.setViewName("forward:/error/exceptionPage.jsp");
}
return modelAndView;
}
}
② 配置异常处理器
<bean id="exceptionResolver" class="com.itheima.exception.MyExceptionResolver"/>
C. 注解开发异常处理器
注解方式进行异常处理器开发,相当于使用AOP
① 定义一个异常处理器类
@Component
@ControllerAdvice //设置当前类为异常处理器类
public class ExceptionAdvice {
}
② 定义异常处理方案(方法)
@Component
@ControllerAdvice //设置当前类为异常处理器类
public class ExceptionAdvice {
//当发生NullPointerException异常时,执行这里,该方法的书写和运行规则类似于Controller
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public String doNullPointerException(Exception ex){
return "NullPointerException";
}
//当发生ArithmeticException异常时,执行这里
@ExceptionHandler(ArithmeticException.class)
public String doArithmeticException(Exception ex, Model m){
m.addAttribute("msg",m.getMessage());
return "error.jsp";
}
@ExceptionHandler(Exception.class)
@ResponseBody
public String doOtherException(Exception ex){
return "Exception";
}
}
5.SpringMVC的文件上传
5.1 文件上传三要素
-
必须包含表单项type=“file”
-
表单的提交方式是post
-
表单的enctype属性是多部分表单形式,及enctype=“multipart/form-data”
<h3>用户注册-文件上传</h3>
<form action="fu" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="name" /> <br/>
年龄: <input type="text" name="age" /> <br/>
头像: <input type="file" name="headImg" /> <br/>
<input type="submit" value="注册">
</form>
5.2 文件上传
5.2.1 添加依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
5.2.2 配置文件解析器
注意:
在SpringMVC.xml中配置文件解析器
文件解析器的Id,必须为"multipartResolver"
<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--上传文件的编码类型-->
<property name="defaultEncoding" value="UTF-8"/>
<!--文件上传的总大小(10M)-->
<property name="maxUploadSize" value="10485600"/>
<!--单个文件的大小(5M)-->
<property name="maxUploadSizePerFile" value="5242800"/>
</bean>
5.2.3 使用
注意:
1. 在Controller的方法参数中,书写MultipartFile类型的参数。
2. 参数名字必须和表单中“文件上传项”的name属性保持一致
@RequestMapping("/upload")
@ResponseBody
public void fileUpload(String name, int age, MultipartFile headImg) throws IOException {
}
5.2.4 保存文件
@RequestMapping("/upload")
@ResponseBody
public void fileUpload(String name, int age, MultipartFile headImg) throws IOException {
//获取普通项
System.out.println(name);
System.out.println(age);
//处理文件上传项
//0.判断文件是否为空
if (!headImg.isEmpty()) {
//1.获取上传文件的文件名称
String filename = headImg.getOriginalFilename(); //6b.jpeg
//2.处理文件名
filename = new Date().getTime() + "_" + filename; //1573701830347_6b.jpeg
//3.获取当前项目下的images文件夹的绝对路径
String realPath = request.getServletContext().getRealPath("/images");
//4.保存该文件
headImg.transferTo(new File(realPath,filename));
}
}
5.3 多文件上传
5.3.1 表单代码
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="name" /> <br/>
图片1: <input type="file" name="uploadFile"><br/>
图片2: <input type="file" name="uploadFile"><br/>
<input type="submit" value="提交">
</form>
5.3.2 后台代码
注意:
多文件上传时,只要把MultipartFile类型变为数组即可。
但是,要求数组名字,必须和表单中“文件上传项”的name属性保持一致
@RequestMapping("/upload")
@ResponseBody
public void fileUpload(String name, MultipartFile[] uploadFile) throws IOException {
}
6.Restful风格
6.1 Restful概述
Rest( REpresentational State Transfer) 一种网络资源的访问风格,定义了网络资源的访问方式。
传统风格访问路径:
http://localhost/user/get?id=1
Rest风格访问路径:
http://localhost/user/1
特点:
- 不明确显示参数信息。(通过路径中的某部分来传递参数)
- 隐藏资源的访问行为,通过地址无法得知做的是何种操作。(通过请求方式来确定操作行为)
6.2 行为约定
- GET请求: http://localhost/user/1 (查询)
- POST请求: http://localhost/user (保存)
- PUT请求: http://localhost/user (更新)
- DELETE请求 http://localhost/user (删除)
- **注意:**上述行为是约定方式,约定不是规范,可以打破,所以称Rest风格,而不是Rest规范
6.3 Restful开发入门
6.3.1 Restful风格的控制器
@RestController //相当于@Controller + @ResponseBody
@RequestMapping("/user")
public class UserController {
@RequestMapping("/user/{id}")
public String restLocation(@PathVariable Integer id){ //使用@PathVariable注解获取请求路径上的一部分
System.out.println("restful is running ....");
return "success.jsp";
}
@RequestMapping("{id}")
public String restLocation2(@PathVariable Integer id){
System.out.println("restful is running ....get:"+id);
return "success.jsp";
}
@GetMapping("{id}") //相当于 @RequestMapping(value = "{id}",method = RequestMethod.GET)
public String get(@PathVariable Integer id){
System.out.println("restful is running ....get:"+id);
return "success.jsp";
}
@PostMapping("{id}") //相当于 @RequestMapping(value = "{id}",method = RequestMethod.POST)
public String post(@PathVariable Integer id){
System.out.println("restful is running ....post:"+id);
return "success.jsp";
}
@PutMapping("{id}")
public String put(@PathVariable Integer id){
System.out.println("restful is running ....put:"+id);
return "success.jsp";
}
@DeleteMapping("{id}")
public String delete(@PathVariable Integer id){
System.out.println("restful is running ....delete:"+id);
return "success.jsp";
}
}
6.3.2 修改页面form表单
<form action="/user/1" method="post">
<input type="hidden" name="_method" value="PUT"/>
<input type="submit"/>
</form>
注意:
html页面只能发送get或post请求,所以,如果想使用Restful风格开发,则要求:
1.表单提交方式必须是post
2.表单中必须由一个隐藏域,参数名称固定为_method,值为真正的请求方式。
3.必须配置指定的拦截器,用来解析真正的请求方式
6.3.3 配置拦截器
<!--配置拦截器,解析请求中的参数_method,否则无法发起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>
<!--拦截所有DispatcherServlet的请求-->
<servlet-name>DispatcherServlet</servlet-name>
</filter-mapping>