SpringMVC响应+异常+拦截


前言:内容基本是黑马视频笔记,偶尔会加些个人补充,仅作为复习巩固用途。如有错误,请指出,谢谢。
提示:部分内容是完整复制粘贴过来的,不需要详细掌握,简单了解即可。

小插曲:
小插曲1、出现xml配置文件xsd标红,项目右击->Maven单击->Reimport单击,重新导入meven

小插曲2、出现引入本地jQuery,仍是无效Unresolved function or method $(),先是利用原生javascript发现能执行,后面查看博文,先是打算重启一下IDEA再说,发现意外解决问题,但仍是提示上述无效,以后万事不决先重启IDEA

一、SpringMVC对前面章节的一点补充

记得刚开始入门时候,提到spring开启注解mvc的支持,开不开无所谓,但是现在发现,不开容易出现一系列不可预知问题404,所以后面都加上

<mvc:annotation-driven></mvc:annotation-driven>

二、SpringMVC响应数据和结果视图

1. 返回值分类3种,字符串,空,ModelAndView

1. 返回字符串
	1. Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。

2. 返回值是void
	1. 如果控制器的方法返回值编写成void,没有返回响应数据,执行程序报404的异常,默认查找JSP页面没有找到。
		原因,会调用视图解析器,至于字符串则是一二级目录拼凑的。
	2. 可以使用请求转发或者重定向跳转到指定的页面,后面SpringMVC框架也提供了转发和重定向
	3. 直接返回响应数据

3. 返回值是ModelAndView对象
	1. ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图

response.jsp里触发下列方法

<body>
    <a href="user/testString">testString</a><br/>
    <a href="user/testVoid">testVoid</a><br/>
    <a href="user/testForwardOrRedirect">testForwardOrRedirect</a><br/>
    <a href="user/testModelAndView">testModelAndView</a><br/>
</body>

success.jsp页面,至于index就是普通页面,没啥内容,就不附了

<body>
    <h3>执行成功</h3>
    ${user.uname}
    ${user.age}
</body>

控制器处理结果

package com.valerius.controller;

import com.valerius.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

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

@Controller
@RequestMapping("/user")
public class UserController {
    /**
     * 返回字符串
     * @param model
     * @return
     */
    @RequestMapping("/testString")
    public String testString(Model model){
        // 模拟从数据库查找对象
        User user = new User();
        user.setUname("张三");
        user.setAge(18);
        model.addAttribute("user", user);
        return "success";
    }
    /**
     * 返回空
     */
    @RequestMapping("/testVoid")
    public void testVoid(){
        // 模拟从数据库查找对象
        System.out.println("testVoid方法执行...");
    }
    /**
     * 返回空,但使用了 转发 或重定向 或直接返回响应数据
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/testForwardOrRedirect")
    public void testForwardOrRedirect(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 模拟从数据库查找对象
        System.out.println("testForwardOrRedirect方法执行...");
        // 执行转发
        //request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
        // 执行重定向
        //System.out.println(request.getContextPath());
        //response.sendRedirect(request.getContextPath() + "/index.jsp");
        // 设置中文编码
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        // 直接返回响应数据
        response.getWriter().println("nihao");
        response.getWriter().println("你好");
        return;
    }
    /**
     * 返回 ModelAndView
     * 注意:返回字符串底层使用的仍是下面的代码
     * @return
     */
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView()  {
        // 创建ModelAndVies对象
        ModelAndView mv = new ModelAndView();
        System.out.println("testModelAndView执行了");
        // 模拟从数据库取对象,后存入session
        User user = new User();
        user.setUname("张三");
        user.setAge(18);
        // 把user对象存入mv对象中
        mv.addObject("user", user);
        // 跳转页面
        mv.setViewName("success");
        return mv;
    }

}

2.@RequestBody接收转化@ResponseBody响应转化

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

1. mvc:resources标签配置不过滤
1. location元素表示webapp目录下的包下的所有文件
2. 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 -->

参考博文:设置静态资源不被拦截的方法汇总
@RequestBody将json转化为JavaBean
@ResponseBody将JavaBean对象转化为json

  1. 使用@RequestBody获取请求体数据
// 页面加载
$(function(){
	// 绑定点击事件
	$("#btn").click(function(){
		$.ajax({
			url:"user/testJson",
			contentType:"application/json;charset=UTF-8",
			data:'{"addressName":"aa","addressNum":100}',
			dataType:"json",
			type:"post",
			success:function(data){
			alert(data);
			alert(data.addressName);
			}
		});
	});
});
* 获取请求体的数据
* @param body
*/
@RequestMapping("/testJson")
public void testJson(@RequestBody String body) {
	System.out.println(body);
}

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

// 页面加载
$(function(){
	// 绑定点击事件
	$("#btn").click(function(){
		$.ajax({
			url:"user/testJson",
			contentType:"application/json;charset=UTF-8",
			data:'{"addressName":"aa","addressNum":100}',
			dataType:"json",
			type:"post",
			success:function(data){
			alert(data);
			alert(data.addressName);
			}
		});
	});
});
/**
* 获取请求体的数据
* @param body
*/
@RequestMapping("/testJson")
public void testJson(@RequestBody Address address) {
	System.out.println(address);
}

3、使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应,但要求方法需要返回JavaBean的对象

// 页面加载
$(function(){
	// 绑定点击事件
	$("#btn").click(function(){
		$.ajax({
			url:"user/testJson",
			contentType:"application/json;charset=UTF-8",
			data:'{"addressName":"哈哈","addressNum":100}',
			dataType:"json",
			type:"post",
			success:function(data){
			alert(data);
			alert(data.addressName);
			}
		});
	});
});
@RequestMapping("/testJson")
public @ResponseBody Address testJson(@RequestBody Address address) {
	System.out.println(address);
	address.setAddressName("上海");
	return address;
}

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>

3.SpringMVC框架提供的转发和重定向,了解

. forward请求转发

  1. controller方法返回String类型,想进行请求转发也可以编写成
/**
* 使用forward关键字进行请求转发
* "forward:转发的JSP路径",不走视图解析器了,所以需要编写完整的路径
* @return
* @throws Exception
*/
@RequestMapping("/delete")
public String delete() throws Exception {
	System.out.println("delete方法执行了...");
	// return "forward:/WEB-INF/pages/success.jsp";
	return "forward:/user/findAll";
}

redirect重定向

  1. controller方法返回String类型,想进行重定向也可以编写成
/**
* 重定向
* @return
* @throws Exception
*/
@RequestMapping("/count")
public String count() throws Exception {
	System.out.println("count方法执行了...");
	return "redirect:/add.jsp";
	// return "redirect:/user/findAll";
}

三、SpringMVC的异常处理

异常最后都返回到前端控制器,前端控制器分配给异常处理器组件处理,处理好或不能处理返回到一个错误页面等

1、自定义异常类,继承异常类Exception

package com.valerius.exception;

public class SysException extends Exception{
    private static final long serialVersionUID = 4055945147128016300L;
    // 异常提示信息
    private String message;
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public SysException(String message) {
        this.message = message;
    }
}

2. 自定义异常处理器,实现HandlerExceptionResolver 接口

package com.valerius.exception;

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

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

/**
 * 异常处理器
 * @author rt
 */
public class SysExceptionResolver implements HandlerExceptionResolver {
    /**
     * 跳转到具体的错误页面的方法
     */
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                                         Object handler, Exception ex) {
        ex.printStackTrace();
        SysException e = null;
        // 获取到异常对象
        if(ex instanceof SysException) {
            e = (SysException) ex;
        }else {
            e = new SysException("请联系管理员");
        }
        ModelAndView mv = new ModelAndView();
        // 存入错误的提示信息
        mv.addObject("message", e.getMessage());
        // 跳转的Jsp页面
        mv.setViewName("error");
        return mv;
    }
}

3. 配置异常处理器

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

异常处理后转向页面error.jsp就不附了,只附上一个触发异常的方法

    @RequestMapping("/testException")
    public String testException() throws SysException {
        System.out.println("异常执行...");
        try{
            int a = 10/0;
        }
        catch(Exception e){
            e.printStackTrace();
            throw new SysException("查询所有");
        }
        return "success";
    }

四、SpringMVC框架中的拦截器,拦截方法

1. 拦截器的概述

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

注意过滤器和拦截器两者的区别

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

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

3、过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。所以过滤器经常需要放行静态资源

4、拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp, html,css,image 或者 js 是不会进行拦截的。

2.自定义拦截器步骤

创建类,实现HandlerInterceptor接口,重写需要的方法

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* 自定义拦截器1
* @author rt
*/
public class MyInterceptor1 implements HandlerInterceptor{
	/**
	* controller方法执行前,进行拦截的方法
	* return true放行
	* return false拦截
	* 可以使用转发或者重定向直接跳转到指定的页面。
	*/
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
	Object handler) throws Exception {
		System.out.println("拦截器执行了...");
		return true;
	}
}

3.在springmvc.xml中配置拦截器类

<!-- 配置拦截器 -->
<mvc:interceptors>
	<mvc:interceptor>
	<!-- 哪些方法进行拦截 -->
	<mvc:mapping path="/user/*"/>
	<!-- 哪些方法不进行拦截
	<mvc:exclude-mapping path=""/>
	-->
	<!-- 注册拦截器对象 -->
	<bean class="cn.valerius.demo1.MyInterceptor1"/>
	</mvc:interceptor>
</mvc:interceptors>

4.HandlerInterceptor接口中的方法

1. preHandle方法是controller方法执行前拦截的方法
	1. 可以使用request或者response跳转到指定的页面
	2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
	3. return false不放行,不会执行controller中的方法。

2. postHandle是controller方法执行后执行的方法,在JSP视图执行前。
	1. 可以使用request或者response跳转到指定的页面
	2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。

3.afterCompletion	只有 preHandle 返回 true 才调用,而且此方法返回为空。可以做一些资源清理

简单两个拦截器流程示意图:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值