SpringMVC = SpringMVC响应,异常处理以及拦截器

springmvc 响应,同步-页面跳转,异步-网络请求返回数据 ; ajax异步交互; restful前后端分离开发风格;

异常统一处理;拦截器

一.SpringMVC的响应:

(1)页面跳转=====转发

方式一:简单方式

方式 二: forward关键字:

此关键字的底层就是:request.getRequestDispatcher("跳转路径").forward(req,resp);

此关键字在使用后,不在经过视图解析器进行字符串的拼接...

    @RequestMapping("/quick")
    public String quick(){
//        return "success";  //方式一
//        int i=1/0;
        return "forward:/WEB-INF/pages/success.jsp"; //方式二
    }

方式三:servlet原生API

 

转发携带数据:(request域)

方式一:ServletAPI

    @RequestMapping("/requestApiData") //
    public void requestApiData(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException{
       request.setAttribute("message","requestApiData==方式四转发携带数据:");
        request.getRequestDispatcher("/WEB-INF/pages/successData.jsp").forward(request,response);
    }

方式二:ModelAndView对象

 @RequestMapping("/modelAndView")
    public ModelAndView modelAndView(ModelAndView  modelAndView){
        modelAndView.addObject("message","modelAndView==方式四转发携带数据:");
        modelAndView.setViewName("successData");
        return modelAndView;
    }

方式三:Model对象:

    @RequestMapping("/quickModel")
    public String quickModel(Model model){
        model.addAttribute("message","quickModel==b不会收到的");
        return "successData";
    }

 

(2)页面跳转---重定向

方式一:redirect 关键字

此关键字的底层:response.sendRedirect("web项目地址+重定向地址");

而且还在此技术上进行了优化,我们不需要再去编写web项目地址,直接编写重定向地址.

 //方式一
    @RequestMapping("/redirect")
    public String redirect(){
        return "redirect:/index.jsp";
    }

方式二:servlet原生API

    @RequestMapping("/responseRedirect")
    public void responseRedirect(HttpServletRequest request,HttpServletResponse response,HttpSession session) throws ServletException ,IOException{
        response.sendRedirect(request.getContextPath()+"/index.jsp");
    }

 

二、ajax异步交互

需求:

发送$.ajax()

响应new ObjectMapper().writeValueAsString()

关于SpringMVC框架,ajax异步请求,后端响应json

在SpringMVC中,这个功能主要是通过两个注解@RequestBody 和 @ResponseBody实现的

注意:

SpringMVC默认用MappingJackson2HttpMessageConverter对json数据进行转换,需要加入jackson的包

<!--jsckson -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9</version>
</dependency>

(1)RequestBody

用于接收前端传递的请求体中的json数据, 并可以自动转换封装进指定的对象中。

 

开启静态资源放行:

页面引入jquery文件

编写ajax代码:

<button id="ajaxBtn">发送ajax请求</button>
<script>
    $('#ajaxBtn').click(function () {
        // alert(1)

        /*
            使用: $.ajax() 函数
            规则:
                1.ajax提交的数据必须是一个标准的json字符串
                2.ajax提交的方式必须为post,数据必须在请求体中
                3.ajax提交的MIME类型必须为:application/json;charset=utf-8
         */
        $.ajax({
            url: '${pageContext.request.contextPath}/ajaxRequest',
            type: 'POST',
            data: '{"username":"lucy","age":18}',
            contentType:'application/json;charset=utf-8',
            success: function (resp) {

            }
        });
    })
</script>

编写User实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private String username;

    private Integer age;
}

获取请求体的json数据

 

(2)@ResponseBody

用于将controller方法返回的对象通过转换器转换为指定的格式(通常为json)之后,写入到response对象的响应体中。

 

总结:

@RequestBody:将请求体中的json字符串,转为指定类型的java对象

@ResponseBody:将java对象转为json字符串,再设置到响应体中,返回到浏览器(客户端)

 

三.Restful设计风格

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。

应用场景:前(html)后端(servlet)分离开发的架构中(ajax交互)

Restful规范了HTTP请求动作,使用四个词语分别表示对资源的CRUD操作:

  • GET(获取)、POST(新建)、PUT(更新)、DELETE(删除)

 

模拟Restful风格代码:ajax交互

/*@Controller
@ResponseBody*/
@RestController
public class RestFulController {

    // 查询所有
    // @RequestMapping(value = "/user", method = RequestMethod.GET)
    @GetMapping("/user")
   // @ResponseBody // 就相当于 response.getWriter().write()
    public String findAll() {
        System.out.println("查询所有");
        return "findAll";
    }

    // 查询一个
    // @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    @GetMapping("/user/{id}")
   // @ResponseBody
    public String findById(@PathVariable Integer id) {
        System.out.println("查询一个");
        return "findById:" + id;
    }

    // 新增
   //  @RequestMapping(value = "/user", method = RequestMethod.POST)
    @PostMapping("/user")
    // @ResponseBody
    public String save(User user) {
        System.out.println("新增");
        return "save";
    }

    // 修改
    // @RequestMapping(value = "/user", method = RequestMethod.PUT)
    @PutMapping("/user")
   // @ResponseBody
    public String update(User user) {
        System.out.println("新增");
        return "update";
    }

    // 删除
    // @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    @DeleteMapping("/user/{id}")
   // @ResponseBody
    public String delete(@PathVariable Integer id) {
        System.out.println("删除");
        return "delete:" + id;
    }

}

测试:浏览器默认只能发送:get、post请求

进入公司,如何测试自己后端代码?借助于postman工具,它可以模拟浏览器发送请求(get、post、put、delete)等请求方式...

 

 

四.异常处理

java对于异常的处理一般有两种方式:

  • 一种是当前方法处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合。

  • 一种是当前方法不处理, 出现异常后直接抛给调用者处理。

使用Spring框架后,我们的代码最终是由框架来调用的。也就是说,异常最终会抛到框架中, 然后由框架指定异常处理器来统一处理异常。

(1)自定义异常处理器:

编写异常处理器类:

// 全局异常处理器
public class GlobalExceptionResolver implements HandlerExceptionResolver {

    /**
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  处理器对象(某一个方法method对象)
     * @param ex       异常对象
     * @return ModelAndView
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 获得异常信息
        String message = ex.getMessage();
        // 创建 ModelAndView
        ModelAndView modelAndView = new ModelAndView();

        // 将异常信息存储到model中
        modelAndView.addObject("message", message);

        // 指定异常友情提示页面
        modelAndView.setViewName("forward:/error.jsp");
        return modelAndView;
    }
}

将对对象交给ioc容器:

  <!--配置全局异常处理器-->
    <bean id="globalExceptionResolver"  class="com.wsl.web.exception.GlobalExceptionResolver"></bean>

注意:

全局异常处理器:

错误页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>error</title>
</head>
<body>
<h4>错误页面...</h4>
<span>${message}</span>
</body>
</html>

 

(2)@ControllerAdvice

对所有的controller(控制器)进行异常捕获的增强,捕获什么异常自己来定,方法自己写...

/*
    对所有controller进行异常增强,底层就是AOP
 */
@ControllerAdvice
public class GlobalControllerAdvie {

    // 捕获所有异常(如果没有子异常捕获,老大哥来兜底....)
    @ExceptionHandler(Exception.class)
    public String resolverHandler(Exception ex, Model model) {
        model.addAttribute("message", "捕获所有异常..");
        return "forward:/error.jsp";
    }

    // 捕获空指针异常
    @ExceptionHandler(NullPointerException.class)
    public String resolverNullPointHandler(NullPointerException npe, Model model) {
        model.addAttribute("message", "捕获空指针异常..");
        return "forward:/error.jsp";
    }

    // 捕获数学异常

    // 捕获数组越界异常

    // 捕获内存溢出异常
}
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;


@ControllerAdvice
public class MyGlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public String resolverHandler(Exception ex, Model model){
        model.addAttribute("message","捕获异常");
        return "forward:/error.jsp";
    }

    @ExceptionHandler(NullPointerException.class)
    public String resolverNullPointHandler(NullPointerException point,Model model){
        model.addAttribute("message","空指针异常");
        return "forward:/error.jsp";
    }

    @ExceptionHandler(ArithmeticException .class)
    public String resolverNAttHandler(NullPointerException point,Model model){
        model.addAttribute("message","算术异常");
        return "forward:/error.jsp";
    }
}

注意:这个只能捕获SpringMVC的异常问题、

 

(3)Web.xml (tomcat提供异常处理) 使用web提供的异常机制:

   <!--捕获异常
        error-code 错误状态码
        location  出现错误后,跳转的提示页面
    -->
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:applicationContext.xml</param-value>
		</init-param>
		<load-on-startup>4</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<error-page>
		<error-code>404</error-code>
		<location>/404.jsp</location>
	</error-page>
</web-app>

 

五.拦截器

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理后处理

SpringMVC的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),用于对处理器进行预处理
后处理
 
拦截器对比过滤器:
二者规范不同:Filter是在servlet规范中定义,用于servlet容器中,而拦截器是spring框架提供的,用
spring容器内。
使用范围不同:Filterservlet规定的,只能用于web工程中,而拦截器没有此限制。
 
=============================
 
1. 自定义一个类实现HandleInterceptor接口,或者继承HandlerInterceptorAdaptor抽象类。
2. 实现HandlerInterceptor接口的三个方法:
preHandle() : 在目标方法之前执行,一般用于预处理
postHandle():在目标方法执行之后执行,一般用于后处理
afterCompletion():整个请求处理完毕,在视图渲染完毕时回调,一般用于资源的清理或性能的统计
 
 
 
 

(1)入门:

编写目标资源(TargetController)

@Controller
public class TargetController {

    @RequestMapping("/target")
    public String target() {
        System.out.println("目标方法执行了...");
        return "success";
    }
}

自定义拦截器:

// 自定义拦截器
public class MyIntercepter1 implements HandlerInterceptor {

    /*
        在controller目标方法执行之前,拦截
            返回值:
                true 放行
                false 拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("preHandle1...");
        // request 转发
        // response 重定向
        // handler 获取目标方法的一切信息,进行增强...
        return true;
    }
}

定义拦截器拦截规则(spring-mvc.xml)

    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- @RequestMapping("/target") -->
            <mvc:mapping path="/target"/>
            <bean class="com.wsl.web.intercept.MyIntercepter1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

测试:

(2)拦截器API介绍

 

// 自定义拦截器
public class MyIntercepter1 implements HandlerInterceptor {

    /*
        在controller目标方法执行之前,拦截
            返回值:
                true 放行
                false 拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("preHandle1...");
        // request 转发
        // response 重定向
        // handler 获取目标方法的一切信息,进行增强...
        return true;
    }

    /*
        在controller目标方法执行之后,进行增强
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("postHandle1...");
    }

    /*
        在视图渲染完毕后,进行资源释放
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("afterCompletion1....");
    }
}

(3)拦截器链

开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链。

开发步骤和单个拦截器是一样的,只不过注册的时候注册多个,注意这里注册的顺序就代表拦截器执行的顺序。

 

例子和入门案例一致,创建另外一个MyIntercepter2,对象

1.拦截器执行先后问题:mvc:interceptor 谁先声明,谁先拦截

拦截器方法的执行顺序:先进后出

六:配置文件:

Spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		 http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc.xsd
		 http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解组件扫描-->
    <context:component-scan base-package="com.wsl.web"/>



    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>


    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="5024000"></property>
    </bean>

    <!--配置拦截器-->
    <!--拦截器的配置顺序决定了拦截器的执行顺序-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/target"/>
            <bean class="com.wsl.web.interceptor.MyIntercepter01"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/target"/>
            <bean class="com.wsl.web.interceptor.MyIntercepter"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!--配置错误页面-->
    <!--<bean id="globalExceptionResolver" class="com.wsl.web.execption.GobalExpectionResolver"></bean>-->

    <!--开启mvc注解支持-->
    <mvc:annotation-driven></mvc:annotation-driven>

    <mvc:default-servlet-handler></mvc:default-servlet-handler>

</beans>

pom.xml

 <dependencies> 
    <!--mysql驱动-->  
    <dependency> 
      <groupId>mysql</groupId>  
      <artifactId>mysql-connector-java</artifactId>  
      <version>5.1.47</version> 
    </dependency>  
    <!--druid连接池-->  
    <dependency> 
      <groupId>com.alibaba</groupId>  
      <artifactId>druid</artifactId>  
      <version>1.1.15</version> 
    </dependency>  
    <!--spring-jdbc-->  
    <dependency> 
      <groupId>org.springframework</groupId>  
      <artifactId>spring-jdbc</artifactId>  
      <version>5.1.5.RELEASE</version> 
    </dependency>  
    <!--spring核心-->  
    <dependency> 
      <groupId>org.springframework</groupId>  
      <artifactId>spring-context</artifactId>  
      <version>5.1.5.RELEASE</version> 
    </dependency>  
    <!--junit-->  
    <dependency> 
      <groupId>junit</groupId>  
      <artifactId>junit</artifactId>  
      <version>4.12</version> 
    </dependency>  
    <!--spring整合junit-->  
    <dependency> 
      <groupId>org.springframework</groupId>  
      <artifactId>spring-test</artifactId>  
      <version>5.1.5.RELEASE</version> 
    </dependency>  
    <dependency> 
      <groupId>org.springframework</groupId>  
      <artifactId>spring-orm</artifactId>  
      <version>5.1.5.RELEASE</version> 
    </dependency>  
    <dependency> 
      <groupId>org.aspectj</groupId>  
      <artifactId>aspectjweaver</artifactId>  
      <version>1.9.5</version> 
    </dependency>  
    <!--springMVC-->  
    <dependency> 
      <groupId>org.springframework</groupId>  
      <artifactId>spring-webmvc</artifactId>  
      <version>5.1.5.RELEASE</version> 
    </dependency>  
    <!--servlet-->  
    <dependency> 
      <groupId>javax.servlet</groupId>  
      <artifactId>servlet-api</artifactId>  
      <version>2.5</version>  
      <scope>provided</scope> 
    </dependency>  
    <!--jsp-->  
    <dependency> 
      <groupId>javax.servlet</groupId>  
      <artifactId>jsp-api</artifactId>  
      <version>2.0</version>  
      <scope>provided</scope> 
    </dependency>  
    <dependency> 
      <groupId>org.projectlombok</groupId>  
      <artifactId>lombok</artifactId>  
      <version>1.18.10</version> 
    </dependency>  
    <dependency> 
      <groupId>commons-fileupload</groupId>  
      <artifactId>commons-fileupload</artifactId>  
      <version>1.4</version> 
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.9</version>
    </dependency>

  </dependencies>
  
  <build> 
    <plugins> 
      <plugin> 
        <groupId>org.apache.maven.plugins</groupId>  
        <artifactId>maven-compiler-plugin</artifactId>  
        <version>3.1</version>  
        <configuration> 
          <source>1.8</source>  
          <target>1.8</target>  
          <encoding>UTF-8</encoding> 
        </configuration> 
      </plugin> 
    </plugins> 
  </build> 

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:applicationContext.xml</param-value>
		</init-param>
		<load-on-startup>4</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>


	<error-page>
		<error-code>404</error-code>
		<location>/404.jsp</location>
	</error-page>
</web-app>

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章