SpringMVC框架笔记(二)

文章目录

  • 一、响应数据和结果视图
    • 1.返回值分类
      • 1.1 字符串
      • 1.2 void
      • 1.3 ModelAndView
    • 2.转发和重定向
      • 2.1面试常考题:转发(forward)和重定向(redirect)的区别
        • 2.1.1 转发
        • 2.1.2 重定向
        • 2.1.3 转发(forward)和重定向(redirect)的区别
          • 2.1.3.1 从地址栏来说
          • 2.1.3.2 从数据共享来说
          • 2.1.3.3 从运用地方来说
          • 2.1.3.4 从效率来说
      • 2.2 转发(forward)和重定向(redirect)
      • 2.3 ResponseBody响应 json 数据
        • 2.3.1 使用说明
        • 2.3.2 代码实现
        • 2.3.3 测试运行结果
  • 二、SpringMVC 实现文件上传
    • 1.传统方式上传文件
    • 2.SpringMVC方式上传文件
    • 3.SpringMVC跨服务器方式文件上传
      • 3.1 分服务器的目的
      • 3.2 代码块的实现
  • 三、SpringMVC中的拦截器
    • 1.拦截器Interceptor和过滤器Filter的区别与联系
    • 2.自定义拦截器的步骤
      • 2.1 拦截器逻辑图
      • 2.2 第一步:编写一个普通类实现 HandlerInterceptor 接口
      • 2.3 第二步:配置拦截器
      • 2.4 第三步:测试运行结果

一、响应数据和结果视图

注意:其中里面的springmvc.xml和web.xml的配置文件和前面一样
success.jsp文件还是在WEB-INF的pages目录下,里面就只有执行成功语句

1.返回值分类

1.1 字符串

@Controller()
@RequestMapping("user")
public class UserController {
     
    /**
     * 返回String
     * @param model
     * @return
     */
    @RequestMapping("testString")
    public String testString(Model model) {
     
        System.out.println("testString方法执行了...");
        User user = new User();
        user.setUsername("小华");
        user.setPassword("123");
        user.setAge(16);
        model.addAttribute("user", user);
        return "success";
    }
}
  • 测试运行结果
    SpringMVC框架笔记(二)_第1张图片

1.2 void

@Controller()
@RequestMapping("user")
public class UserController {
     
/**
     * 返回void
     * @param request
     * @param response
     */
    @RequestMapping("testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
     
        System.out.println("testVoid方法执行了...");
        //1.编写请求转发的程序
//        request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response );

        //2.重定向
//        response.sendRedirect(request.getContextPath()+"/index.jsp");

        //设置中文乱码
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        //3.直接进行响应
        response.getWriter().print("你好");
        return;
    }
}
  • 输出结果:页面显示“你好”

1.3 ModelAndView

ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。

该对象中有像个经常使用的方法
1.addObject(String attributeName, Object attributeValue)

//添加模型到该对象中
//在jsp页面中可以用el表达式来获取数据,例如:${attributeName}
public ModelAndView addObject(String attributeName, Object attributeValue) {
     
    this.getModelMap().addAttribute(attributeName, attributeValue);
    return this;
}

2.setView(@Nullable View view)

//用于设置逻辑视图名称,视图解析器会根据名称前往指定的视图
@Nullable
public View getView() {
     
    return this.view instanceof View ? (View)this.view : null;
}
  • ModelAndView的实现演示代码块
@Controller()
@RequestMapping("user")
public class UserController {
     
	@RequestMapping("testModelAndView")
	public ModelAndView testModelAndView() {
     
	    //创建ModelAndView对象
	    ModelAndView mv = new ModelAndView();
	    System.out.println("testModelAndView方法执行了...");
	    //模拟数据库中查询出User对象
	    User user = new User();
	    user.setUsername("张三");
	    user.setPassword("456");
	    user.setAge(18);
	
	    //把user对象存储到mv对象中,也会把user对象存入到request对象
	    mv.addObject("user",user );
	
	    /*
	        原理和testString方式差不多: model.addAttribute("user", user);
	                                    return "success";
	        都是通过扫描视图解析器形成的
	        而且上述的最终底层原理也是通过ModelAndView来进行实现的
	     */
	    //跳转到哪个页面
	    mv.setViewName("success");
	    return mv;
	}
}

SpringMVC框架笔记(二)_第2张图片

2.转发和重定向

2.1面试常考题:转发(forward)和重定向(redirect)的区别

2.1.1 转发

是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址。

2.1.2 重定向

是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL。

2.1.3 转发(forward)和重定向(redirect)的区别

2.1.3.1 从地址栏来说

转发(forward):转发地址栏路径不变,转发只能访问当前服务器下的资源,转发是一次请求,可以使用request对象来共享数据
重定向(redirect):地址栏发生变化,重定向可以访问其他站点(服务器)的资源,重定向是两次请求。不能使用request对象来共享数据

2.1.3.2 从数据共享来说

转发(forward):转发页面和转发到的页面可以共享request里面的数据.
重定向(redirect):不能共享数据.

2.1.3.3 从运用地方来说

转发(forward):一般用于用户登陆的时候,根据角色转发到相应的模块.
重定向(redirect):一般用于用户注销登陆时返回主页面和跳转到其它的网站等

2.1.3.4 从效率来说

转发(forward):高
重定向(redirect):低

2.2 转发(forward)和重定向(redirect)

/**
     * 使用关键字进行转发和重定向
     * @return
     */
    @RequestMapping("testForwardOrRedirect")
    public String testForwardOrRedirect () {
     
        System.out.println("testForwardOrRedirect方法执行了...");

        //使用转发的方法
//        return "forward:/WEB-INF/pages/success.jsp";

        //使用重定向的方法
        // (为啥不用写request.getContextPath()来获取根目录进行添加上去,因为使用关键字的方式底层已经帮忙实现了根路径的添加)
        return "redirect:/index.jsp";
    }

2.3 ResponseBody响应 json 数据

2.3.1 使用说明

  • @RequestBody 注解的作用

该注解用于将Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 Response 响应给客户端

2.3.2 代码实现

  • java的代码
/**
 * 模拟异步请求响应
 */
@RequestMapping("testAjax")
public @ResponseBody User testAjax(@RequestBody User user) {
     
    System.out.println("testAjax方法执行了...");
    //客户端发送ajax请求,传的是json字符串,后端把json字符串封装带user对象中
    System.out.println(user);
    //做响应,模拟查询数据库
    user.setUsername("wangwu");
    user.setPassword("456");
    //做响应
    return user;
}
  • jsp的代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>响应页面</title>

    <%-- 引入jquery文件 --%>
    <script src="js/jquery.min.js"></script>

    <script>
        //页面加载,绑定单击事件
        $(function () {
     
            $("#btn").click(function () {
     
                // alert("hello btn");
                //发送ajax请求
                $.ajax({
     
                    // 编写json格式,设置属性值
                    url:"user/testAjax",
                    contentType:"application/json;charset=UTF-8",
                    data:'{"username":"nihao","password":"123","age":12}',
                    dataType:"json",
                    type:"post",
                    success:function (data) {
     
                        //data服务器响应的json的数据,进行解析
                        alert(data);
                        alert(data.username);
                        alert(data.age);
                    }
                });
            });
        })
    </script>
</head>
<body>
    <a href="user/testString">testString</a>
    <br>
    <a href="user/testVoid">testVoid</a>
    <br>
    <a href="user/testModelAndView">testModelAndView</a>
    <br>
    <a href="user/testForwardOrRedirect">testForwardOrRedirect</a>
    <br>
    <button id="btn">发送ajax请求</button>

</body>
</html>

2.3.3 测试运行结果

SpringMVC框架笔记(二)_第3张图片

二、SpringMVC 实现文件上传

文件上传的必要前提:
①form 表单的 enctype 取值必须是:multipart/form-data
(默认值是:application/x-www-form-urlencoded)
enctype:是表单请求正文的类型
②method 属性取值必须是 Post
③提供一个文件选择域 < input type=”file” />

  • 前端方面的index.jsp代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>传统方式文件上传</h3>
    <form action="user/fileUnload1" method="post" enctype="multipart/form-data">
        上传文件:<input type="file" name="upload"><br>
        <input type="submit" value="上传">
    </form>

    <h3>SpringMVC文件上传</h3>
    <form action="user/fileUnload2" method="post" enctype="multipart/form-data">
        上传文件:<input type="file" name="upload"><br>
        <input type="submit" value="上传">
    </form>

    <h3>跨服务器文件上传</h3>
    <form action="user/fileUnload3" method="post" enctype="multipart/form-data">
        上传文件:<input type="file" name="upload"><br>
        <input type="submit" value="上传">
    </form>
</body>
</html>

1.传统方式上传文件

@Controller
@RequestMapping("/user")
public class UserController {
     

    /**
     * 传统方式文件上传
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/fileUnload1")
    public String fileUnload1(HttpServletRequest request) throws Exception {
     
        System.out.println("传统方式文件上传");

        // 使用fileupload组件完成文件上传
        // 上传位置
        String path = request.getSession().getServletContext().getRealPath("/uplaods/");
        // 判断,该路径是否存在
        File file = new File(path);
        if(!file.exists()) {
     
            // 创建该文件夹
            file.mkdirs();
        }

        // 解析request对象,获取上传文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        // 解析request
        List<FileItem> items = fileUpload.parseRequest(request);
        // 遍历
        for (FileItem item : items) {
     
            // 进行判断,当前item对象是否是上传文化项
            if(item.isFormField()) {
     
                // 说明普通单项表
            } else {
     
                // 说明上传文件项
                // 获取上传文件的名称
                String fileName = item.getName();
                // 把文件的名称设置成唯一值,uuid
                String uuid = UUID.randomUUID().toString().replace("-", "");
                fileName = uuid + "_" +  fileName;
                // 完成文件上传
                item.write(new File(path,fileName));
                // 删除临时文件
                item.delete();
            }
        }
        return "success";
    }

2.SpringMVC方式上传文件

说明:传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。并且上传完成之后,浏览器可能跳转

  • 原理逻辑图:
    SpringMVC框架笔记(二)_第4张图片
  • 代码的实现
/**
 * SpringMVC方式文件上传
 * @param request
 * @return
 * @throws Exception
 */
@RequestMapping("/fileUnload2")
public String fileUnload2(HttpServletRequest request, MultipartFile upload) throws Exception {
     
    System.out.println("SpringMVC方式文件上传");

    // 使用fileupload组件完成文件上传
    // 上传位置
    String path = request.getSession().getServletContext().getRealPath("/uplaods/");
    // 判断,该路径是否存在
    File file = new File(path);
    if(!file.exists()) {
     
        // 创建该文件夹
        file.mkdirs();
    }

    // 说明上传文件项
    // 获取上传文件的名称
    String fileName = upload.getOriginalFilename();
    // 把文件的名称设置唯一值,uuid
    String uuid = UUID.randomUUID().toString().replace("-", "");
    fileName = uuid + "_" + fileName;
    // 完成文件上传
    upload.transferTo(new File(path,fileName));
    return "success";
}

3.SpringMVC跨服务器方式文件上传

  • 原理逻辑图
    SpringMVC框架笔记(二)_第5张图片

3.1 分服务器的目的

在实际开发中,我们会有很多处理不同功能的服务器。
例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器

3.2 代码块的实现

/**
 * 跨服务器方式文件上传
 * @return
 * @throws Exception
 */
@RequestMapping("/fileUnload3")
public String fileUnload3(MultipartFile upload) throws Exception {
     
    System.out.println("跨服务器方式文件上传");

    //定义上传文件服务器路径
    String path = "http://localhost:9090/uploads/";

    //说明上传文件项
    //获取上传文件的名称
    String fileName = upload.getOriginalFilename();
    //把文件的名称色湖之唯一值,uuid
    String uuid = UUID.randomUUID().toString().replace("-", "");
    fileName = uuid + "_" + fileName;

    //创建客户端对象
    Client client = Client.create();

    //和图片服务器进行连接
    WebResource webResource = client.resource(path + fileName);

    //上传文件
    webResource.put(upload.getBytes());
    return "success";
}

三、SpringMVC中的拦截器

1.拦截器Interceptor和过滤器Filter的区别与联系

①过滤器是 servlet 规范中的一部分,任何 javaweb 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
②过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是
jsp,html,css,image 或者 js 是不会进行拦截的

2.自定义拦截器的步骤

2.1 拦截器逻辑图

SpringMVC框架笔记(二)_第6张图片

2.2 第一步:编写一个普通类实现 HandlerInterceptor 接口

  • MyIntercepter2与MyIntercepter1一样,只是输出改了一下
/**
 * 自定义拦截器
 */
public class MyInterceptor1 implements HandlerInterceptor {
     
    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false 不放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
        System.out.println("MyInterceptor中的preHandle方法执行了...前111");
//        request.getRequestDispatcher("WEB-INF/pages/error.jsp").forward(request,response );
        return true;
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp执行之前
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
     
        System.out.println("MyInterceptor中的postHandle方法执行了...后111");
    }

    /**
     * success.jsp执行之后,该方法会执行(不能进行页面跳转因为已经执行了success.jsp页面,一般用于释放资源的作用)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
     
        System.out.println("MyInterceptor中的afterCompletion方法执行了...最后111");
    }
}
  • UserController的实现
/**
 * 控制方法
 */
@Controller
@RequestMapping("/user")
public class UserController {
     

    @RequestMapping("/testInterceptor")
    public String testInterceptor() {
     
        System.out.println("testInterceptor控制器方法执行了...");

        return "success";
    }
}

2.3 第二步:配置拦截器

  • 在springmvc.xml配置文件中配置
<!-- 配置拦截器 -->
<mvc:interceptors>
    <!-- 配置拦截器 -->
    <mvc:interceptor>
        <!-- 要拦截的方法 -->
        <mvc:mapping path="/user/*"/>
        <!-- 不要拦截的方法(意思:就是说上面拦截的方法和下面的不要拦截的方法实现一个就可以了)
         -->
        <!--<mvc:exclude-mapping path=""></mvc:exclude-mapping>-->
        <!-- 配置拦截器对象 -->
        <bean class="com.hugong.interceptor.MyInterceptor1"></bean>
    </mvc:interceptor>

    <!-- 配置另外一个拦截器 -->
    <mvc:interceptor>
        <!-- 要拦截的方法 -->
        <mvc:mapping path="/**"/>
        <!-- 不要拦截的方法(意思:就是说上面拦截的方法和下面的不要拦截的方法实现一个就可以了)
         -->
        <!--<mvc:exclude-mapping path=""></mvc:exclude-mapping>-->
        <!-- 配置拦截器对象 -->
        <bean class="com.hugong.interceptor.MyInterceptor2"></bean>
    </mvc:interceptor>
</mvc:interceptors>

2.4 第三步:测试运行结果

SpringMVC框架笔记(二)_第7张图片

你可能感兴趣的:(框架学习)