目录
修改form表单属性enctype为multipart/form-data
-
响应
-
返回值是String类型
- 常用
- springMVC会根据视图解析器中的前缀和后缀去寻找对应的页面资源文件
- 如果你想返回的页面在视图解析器理面没有配置, 那么你就需要自己手动使用重定向或转发了
-
返回值为空
- springMVC默认会去访问请求路径下面的页面文件, 但一般不这么使用
- 需要自己使用重定向或转发来跳转页面
-
返回值是ModelAndView
- 不常用
- 存储数据使用方法addObject()
- 底层使用的依旧是ModelMap
- 跳转页面使用的是方法setViewName
- 底层使用的是视图解析器
- 当我们使用返回值是String的跳转方式时, 底层使用的依旧是ModelAndView方式
-
/** * @return 返回值是ModelAndView类型 */ @RequestMapping("/ModelAndView") public ModelAndView test02() { ModelAndView modelAndView = new ModelAndView(); User user = new User("李乾1", "123", 23); //存储数据 modelAndView.addObject("user", user); //设置要跳转的页面 modelAndView.setViewName("success"); return modelAndView; }
-
使用forward和redirect关键字进行页面跳转
- 用得不多
-
/** * 使用关键字进行页面跳转 * * @return */ @RequestMapping("/ForwardOrRedirect") public String ForwardOrRedirect() { // return "forward:/WEB-INF/pages/success.jsp"; return "redirect:/index.jsp";// 不需要写虚拟路径, springMVC会自动帮你写虚拟路径 }
-
响应json数据
-
过滤静态资源
- 前端控制器dispatcherServlet默认会拦截所有的静态资源
- 需要告诉前端控制器那些静态资源不要拦截
- springmvc.xml中配置
-
<!--告诉前端控制器不要拦截那些资源--> <!--<mvc:resources location="/css/" mapping="/css/**"/>--> <!--<mvc:resources location="/images/" mapping="/images/**"/>--> <mvc:resources location="/js/" mapping="/js/**"/>
-
发送ajax请求
- js表达式
-
$.ajax({ url:"user/ajax",//请求的url contentType:"application/json;charset=utf-8",//发送的数据格式和字符集编码 data:'{"username":"asd","password":"123","age":22}',//json数据 dataType:"json",//预期服务器返回的数据类型 type:"post",//请求的方式 success:function (data) {//请求成功之后的回调函数 alert(data); alert(data.username) alert(data.password) alert(data.age) } })
-
- 控制器获取数据的方式
- 请求中的json数据是在请求体中, 所以要给形参添加@RequestBody注解
- js表达式
-
响应json格式数据
- 第一步需要导入jar包坐标
-
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency>
-
- 给控制器方法中的返回值添加注解@ResponseBody注解即可
- 第一步需要导入jar包坐标
-
-
-
文件上传
-
必要前提
-
修改form表单属性enctype为multipart/form-data
- 修改之后, 请求体的正文就变成了MIME类型, 我们自己解析比较麻烦, 可以使用第三方的组件Commons-fileupload
- jar包坐标
-
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
-
-
method属性必须是post
-
-
传统方法的文件上传
- 文件通过request请求发到服务器, 我们要做的就是, 解析request请求里面的数据内容, 如果是文件, 就把它上传到服务器
-
/** * 传统方法的文件上传 * 文件通过request请求发到服务器, 我们要做的就是, 解析request请求里面的数据内容, 如果是文件, 就把它上传到服务器 * * @param request * @return * @throws Exception */ @RequestMapping("/upload") public String upload(HttpServletRequest request) throws Exception { //设置上传的位置, 一般在webapps下面的ROOT文件夹里面 String path = request.getSession().getServletContext().getRealPath("/uploads"); //判断该路径是否存在, 不存在就再创建一个新的 File file = new File(path); if (!file.exists()) { //路径不存在 file.mkdirs(); } //获取解析request对象的对象(磁盘文件项) DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); //解析request对象, 获取数据项 List<FileItem> items = upload.parseRequest(request); for (FileItem item : items) { if (item.isFormField()) { //是普通的表单数据 } else { //是上传文件数据 //获取文件名 //UUID: 保证文件名字不重复 String name = UUID.randomUUID().toString().replaceAll("-", "") + item.getName(); item.write(new File(path, name)); //删除临时文件, 一旦文件项大于10kb就会产生缓存文件, 低于10kb的缓存文件出现在内存里面, 不需要我们管 item.delete(); } } return "success"; }
-
springMVC方式上传
- 需要配置一个文件解析器
- bean的属性id必须为: multipartResolver
- 相比传统方式的优点
- 解析request的操作不需要而我们来做了
-
原理图
-
配置文件解析器对象
-
<!--配置文件解析器对象--> <!--id属性必须为multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--配置上传文件大小, 10485769=10MB --> <property name="maxUploadSize" value="10485769"></property> </bean>
-
-
控制器方法
-
/** * 使用springMVC方式上传文件 * * @param request * @param upload 此参数名字必须和type属性为file的input标签的name属性值保持一致 * @return * @throws Exception */ @RequestMapping("/upload") public String upload(HttpServletRequest request, MultipartFile upload) throws Exception { //设置上传的位置, 一般在webapps下面的ROOT文件夹里面 String path = request.getSession().getServletContext().getRealPath("/uploads"); //判断该路径是否存在, 不存在就再创建一个新的 File file = new File(path); if (!file.exists()) { //路径不存在 file.mkdirs(); } //获取文件名 //UUID: 保证文件名字不重复 //getOriginalFilename(): 获取原始文件名字 String filename = "aaa" + UUID.randomUUID().toString().replaceAll("-", "") + upload.getOriginalFilename(); upload.transferTo(new File(path, filename)); return "success"; }
-
- 需要配置一个文件解析器
-
跨服务器文件上传
- 文件服务器
- 负责存储用户上传文件的服务器
- 需要导入jar包的依赖坐标
-
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency>
-
- 控制器方法代码
-
/** * 跨服务器文件上传 * * @param upload * @return * @throws Exception */ @RequestMapping("/upload2") public String upload2(MultipartFile upload) throws Exception { System.out.println("upload2..."); //定义上传到文件服务器的位置 String path = "http://localhost:81/uploads/"; //获取文件名 //UUID: 保证文件名字不重复 //getOriginalFilename(): 获取原始文件名字 String filename = UUID.randomUUID().toString().replaceAll("-", "") + "_" + upload.getOriginalFilename(); System.out.println("filename = " + filename); //创建客户端对象 Client client = Client.create(); //和文件服务器进行连接 WebResource webResource = client.resource(path + filename); //上传文件 webResource.put(upload.getBytes()); return "success"; }
-
- 文件服务器
-
-
异常处理
-
分析
- 底层出现异常一般情况都是向上抛出
- 新组件
- 异常处理器组件
-
代码编写
-
编写自定义异常类
- 用来做提示信息用的
- 需要异常类都要继承Exception类
-
package lq.exception; /* author: lq time: 2020-05-09 11:17 */ public class SysException extends Exception { private String massage; public SysException(String message) { this.massage = massage; } public String getMassage() { return massage; } public void setMassage(String massage) { this.massage = massage; } }
-
编写异常处理类
- 跳转到指定页面
- 需要实现HandlerExceptionResolver接口
-
package lq.exception; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* author: lq time: 2020-05-09 11:19 */ public class SysExceptionResolver implements HandlerExceptionResolver { /** * 异常处理器类 * @param httpServletRequest * @param httpServletResponse * @param o 不常用, 表示当前处理器对象 * @param e 接收抛出的异常对象 * @return 返回的是一个ModelAndView对象, 可以帮你实现存储信息和页面跳转 */ @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { SysException sysException=null; //判断接收到的异常是不是我们自定义的异常 if (e instanceof SysException){ //是, 直接赋值 sysException= (SysException) e; }else { //不是, 再重新新建一个 e=new SysException("系统维护中..."); } //创建视图对象 ModelAndView modelAndView = new ModelAndView(); //往request中存储错误信息 modelAndView.addObject("errorMsg",((SysException) e).getMassage()); //设置跳转页面 modelAndView.setViewName("error"); return modelAndView; } }
-
配置异常处理器
-
<!--配置异常处理器对象--> <bean id="sysExceptionResolver" class="lq.exception.SysExceptionResolver"></bean>
-
-
-
-
拦截器
-
概念
- 用于对控制器中的方法进行预处理和后处理
- 拦截器和过滤器的区别
- 过滤器是sun公司提供的, 任何javaWeb工程都可以使用
- 拦截器是springMVC自己的, 只有使用springMVC框架的项目才可以使用
- 过滤器一旦配置了/*就可以拦截所有的资源(jsp 图片 静态资源)
- 拦截器只能拦截控制器中的方法
-
入门代码
-
编写拦截器的类
- 实现HandlerInterceptor接口
- 实现了接口之后并没有让实现方法, 不是接口里面没有方法, 接口里面是有方法的, 只不过JDK1.8之后对接口进行了加强, 允许在接口中直接实现方法
-
package lq.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * */ public class MyInterceptor implements HandlerInterceptor { /** * 预处理 * @param request * @param response * @param handler * @return 返回值为true放行 返回值为false不放行, 使用request response这两个对象跳转到指定页面 * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle..."); } }
- 实现HandlerInterceptor接口
-
配置拦截器
-
<!--配置拦截器--> <mvc:interceptors> <mvc:interceptor> <!--拦截的路径--> <mvc:mapping path="/user/*"/> <bean class="lq.interceptor.MyInterceptor"></bean> <!--不拦截的路径--> <!--<mvc:exclude-mapping path="" />--> </mvc:interceptor> </mvc:interceptors>
-
-
-
HandlerInterceptor接口方法介绍
-
postHandle()
- 在控制器方法执行后, success.jsp页面执行前执行
- 当你在这个方法里面指定了一个新的跳转之后, 那么springMVC就会往新的页面跳转, 不再往旧的页面跳转, 但是, 旧的页面依然会被执行(jsp页面会现在服务器内部执行)
-
afterCompletion()
- 会在success.jsp页面执行之后执行
- 通常可以用于释放一些资源
- 最后执行
- 无法在此方法中实现页面跳转
-
-
多个拦截器之间的拦截顺序
-
拦截顺序规则(个人见解)
- 当两个拦截器拦截的路径相同时(即mvc:mapping标签的path属性相同), 拦截顺序以在springmvc.xml配置拦截器时的顺序为准
- 配置在上面的拦截器会先执行, 配置在后面的拦截器会后执行
-
<!--配置拦截器--> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/user/*"/> <bean class="lq.interceptor.MyInterceptor"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/user/*"/> <bean class="lq.interceptor.MyInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
- 当两个拦截器拦截的路径相同时(即mvc:mapping标签的path属性相同), 拦截顺序以在springmvc.xml配置拦截器时的顺序为准
-
-