springMVC学习笔记二:高级参数绑定,springMVC的异常处理,SpringMVC的上传功能,SpringMVC的拦截器学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33322074/article/details/89666776

1. springMVC学习笔记二:参数绑定、文件上传、拦截器学习

2. springMVC高级参数绑定

2.1. springMVC绑定数组

  1. 主要修改Controller层的接收参数类型,例如修改接收参数类型为Integer[] .
  2. 修个jsp页面。
<c:forEach items="${itemList }" var="item">
    <tr>
        <td><input type="checkbox" name="ids" value="${item.id }"></td>
  • 接收参数为Integer[] ids。注意ids一定要和前台的参数一样,springMVC接收参数的机制就是要两者相同。
@RequestMapping(value="/deletes.action")
public ModelAndView deleteitem(Integer[] ids) {
  1. 还有一种方法,再对象包装类中创建一个Integer[] 属性。让后再让Controller层方法的形参为该包装类。
public ModelAndView deletes(QueryVo vo){
  • 包装类,必须保证Integer[] 对象和jsp中的id一样。即:ids和jsp中的id值相同。
public class QueryVo {
    //商品
    private Items items;
    Integer[] ids;

2.2. springMVC绑定LIst集合

  1. 必须使用包装类,在包装类中创建list集合
public class QueryVo {
    private List<Items> itemsList;
  1. 在jsp页面通过JSTL表达式进行赋值
    • springMVC技术只要让对象名字和包装类中的属性名字相同,就能实现包装类从jsp页面中获取对应的值。
<c:forEach items="${itemList }" var="item" varStatus="s">
    <tr>
        <td><input type="checkbox" name="ids" value="${item.id }"></td>
        <td><input type="text" name="itemsList[${s.index}].name" value="${item.name }"></td>
        <td><input type="text" name="itemsList[${s.index }].price" value="${item.price }"></td>
  1. 在Controller层给方法添加包装类形参。
public ModelAndView updates(QueryVo vo){

2.3. RequestMapping映射路径标签

  1. URl路径映射
    • 可以添加多路径,这样在请求时可以多路径请求不会报错。
    • 用逗号隔开。
@RequestMapping(value = {"/item/itemlist.action","/item/itemlisthaha.action"})
  1. 添加在类上面
    • 添加在类的上面相当于全局,在该目录下。也就是说如果添加到类的上面,该类里的所有请求都要从该路径下进行。

全局请求目录

  1. 请求方法限定
    • 限定提交方式是get还是post提交,如果限定了提交类型,却用其他的方式提交就会报错。
    • 报错内容:HTTP Status 405 - Request method ‘GET’ not supported
@RequestMapping(value = "itemList",method = RequestMethod.POST)
//两种方法到可以
@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})

2.4. Controller层方法返回值

2.4.1. ModelAndView作为返回值
  1. ModeAndView
    • 是无敌的,带着数据,返回视图路径。
2.4.2. String作为返回值
  1. String作为返回值
    • 包含视图路径,为了能够带着数据,提供一个形参Model,让它带着数据。这个官方推荐,
    • 实现类数据和视图分离,符合高内聚,低耦合思想。
    • 用model.addAttribute()方法给域对象赋值。
@RequestMapping(value = {"/item/itemlist.action","/item/itemlisthaha.action"})
public String itemList(Model model,HttpServletRequest request,HttpServletResponse response) throws MessageException{
    List<Items> list = itemService.selectItemsList();
    model.addAttribute("itemList", list);
    return "itemList";
  1. String作为返回值实现重定向和转发
  • 实现重定向
return "redirect:/itemEdit.action?itemId=" + item.getId();
  1. String作为返回值实现转发
return "forward:/itemEdit.action";
2.4.3. Void作为返回值
  • 主要用于ajax异步请求,ajax返回类型是json格式,不是直接的数据,因此String作为返回值也不能接收ajax数据。
  • 在Controller方法形参上可以定义request和response,使用request或response指定响应结果:
  • 使用request转发页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
  • 可以通过response页面重定向:
response.sendRedirect("url")
response.sendRedirect("/springmvc-web2/itemEdit.action");
  • 可以通过response指定响应结果,例如响应json数据如下:
response.getWriter().print("{\"abc\":123}");

3. springMVC异常处理器

3.1. 异常处理器思路

  1. springMVC提供的异常处理器不是用来处理异常的,是用来捕获异常的,异常捕获后由程序员开发的自定义异常处理器处理异常。
  2. 异常处理器图解
    • springMVC提供的是一个异常接口HandlerExceptionResolver,我们需要写一个类实现该接口。

springMVC异常处理

3.2. 异常分类

3.2.1. 预知异常
  1. 预期异常就是预先开发人员可以知道的异常,对其进行处理。
  2. 从上图可以看出,如果程序出现异常,就会向上抛出,直到抛给异常处理器的接口,然后有异常处理器实现类完成异常的处理。
  3. 首先发现预知异常,向上抛出
    • 异常被抛给MessageException,这是一个异常信息实体类,用于存储异常信息。
@RequestMapping(value = {"/item/itemlist.action","/item/itemlisthaha.action"})
public String itemList(Model model,HttpServletRequest request,HttpServletResponse response) throws MessageException{
    //		Integer i = 1/0;
    //从Mysql中查询
    List<Items> list = itemService.selectItemsList();
    if(null == null){
        throw new MessageException("商品信息不能为空");
    }
    model.addAttribute("itemList", list);
    return "itemList";
}
  1. 异常实体类
    • 异常实体类要继承Exception。
    • 将预知异常抛出到异常实体类,异常实体类接收。
public class MessageException extends Exception{
    private String msg;
    public MessageException(String msg) {
        super();
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
  1. 异常实体类接收后,会被注入在springMVC.xml的异常实现类取出。
<!-- Springmvc的异常处理器 -->
<bean class="com.it.springmvc.exception.CustomExceptionResolver"/> 
  1. 异常处理器实现类获取异常信息,并进行处理
    • 实现接口,并从异常实体类中获取异常信息。
    • 异常被抛出后,DipatcherServlet前度控制器会自动寻找异常处理器接口,异常处理器接口再从springMVC.xml中寻找其实现类,执行该实现类。
    • 该实现类实现接口方法,并获取报错信息,或者重定向到错误页面显示。
public class CustomExceptionResolver implements HandlerExceptionResolver{

    public ModelAndView resolveException(HttpServletRequest request, 
                                         HttpServletResponse response, Object obj,
                                         Exception e) {
        ModelAndView mav = new ModelAndView();
        //判断异常为类型
        if(e instanceof MessageException){
            //预期异常
            MessageException me = (MessageException)e;
            mav.addObject("error", me.getMsg());
        }else{
            mav.addObject("error", "未知异常");
        }
        mav.setViewName("error");
        return mav;
    }
3.2.2. 运行时异常
  1. 运行时的异常,主要通过规范代码开发,测试通过手段减少运行时异常发生。

4. springMVC上传图片

4.1. 步骤分析

  1. 给上传文件的方法添加上传文件类参数:即文件接口MultipartFile
  2. 在springMVC.xml中添加bean注入文件上传实现类用于实现1步的接口。
  3. 配置虚拟目录,创建文件保存本地的路径
  4. 添加上传文件的jar:commons-fileupload-1.2.2.jar,commons-io-2.4.jar
  5. 为了防止上传的文件重名,生成uuid并去掉四个-为文件名
  6. 获取扩展名将文件上传到本地
  7. 将文件存储到数据库中
  8. 重定向验证该id下的图像

4.2. 实现代码

  1. 给文件接口添加MultiPartFile形参
public String updateitem(QueryVo vo,MultipartFile pictureFile)
  1. 配置springMVC.xml
    • 用于配置上传文件的实现类
<!-- 上传图片配置实现类 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 上传图片的大小   B   5M  1*1024*1024*5-->
    <property name="maxUploadSize" value="5000000"/>
</bean>
  1. 配置服务器虚拟目录,将文件保存到本地文件夹

配置服务器虚拟目录

配置虚拟目录

  1. 设置uuid
    • 用空字符替换掉java生成的uuid中的“-”
String name = UUID.randomUUID().toString().replaceAll("-", "");
  1. 获取图像的后缀名
String ext = FilenameUtils.getExtension(pictureFile.getOriginalFilename());
  1. 将文件上传到虚拟目录
pictureFile.transferTo(new File("D:\\upload\\" + name + "." + ext));
  1. 将文件名存储到数据库
vo.getItems().setPic(name + "." + ext);
itemService.updateItemsById(vo.getItems());
  1. jsp页面获取数据库中的图片,会从虚拟目录中获取。
<c:if test="${item.pic !=null}">
    <img src="/pic/${item.pic}" width=100 height=100/>
    <br/>
</c:if>

5. springMVC实现json格式的数据交互

5.1. springMVC封装json数据为java对象,并将数据封装为json数据

  1. spingMVC使用@RequestBody注解用于读取http请求的字符串,通过springMVC提供的HttpMessageConverter接口将读取到的内容(json数据)转换为java对象并绑定到Controller方法的参数。
  2. springMVC使用@ResponseBody注解将Controller的方法返回的对象,通过springMVC提供的HttpMessageConverter接口转换为指定的格式的数据如:json,xml等通过Resonse响应给客户端。
@RequestMapping(value = "/json.action")
public @ResponseBody
    Items json(@RequestBody Items items){
    //		System.out.println(items);
    return items;
}

5.2. 前台ajax代码

  1. 为什么使用Ajax代码呢
    • ajax最大的优点就是能在不刷新整个页面的情况下维持与服务器通信
    • 异步与服务器通信,使用异步的方式与服务器登录,不打断用户的操作。
    • 前端和后端负载均衡:将一些后端的工作移动到前端,减少服务器与带宽的负担。
    • 基于规范被广泛支持:不需要下载浏览器插件或者小程序,但需要客户允许javaScript在浏览器上执行。
    • 界面与应用分离:Ajax使得界面与应用分离,也就是数据与呈现分离。
$(function(){
    var params = '{"id": 1,"name": "测试商品","price": 99.9,"detail": "测试商品描述","pic": "123456.jpg"}';
    $.ajax({
        url : "${pageContext.request.contextPath }/json.action",
        data : params,
        contentType : "application/json;charset=UTF-8",//发送数据的格式
        type : "post",
        dataType : "json",//回调
        success : function(data){
            alert(data.name);
        }
    });
});

6. RESTful编程风格

  1. 以京东为例
    • 互联网上的所有事物都可以被抽象认为资源,如京东的资源编号。
    • 在电子商务网站中你不可能给每件商品想一个名字,只能用编号来代替。

RESTful风格京东应用

RESTful风格

  1. 传统方式和RESTful风格区别
    • 用数字代替了名字,直接写id名,不要写其他的了。

传统操作和RESTful风格请求路径对比

  1. RESTful风格做法
    • 只需要修个两点即可,在请求路径上获取id值,在方法形参中添加路径变量的注解。
    • 也就是从url请求路径上获取参数。
//RestFul风格的开发
@RequestMapping(value = "/itemEdit/{id}.action")
public ModelAndView toEdit1(@PathVariable Integer id,
                            HttpServletRequest request,HttpServletResponse response
			,HttpSession session,Model model){
  1. 原来代码
@RequestMapping(value = "/itemEdit.action")
public ModelAndView toEdit(Integer id,

7. springMVC的拦截器学习

7.1. 拦截器用途

  1. 当用户执行一个方法时需要知道该用户是否已经登录。如果登录了就执行,没有登录就重定向到登录页面。

7.2. 拦截器的使用

  1. 在springMVC.xml中配置拦截器
    • 可以在拦截器栈中配置多个拦截器
    • 可以用"/**"/表示有多个请求目录:例如:item/itemlist/abc/a.action,也表示拦截所有请求。
<!-- SPringmvc的拦截器 -->
<mvc:interceptors>
    <!-- 多个拦截器 -->
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!-- 自定义的拦截器类 -->
        <bean class="com.it.springmvc.interceptor.Interceptor1"/>
    </mvc:interceptor>
    <!-- 		<mvc:interceptor>
    <mvc:mapping path="/**"/>
    自定义的拦截器类
    <bean class="com.it.springmvc.interceptor.Interceptor2"/>
   </mvc:interceptor> -->
</mvc:interceptors>
  1. 需要自定义拦截器类
    • 该自定义类需要实现HandlerInterceptor接口,实现拦截器处理器接口。
    • 包含三个方法preHandle方法执行前,postHandle方法执行后,afterCompletion页面渲染后。
  2. 如果有多个拦截器三个方法的执行顺序遵循5个规则
    • preHandle按拦截器定义顺序调用。
    • postHandle按拦截器定义逆序调用
    • afterCompletion按拦截器定义逆序调用
    • postHandle在拦截器栈内所有拦截器返回成功才调用。一个拦截器失败,就不会调用了。
    • afterCompletion在preHandle返回true才调用。
  3. 自定义拦截器类实现判断是否登录案例
    • 第一是先获取用户提交的URI是否为login.action因为这个不需要再拦截了。
    • 再判断该session域是否有值,没有表示没有登录,重定向到登录界面。否则通过拦截器,放行。
public class Interceptor1 implements HandlerInterceptor{
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
        System.out.println("方法前 1");
        //判断用户是否登陆  如果没有登陆  重定向到登陆页面   不放行   如果登陆了  就放行了
        // URL  http://localhost:8080/springmvc-mybatis/login.action
        //URI /login.action
        String requestURI = request.getRequestURI();
        if(!requestURI.contains("/login")){
            String username = (String) request.getSession().getAttribute("USER_SESSION");
            if(null == username){
                response.sendRedirect(request.getContextPath() + "/login.action");
                return false;
            }
        }
        return true;
    }
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
        throws Exception {
        System.out.println("方法后 1");
    }
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
        throws Exception {
        System.out.println("页面渲染后 1");

    }

猜你喜欢

转载自blog.csdn.net/qq_33322074/article/details/89666776