SSM学习笔记(6)_SpringMVC_Day02_相应数据和结果视图/文件上传/拦截器

Day02

1.响应数据和结果视图

1.1 返回值分类

展示视图

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>执行成功</h3>
    ${user.username}
    ${user.password}
</body>
</html>
1.返回值是字符串

controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。

//指定逻辑视图名,经过视图解析器解析为 jsp 物理路径:/WEB-INF/pages/success.jsp

 /**
     * 返回String
     * @param model
     * @return
     */
    @RequestMapping("/testString")
    public String testString(Model model){
        System.out.println("testString方法执行了...");
        // 模拟从数据库中查询出User对象
        User user = new User();
        user.setUsername("美美");
        user.setPassword("123");
        user.setAge(30);
        // model对象
        model.addAttribute("user",user);
        return "success";
    }
2.返回值是Void

Servlet 原始 API 可以作为控制器中方法的参数:

在 controller 方法形参上可以定义 request 和 response,使用 request 或 response 指定响应结果:

1、使用 request 转向页面,如下:

request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);

2、也可以通过 response 页面重定向:

response.sendRedirect(“testRetrunString”)

3、也可以通过 response 指定响应结果,例如响应 json 数据:

response.setCharacterEncoding(“utf-8”);
response.setContentType(“application/json;charset=utf-8”);
response.getWriter().write(“json 串”);

    /**
     * 是void
     * 请求转发一次请求,不用编写项目的名称
     */
    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("testVoid方法执行了...");
        // 编写请求转发的程序
        // request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);

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

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

        // 直接会进行响应
        response.getWriter().print("你好");

        return;
    }

3.返回值是ModelAndView对象

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

注意: 我们在页面上上获取使用的是 requestScope.username 取的,所以返回 ModelAndView 类型时,浏览器跳转只能是请求转发。

   /**
     * 返回ModelAndView
     * @return
     */
    @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(30);

        // 把user对象存储到mv对象中,也会把user对象存入到request对象
        mv.addObject("user",user);

        // 跳转到哪个页面
        mv.setViewName("success");

        return mv;
    }
1.2 SpringMVC的转发和重定向

因为使用转发和重定向时,不会再扫描配置的视图解析器,即不会再去某个指定的文件下搜寻,所以需要自己指定文件的准确路径。

1.forward请求转发

controller 方法在提供了 String 类型的返回值之后,默认就是请求转发。

需要注意的是,如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图。

它相当于“request.getRequestDispatcher(“url”).forward(request,response)”。使用请求转发,既可以转发到 jsp,也可以转发到其他的控制器方法。

    /**
     * 使用关键字的方式进行转发或者重定向
     * @return
     */
    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect(){
        System.out.println("testForwardOrRedirect方法执行了...");
        // 请求的转发
        return "forward:/WEB-INF/pages/success.jsp";
    }
2.redirect重定向

contrller 方法提供了一个 String 类型返回值之后,它需要在返回值里使用:redirect:

它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不能写在 WEB-INF 目录中,否则无法找到。

    /**
     * 使用关键字的方式进行转发或者重定向
     * @return
     */
    @RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect(){
        System.out.println("testForwardOrRedirect方法执行了...");
        // 重定向
        return "redirect:/index.jsp";
    }
1.3 ResponseBody响应json数据

DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置

1.mvc:resources标签配置不过滤

2.ocation元素表示webapp目录下的包下的所有文件

3.mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b

<!-- 设置静态资源不过滤 --> 
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 --> 
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 --> 
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->

使用 Json 需要导入:Jquery.js 文件

需要导入坐标:pom.xml

json字符串和JavaBean对象互相转换的过程中,需要使用jackson的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>

JSP页面:

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

            });
        });

    </script>

使用@RequestBody获取请求体数据

使用@RequestBody注解把json的字符串转换成JavaBean的对象

    /**
     * 模拟异步请求响应
     */
    @RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user){
        System.out.println("testAjax方法执行了...");
        // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
        System.out.println(user);
        // 做响应,模拟查询数据库
        user.setUsername("haha");
        user.setAge(40);
        // 做响应
        return user;
    }

2.SpringMVC的文件上传

文件上传的必要前提

A.form 表单的 enctype 取值必须是:multipart/form-data

(默认值是:application/x-www-form-urlencoded)

enctype:是表单请求正文的类型

B.method 属性取值必须是 Post

C.提供一个文件选择域 <input type=“file” />

2.1 传统的文件上传方式

导入坐标

<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> 

JSP页面

    <h3>传统文件上传</h3>

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

控制器

    /**
     * 文件上传
     * @return
     */
    @RequestMapping("/fileupload1")
    public String fileuoload1(HttpServletRequest request) throws Exception {
        System.out.println("文件上传...");

        // 使用fileupload组件完成文件上传
        // 上传的位置
        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){
            // 进行判断,当前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.2 SpringMVC文件上传原理

在这里插入图片描述

2.3 SpringMVC文件上传

1.引入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> 

2.编写JSP

    <h3>Springmvc文件上传</h3>

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

3.编写控制器

SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单fifile标签的name属性名称相同。

    /**
     * SpringMVC文件上传
     * @return
     */
    @RequestMapping("/fileupload2")
    public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception {
        System.out.println("springmvc文件上传...");

        // 使用fileupload组件完成文件上传
        // 上传的位置
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        // 判断,该路径是否存在
        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";
    }

4.编写文件解释器对象

注意: 文件上传的解析器 id是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不光是文件,其他字段也将无法绑定)

    <!--配置文件解析器对象,要求id名称必须是multipartResolver-->
    <bean id="multipartResolver" 		 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760" /> 
        <!--最大限制为10M 10*1024*1024-->
    </bean>
2.4 SpringMVC跨服器上传

分服务器的目的

在实际开发中,我们会有很多处理不同功能的服务器。例如:

应用服务器:负责部署我们的应用

数据库服务器:运行我们的数据库

缓存和消息服务器:负责处理大并发访问的缓存和消息

文件服务器:负责存储用户上传文件的服务器。

(注意:此处说的不是服务器集群)

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。


系统要求: 当上传一个图片时,不是上传到系统的服务器中,而是上传到一个另外的图片服务器中

在这里插入图片描述

1.配置两个服务器(Tomcat),新建一个项目作为存储图片的服务器,配置 一个新的 tomcat,修改端口号,部署环境。

2.另一个传统的服务器,作为上传文件的服务器,使用正常的 Tomcat

导入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> 

JSP页面

    <h3>跨服务器文件上传</h3>

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

控制器

   /**
     * 跨服务器文件上传
     * @return
     */
    @RequestMapping("/fileupload3")
    public String fileuoload3(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";
    }

3.SpringMVC异常处理

3.1 存在的问题及解决方案

存在的问题:

系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理

解决方案:

使用 SpringMVC的异常处理器

在这里插入图片描述

3.2 相关代码的编写

在这里插入图片描述

1.自定义异常类

package cn.itcast.exception;

/**
 * 自定义异常类
 */
public class SysException extends Exception{

    // 存储提示信息的
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public SysException(String message) {
        this.message = message;
    }

}

2.自定义异常处理器

package cn.itcast.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 异常处理器
 */
public class SysExceptionResolver implements HandlerExceptionResolver{

    /**
     * 处理异常业务逻辑
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 获取到异常对象
        SysException e = null;
        if(ex instanceof SysException){
            e = (SysException)ex;
        }else{
            e = new SysException("系统正在维护....");
        }
        // 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e.getMessage());
        mv.setViewName("error");
        return mv;
    }

}

3.配置异常处理器 springmvc.xml

 <!--配置异常处理器-->
    <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>

4.模拟异常的发生

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

    @RequestMapping("/testException")
    public String testException() throws SysException{
        System.out.println("testException执行了...");

        try {
            // 模拟异常
            int a = 10/0;
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
            // 抛出自定义异常信息
            throw new SysException("出现了一个异常....");
        }
        return "success";
    }

}

5.异常的界面

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${errorMsg}
</body>
</html>

4.SpringMVC的拦截器

4.1 基本概念

​ Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。

​ 谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

​ 说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:

过滤器 是 servlet 规范中的一部分,任何 java web 工程都可以使用。

拦截器 是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。

过滤器 在 url-pattern 中配置了**/***之后,可以对所有要访问的资源拦截。

拦截器 它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。它也是 AOP 思想的具体应用。

我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

4.2 自定义拦截器的步骤

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

HandlerInterceptor接口 一共有三个方法,不重写不会报错,默认使用接口的实现,即放过所有的程序,需要拦截哪一个需要重写相应的方法。这三个方法分别代表:预处理controller方法执行前拦截、后处理方法,controller方法执行后success.jsp执行之前拦截、success.jsp页面执行后拦截

package cn.itcast.controller.cn.itcast.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 MyInterceptor1 implements HandlerInterceptor{

    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false不放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了...前1111");
        // 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
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1执行了...后1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }

    /**
     * success.jsp页面执行后,该方法会执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最后1111");
    }

}

第二步:配置拦截器

<!-- 配置拦截器 --> 
<mvc:interceptors> 
    <mvc:interceptor> 
        <mvc:mapping path="/**"/>
			<bean id="handlerInterceptorDemo1"
class="com.itheima.web.interceptor.HandlerInterceptorDemo1">
        	</bean>
	</mvc:interceptor>
</mvc:interceptors>

第三步:测试运行结果

在这里插入图片描述


作者:耿鬼不会笑
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值