笔记输出来源:拉勾教育Java就业急训营
如有侵权,私信立删
修改时间:2020年2月25日
作者:pp_x
邮箱:[email protected]
文章目录
SpringMVC中的ajax
- Springmvc默认用
MappingJackson2HttpMessageConverter
对json数据进行转换,需要加入jackson的包;同时使用<mvc:annotation-driven />
- 需要的依赖
<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-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
RequestBody
- 该注解用于Controller的方法的形参声明,当使用ajax提交并指定contentType为json形式时,通过
HttpMessageConverter
接口转换为对应的POJO对象 - 用于获取请求体中的参数,并封装成对应的对象,get请求的时候不需要此注解
- ajax
$("#btn1").click(function () {
let url = '${pageContext.request.contextPath}/user/ajaxRequest';
let data = '[{"id":1,"name":"张三"},{"id":2,"name":"ppx"}]';
$.ajax({
type:'post',
url:url,
data:data,
contentType:'application/json;charset=utf-8',
success:function (resp) {
alert(JSON.stringify(resp));
}
})
})
- Controller
/*ajax异步交互*/
@RequestMapping("/ajaxRequest")
public List<User> ajaxRequest(@RequestBody List<User> list){
System.out.println(list);
return list;
}
@ResponseBody
- 该注解用于将Controller的方法返回的对象,通过
HttpMessageConverter
接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
/*ajax异步交互*/
@RequestMapping("/ajaxRequest")
@ResponseBody//返回给浏览器 就不会再走视图解析器
public List<User> ajaxRequest(@RequestBody List<User> list){
System.out.println(list);
return list;
}
RESTful
RESTful概念
- Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
- Restful风格的请求是使用
“url+请求方式”
表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:- GET:读取(Read)
- POST:新建(Create)
- PUT:更新(Update)
- DELETE:删除(Delete)
客户端请求 | 原本风格 | RESTful风格 |
---|---|---|
查询所有 | /user/findAll | GET /user |
根据Id查询 | /user/findById | GET /user/{id} |
增加 | /user/save | POST /user |
更改 | /user/update | PUT /user |
删除 | /user/delete | DELETE /user |
代码实现
- @PathVariable
用来接收RESTful风格请求地址中占位符的值 - @RestController
来替代@Controller
和@ResponseBody
两个注解
// @Controller
@RestController //代替`@Controller`和`@ResponseBody`两个注解
public class RestFulController {
@GetMapping(value = "/user/{id}")
// 相当于 @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
// @ResponseBody
public String get(@PathVariable Integer id) {
return "方法名:" + id;
}
@PostMapping(value = "/user")
// @ResponseBody
public String post() {
return "方法名";
}@PutMapping(value = "/user")
// @ResponseBody
public String put() {
return "方法名";
}
@DeleteMapping(value = "/user/{id}")
// @ResponseBody
public String delete(@PathVariable Integer id) {
return "方法名:"+ id;
}
}
文件上传
文件上传三要素
- 表单项
type="file"
- 表单的提交方式
method="POST"
- 表单的enctype属性是多部分表单形式
enctype=“multipart/form-data"
文件上传原理
- 当form表单修改为多部分表单时,
request.getParameter()
将失效 - 当form表单的enctype取值为
application/x-www-form-urlencoded
时,- form表单的正文内容格式是:
name=value&name=value
当form表单的enctype取值为mutilpart/form-data
时,请求正文内容就变成多部分形式
- form表单的正文内容格式是:
单文件上传
- 需要的坐标
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
- spring-mvc.xml配置文件上传解析器
<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置文件上传的最大值 最大为5mb-->
<property name="maxUploadSize" value="5242880"></property>
<!--设定文件上传时 写入内存的最大值 如果小于这个参数不会生成临时文件,默认为10240-->
<property name="maxInMemorySize" value="40960"></property>
</bean>
- 前端代码
<%--编写一个满足文件上传三要素的表单
1.表单的提交方式必须是post
2.表单的enctype属性必须要修改成multipart/form-data
3.表单中必须要有文件上传项
--%>
<form action="${pageContext.request.contextPath}/fileupload" method="post" enctype="multipart/form-data">
名称:<input type="text" name="username"> <br>
文件:<input type="file" name="filePic"> <br>
<input type="submit" value="单文件上传">
</form>
- 控制器方法
/*
单文件上传
* */
@RequestMapping("/fileupload")
public String fileUpload(String username, MultipartFile filePic) throws IOException {
//获取表单的提交参数
System.out.println(username);
// 获取文件名
String originalFilename = filePic.getOriginalFilename();
//将文件存储到D盘的upload下
filePic.transferTo(new File("D:/upload/"+originalFilename));
return "success";
}
多文件上传
- 多文件上传只需要增加多个name值相同的文件表单项,控制器方法使用
MultipartFile[]
数组接收即可
SpringMVC的异常处理
- 在Java中,异常处理一般有两种形式:
- 一种是在当前方法内捕获异常即
try-catch
,此种方式会增加异常代码和业务代码的耦合 - 另一种是抛出异常
throws
,将异常抛给调用者,调用者再抛给调用者,此方法最后会增加jvm的负担
- 一种是在当前方法内捕获异常即
- SpringMVC中的异常处理机制
自定义异常处理器
步骤分析
- 创建异常处理器类实现
HandlerExceptionResolver
- 配置异常处理器
- 编写异常页面
- 测试异常跳转
代码实现
- 异常处理类
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//具体的异常处理
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("error",e.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
- spring-mvc.xml中异常处理器
//异常处理类上使用@component注解
//配置bean标签
<bean id="globalExecptionResovler" class="com.lagou.exception.GlobalExecptionResovler">
</bean>
- 异常页面
<body>
这是异常页面${error}
</body>
- 测试跳转
@Controller
public class ExceptionController {
@RequestMapping("testException")
public String test(){
int i = 1/0;
return "success";
}
}
Web的异常处理
- 如果不想服务器404、500异常的时候,浏览器跳转至默认页面,可以进行如下配置
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
拦截器
拦截器的作用
- Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理
- 将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现
拦截器和过滤器的区别
代码实现
- 创建拦截器类实现
HandlerInterceptor
接口 - 配置拦截器
- 测试拦截器的拦截效果
- 创建拦截器实现接口
public class MyInterceptor implements HandlerInterceptor {
/*
* 目标方法执行之前进行拦截
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
//false代表不放行 反之放行
return true;
}
/*
* 目标方法执行之后,视图对象返回之前执行
* */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
/*
* 目标方法都执行完后 执行此方法
* */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
- spring-mvc.xml中配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/><!--代表堆所有controller类里面所有的方法进行拦截-->
<bean class="com.lagou.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lagou.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
- 测试
@Controller
public class TargetController {
@RequestMapping("/targetController")
public String targetMethod(){
System.out.println("目标方法执行了");
return "success";
}
}
拦截器链
- 开发中拦截器可以单独使用也可以多个拦截器一起使用,当按顺序注册多个拦截器的时候,就形成了一个拦截器链,注册顺序就是拦截器执行顺序
- 第二个拦截器实现代码
public class MyInterceptor2 implements HandlerInterceptor {
/*
* 目标方法执行之前进行拦截
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle2");
//false代表不放行 反之放行
return false;
}
/*
* 目标方法执行之后,视图对象返回之前执行
* */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle2");
}
/*
* 目标方法都执行完后 执行此方法
* */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion2");
}
}
- 配置同上
- 执行结果
preHandle
preHandle2
目标方法执行了
postHandle2
postHandle
视图执行了
afterCompletion2
afterCompletion
小结
- 如果其中一个拦截器
preHandle()
方法返回false,那么其拦截器及其后拦截器的postHandle()
和afterCompletion()
方法不在执行,其之前的拦截器会执行afterCompletion()
,但不会执行postHandle()