Spring MVC知识点复习二

一、有关SpringMVC的响应问题

1.响应之返回值是字符串

这种响应就像我们前面一篇博客说的没有什么特殊之处。在这里仅把代码放在这里

@RequestMapping("/stringResponse")
    public String stringResponse(Model model){
        System.out.println("testResponse执行了");
        User user = new User();
        user.setUsername("美美");
        user.setAge(23);
        user.setMoney(100.0);
        model.addAttribute("user",user);
        return "success";
    }

2.没有返回值

对于没有返回值的响应,其大致也有三种形式,一种是转发,一种是重定向,还有一种就是直接输出,和我们原生servlet中是一模一样的。

@RequestMapping("/voidResponse")
    public void voidResponse(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //请求转发
        /*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().println("hello");
        return;
    }

3.返回值是ModelAndView类型的

@RequestMapping("/modelAndView")
    public ModelAndView testModelAndView(){
        ModelAndView modelAndView = new ModelAndView();
        User user = new User();
        user.setUsername("张三");
        user.setAge(24);
        user.setMoney(99.0);
        System.out.println("testModelAndView方法执行了");
        modelAndView.addObject("user",user);
        //跳转到哪个页面
        modelAndView.setViewName("success");
        return modelAndView;
    }

主要就是涉及两个方法,一个是addObject方法将对象添加到域中,还有一种是setViewName用于设置跳转的页面。

4.响应json数据

这个时候请注意,我们前端需要使用Jquery了,所以需要把jquery.min.js给配置进去

<script src="js/jquery.min.js"></script>

你配置之后发现根本就用不了,这是因为在配置前端控制器的时候,设置了任何资源都要拦截,然后就把静态资源给拦截了,所以在这里访问不到你添加进去的.js文件,所以需要在springmvc.xml中设置对静态资源不进行拦截:

<!-- 前端控制器,哪些静态资源不拦截 -->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/><!-- 前端控制器,哪些静态资源不拦截 -->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>

这一切配置完之后我们就可以写我们的代码了,前端基本上还是和我们JAVA web时是一致的:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Response</title>
    <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":"hehe","age":"123","money":30.0}',
                    dataType:"json",
                    type:"post",
                    success:function(data){
                        // data服务器端响应的json的数据,进行解析
                        alert(data);
                        alert(data.username);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <button id="btn">发送ajax请求</button>
</body>
</html>

在后端我们使用到了RequestBody标签,他相当于一个json数据的解析器,只要在变量前加上@RequestBody,就能够将其从json解析为单一的对象或者将对象封装成json数据类型。

@RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user){
        System.out.println("testAjax执行了");
        System.out.println(user);
        user.setUsername("张三");
        user.setAge(33);
        user.setMoney(100.0);
        return user;
    }

二、文件上传

1.传统的文件上传步骤

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

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

3)文件上传所需要的后端代码

@RequestMapping("/fileupload1")
    public String fileUpload1(HttpServletRequest request) throws Exception {
        System.out.println("文件上传");
        //使用fileupload组件完成文件上传
        //上传位置
        String path = request.getSession().getServletContext().getRealPath("/upload/");
        //判断,该路径是否存在
        File file = new File(path);
        if(!file.exists()){
            //创建该文件夹
            file.mkdir();
        }
        //解析request对象,获取上传文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
        //解析request
        List<FileItem> items = servletFileUpload.parseRequest(request);
        //遍历
        for (FileItem item : items) {
            //进行判断,当前item对象是否是上传文件项
            if(item.isFormField()){
                //说明普通表单项
            }else{
                String filename = item.getName();
                //把文件的名字设置为唯一
                String uuid = UUID.randomUUID().toString().replace("-", "");
                filename = uuid+"_"+filename;
                //完成文件上传
                item.write(new File(path,filename));
                //删除临时文件
                item.delete();
            }
        }
        return "success";
    }

可以看到整体过程是十分繁琐的,特别是在request的解析以及文件的上传部分,而springMVC可以大大简化代码。在springMVC中request只为获得文件上传的路径,而文件的上传由MuitipartFile这个对象来完成。

2.SpringMVC文件上传步骤

注意这个MultipartFile对象的变量名必须与表单中file的变量名是一致的

@RequestMapping("/fileupload2")
    public String fileupload2(HttpServletRequest request, MultipartFile upload) throws IOException {
        System.out.println("文件上传");
        //使用fileupload组件完成文件上传
        //上传位置
        String path = request.getSession().getServletContext().getRealPath("/upload/");
        //判断,该路径是否存在
        File file = new File(path);
        if(!file.exists()){
            //创建该文件夹
            file.mkdir();
        }
        //解析request对象,获取上传文件项
        String filename = upload.getOriginalFilename();
        //把文件的名字设置为唯一
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;
        //完成文件上传
        upload.transferTo(new File(path,filename));
        return "success";
    }

在这些都写完之后,还需要配置在springmvc.xml中配置一个文件解析对象:

<!-- 配置文件解析对象 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760" />
    </bean>

3.跨服务器的文件上传

以后会有各个功能不同的服务器,我们想着最后图片或者文件都保存在一个服务器上,以后我们访问也只需要和那个服务器进行连接,所以我们需要一个跨服务器文件上传的代码

 1)导入项目所需要的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>

2)配置好图片服务器的环境,在这里就不多说了,项目名我们定位upload,配完之后需要在target/upload/下新建一个文件夹叫fileuploads,用于接收传过来的文件

3)编写后端代码

@RequestMapping("/fileupload3")
    public String fileupload3(MultipartFile upload) throws IOException {
        System.out.println("文件上传");
        String path = "http://localhost:9090/fileuploads/";
        //解析request对象,获取上传文件项
        String filename = upload.getOriginalFilename();
        //把文件的名字设置为唯一
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;
        //创建客户端对象
        Client client = Client.create();
        //和图片服务器进行连接
        WebResource resource = client.resource(path + filename);
        //上传文件
        resource.put(upload.getBytes());
        return "success";
    }

需要注意的是,这里的path是指项目下的fileuploads的文件夹。

三、异常处理

Controller 调用 service service 调用 dao ,异常都是向上抛出的,最终有 DispatcherServlet 找异常处理器进行异常的处理。

1.我们需要自定义一个异常类

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.我们先在controller类中写一个异常,然后将其抛出,请注意这里我们抛出的就是我们定义的那种异常,你也可以抛Exception等其他异常

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testException")
    public String testException() throws SysException {
        //对错误信息进行捕获
        try {
            int a = 1/0;
        } catch (Exception e) {
            e.printStackTrace();
            //抛出自定义异常信息
            throw new SysException("查询所有用户出现错误了。。。");
        }
        return "success";
    }
}

3.自定义异常处理类,请注意这里的e就是我们cotroller中抛出的异常,在类中用了instanceof进行判断,判断完了之后还是需要向下转型,转成我们自己定义的SysException,然后用我们前一天学习过的第三种响应方式,即返回ModelAndView对象

public class SysExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        //获取到异常对象
        SysException sysException = null;
        if(e instanceof SysException){
            sysException = (SysException)e;
        }else{
            sysException = new SysException("系统正在维护...");
        }
        //创建ModelView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",sysException.getMessage());
        mv.setViewName("error");
        return mv;
    }
}

4.配置异常处理器

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

四、拦截器

1.拦截器的概述

1. SpringMVC 框架中的拦截器用于对处理器进行预处理和后处理的技术。
2. 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链
中的拦截器会按着定义的顺序执行。
3. 拦截器和过滤器的功能比较类似,有区别
    3.1. 过滤器是 Servlet 规范的一部分,任何框架都可以使用过滤器技术。
    3.2. 拦截器是 SpringMVC 框架独有的。
    3.3. 过滤器配置了 /* ,可以拦截任何资源。
    3.4. 拦截器只会对控制器中的方法进行拦截。
4. 拦截器也是 AOP 思想的一种实现方式
5. 想要自定义拦截器,需要实现 HandlerInterceptor 接口。

 

2.自定义拦截器的步骤

1)创建类,实现HandlerInterceptor接口,重写需要的方法,通过前面的类型转换器、异常处理器,我们总结出一条组件配置的基本步骤,首先就是要创建一个组件类,然后实现相应的接口,重写里面的方法,最后再去springmvc.xml中进行相应的配置。为了展现执行的顺序,我们创建了两个拦截器。

package com.itheima.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 {
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1执行了...后");
    }
    /*** controller方法执行前,进行拦截的方法 * return true放行 * return false拦截 * 可以使用转发或者重定向直接跳转到指定的页面。 */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了...前");
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最终");
    }
}
package com.itheima.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 MyInterceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor2执行了...前");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor2执行了...后");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor2执行了...最终");
    }
}

2)springmvc.xml中配置拦截器类

<!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 要拦截的方法 -->
            <mvc:mapping path="/user/*"/>
<!--            不要拦截的方法-->
<!--            <mvc:exclude-mapping path=""/>-->
            <bean class="com.itheima.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 要拦截的方法 -->
            <mvc:mapping path="/user/*"/>
            <bean class="com.itheima.interceptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

最后我们输出的顺序为:

 注意事项:

1. preHandle 方法是 controller 方法执行前拦截的方法
    1.1  可以使用 request 或者 response 跳转到指定的页面
    1.2 return true 放行,执行下一个拦截器,如果没有拦截器,执行 controller 中的方法。
    1.3 return false 不放行,不会执行 controller 中的方法。
2. postHandle controller 方法执行后执行的方法,在 JSP 视图执行前。
    2.1  可以使用 request 或者 response 跳转到指定的页面
    2.2  如果指定了跳转的页面,那么 controller 方法跳转的页面将不会显示。
3. postHandle 方法是在 JSP 执行后执行
    3.1 request 或者 response 不能再跳转页面了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值