请求参数绑定

当用户发送请求时,根据Spring MVC的请求处理流程,前端控制器会请求处理器映射器返回一个处理器,然后请求处理器适配器之心相应的处理器,此时处理器映射器会调用Spring Mvc 提供的参数绑定组件将请求的key/value 数据绑定到Controller处理器方法对应的形参上。Spring MVC使用Converter转换器可以进行各种类型的转换,也可自定义Converter转换器,Spring MVC默认转换器支持的类型有HttpServletRequest、HttpServletResponse、HttpSession、Model、ModelMap。其中Model是一个接口,ModelMap是一个接口实现,作用是将model数据填充到request。

简单类型,自定义类型

    //localhost:8080/springMvcNext/product/infoa?id=1
@RequestMapping("infoa")
public String productInfoa(Model model, Integer id) {
model.addAttribute("message", "productid:" + id);
return "product/info";
}

备注:如果url中参数名不是id,则不会绑定成功,需要通过使用注解RequestParam绑定参数

自定义类型传递,使用pojo传递(Product)

@RequestMapping(value="infob",method = RequestMethod.POST)
public String productInfob(Model model, Product product) {
model.addAttribute("message", "product-price:" + product.getPrice()+"product-name:" + product.getProductName());
return "product/info";
}

使用注解绑定参数

通过RequestParam注解绑定参数形参名与入参不一致的参数,RerquestParam有三个参数属性,value参数名,指定要绑定的入参名,required是否必须,默认为false,defaultValue属性,用于没有传递时赋默认值。

    //http://localhost:8080/springMvcNext/product/info?productId=1&name=fgsg
@RequestMapping("info")
public String productInfo(Model model, @RequestParam(name = "name", defaultValue = "test") String productName,
@RequestParam(required = true) Integer productId) {
model.addAttribute("message", "name:" + productName + " productid:" + productId);
return "product/info";
}

通过RequestHeader注解获取请求头的信息,RequestHeader同样有三个参数属性value,required,defaultvalue

   // http://localhost:8080/springMvcNext/product/info2
// 输出产品信息:browser:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36 language:zh-CN,zh;q=0.9
@RequestMapping("info2")
public String productInfo2(Model model, @RequestHeader("User-Agent") String browser,
@RequestHeader(value = "Accept-Language", required = false, defaultValue = "null") String language) { model.addAttribute("message", "browser:" + browser + " language:" + language);
return "product/info";
}

通过CookieValue注解获取请求头的信息

  //http://localhost:8080/springMvcNext/product/info3
  //输出:产品信息:JSESSIONID:0FD3AFA5E445DADACBC1F07568970FEC
  @RequestMapping("info3")
public String productInfo3(Model model, @CookieValue("JSESSIONID") String cookie) { model.addAttribute("message", "JSESSIONID:" + cookie);
return "product/info";
}

通过HttpServletRequest获取参数

使用HttpServletRequest获取请求参数,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息,HttpServletRequest可以用于参数解析,Cookie读取,http请求字段,文件上传

  @RequestMapping("info4")
public String productInfo(String houseUnitInfo, HttpServletRequest request, HttpServletResponse response)
throws IOException { String requestStr = charReader(request); System.out.println(requestStr); return "product/info";
} private String charReader(HttpServletRequest request) throws IOException {
BufferedReader br = request.getReader();
String str, wholeStr = "";
while ((str = br.readLine()) != null) {
wholeStr += str;
}
// System.out.println(wholeStr);
return wholeStr;
}

测试:

结果:

Action返回值

返回ModelAndView

返回ModelAndView可以指定视图名和model数据,ModelAndView提供的addObject方法来给这个模型添加数据,添加的是一个键值对的数据

  @RequestMapping("info5")
public ModelAndView productInfo5() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("product/detail");
modelAndView.addObject("message", "return modelandview");
//modelAndView.addObject("xxx", "yyy");
return modelAndView;
}

返回void,Map,Model

返回void,Map,Model 时,返回对应的逻辑视图名称就是请求url,仍然遵循:prefix前缀+视图名称 +suffix后缀组成

    //1.返回Map// 访问视图: /springMvcNext/WEB-INF/view/product/detail.jsp
@RequestMapping("detail")
public Map<String, Object> detail2313() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("message", "product detail");
return map;
} //2.返回void
//返回void时,则响应的视图页面对应为访问地址
//访问视图: /springMvcNext/WEB-INF/view/product/info6.jsp
@RequestMapping("info6")
public void productInfo6() { }

但输出流中存在输出内容时,则不会去查找视图,而是将输入流中的内容直接响应到客户端,响应的内容类型是纯文本

  @RequestMapping("info7")
public void productInfo7(HttpServletResponse response) throws IOException {
response.getWriter().write("<h2>void method</h2>");//直接相应结果 }
@RequestMapping("info8")
public void productInfo8(HttpServletResponse response) throws IOException {
response.sendRedirect("detail"); //重定向 访问:http://localhost:8080/springMvcNext/product/detail
}
    //3. 返回Model model对象会用于页面渲染,视图路径使用方法名,与void类似。示例代码如下:

      @RequestMapping("info9")
public Model productInfo9(Model model) { model.addAttribute("message", "product detail"); return model; }

返回String(视图名)

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

    @RequestMapping("info10")
public String productInfo10(Model model)
{
model.addAttribute("message", "productInfo10");
return "product/detail";
}

Spring MVC转发与重定向

使用 <mvc:view-controller>标签转发

Spring MVC中对与WEB-INF目录下面的JSP页面,不能直接通过URL访问。需要通过转发的方式,而我们一般都是在控制器中做转发映射,对应一些我们不需要其他操作的JSP页面,我们可以使用<mvc:view-controller path=""/>来配置,这样就可以不用再控制器中再去做转发映射。

    <!-- 配置直接进行转发的页面,无须进入handler方法 -->
<mvc:view-controller path="home" />
<mvc:view-controller path="order/info" />

访问:http://localhost:8080/springMvcNext/order/info 和 http://localhost:8080/springMvcNext/home 不经过处理器

使用forward或者redirect进行视图转发与重定

重定向:Spring mvc中可以在返回的结果前加上一个前缀“redirect:”,可以重定向到一个指定的页面也可以是另一个action

转发:Springmvc中返回结果前加“foword”前缀,注意:转发是一次请求(相同的request),地址栏的URL不会改变

    //重定向
//访问:http://localhost:8080/springMvcNext/product/redirecttest 时Url将跳转http://localhost:8080/springMvcNext/product/info10?redirectparas=test+redirect
@RequestMapping("redirecttest")
public String redirecttest(Model model) {
model.addAttribute("redirectparas", "test redirect"); //带参数跳转
return "redirect:/product/info10";
} //转发
//访问http://localhost:8080/springMvcNext/product/forwardtest url不会跳转
@RequestMapping("forwardtest")
public String forwardtest(Model model){
model.addAttribute("forwardparas", "test forward"); //带参数跳转
return "forward:/product/info10";
}

异常处理

Spring MVC中通过使用@controlleradvice + @ ExceptionHandler 两个注解可以实现全局的异常捕捉。

@ExceptionHandler注解的作用是当出现其定义的异常时进行处理的方法,其可以使用springmvc提供的数据绑定,比如注入HttpServletRequest等,还可以接受一个当前抛出的Throwable对象

@ControllerAdvice 注解可以把异常处理器应用到所有控制器 @Controller ,而不是@Controller注解的单个控制器,该异常处理器对当前控制器的所有方法有效;如果单独某个控制器需要自定义处理异常,不用顶层的异常处理器,可以在当前控制器内用 @ExceptionHandler 注解 ,这样当前控制器的异常处理就在当前类中。

备注:使用ControllerAdvice注解类里面的异常的处理的优先级低于直接定义在处理方法的类中

实现一个异常处理器:

@ControllerAdvice
public class ExceptionHandlers { @ExceptionHandler({ArithmeticException.class})
public ModelAndView toException(Exception e){
ModelAndView mv = new ModelAndView("home");
System.out.println("gobal handler exception");
//虽然不能使用Map往request中存值,但是可以使用下面的方法
mv.addObject("error", e);
System.out.println(e);
return mv;
}
}

控制器

@Controller
@RequestMapping("exception")
public class ExceptionController { // 示例1
@RequestMapping("test")
public ModelAndView test() {
System.out.println(10/0); //抛异常
return new ModelAndView("order/info", "message", "test exception");
}
}

拦截器

Spring MVC提供了Interceptor拦截机制,用于请求的预处理和后处理。在Spring MVC中定义一个拦截器有两种方法:第一种是实现HandlerInterceptor接口,或者继承实现了HandlerInterceptor接口的类例如(HandlerInterceptorAdapter);第二种方法是实现Spring的WebRequestInterceptor接口(该接口是针对请求的拦截器接口,接口方法参数中没有response),或者继承实现了WebrequestInterceptor的类。两种方式都是在Handler的执行周期内进行拦截操作。

如果要实现HandlerInterceptor接口,需要实现三个方法,preHandle、postHandle、afterCompletion

preHandle方法在执行Handler方法之前执行,返回false表示拦截请求,不在执行后续逻辑,可以用来做权限,日志等。

postHandle方法在执行Handler方法之后,返回modelAndView之前执行,由于该方法会在DispatcherServlet进行返回视图渲染之前被调用,所以此方法多被用于同一处理返回视图,例如将公用的模型数据添加到视图,或者根据其他情况制定公用的视图。

afterCompletion方法在执行完Handler之后执行,由于是在Controller方法执行完毕后执行该方法,所以该方法适合进行统一的异常或者日志处理操作。

实现HandlerInterceptor接口之后需要在Spring的类加载配置文件中配置拦截器实现类,才能使拦截器起到拦截的效果。HandlerInterceptor类加载配置有两种方式,分别是”针对HandlerMapping配置”和 全局配置。

针对HandlerMapping配置需要在某个处理器映射器配置中将拦截器作为参数配置进去,之后通过此处理器映射器的handler就会使用配置好的拦截器,配置如下:

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="hInterceptor1" />
<ref bean="hInterceptor2" />
</list>
</property>
<property name="order" value="1"></property>
</bean>
<bean id="hInterceptor1" class="com.sl.interceptors.TestInterceptor"></bean>
<bean id="hInterceptor2" class="com.sl.interceptors.TestOrderInterceptor"></bean>

全局配置,springmvc框架将配置的全局拦截器注入到每个HandlerMapping中。

  <!-- 配置自定义的拦截器 -->
<mvc:interceptors>
<bean class="com.sl.interceptors.TestInterceptor"></bean>
</mvc:interceptors>

实现一个拦截器:

@Component
public class TestInterceptor implements HandlerInterceptor { /**
* 当目标方法执行之前,执行此方法,返回false,则不再执行后续逻辑postHandle、afterCompletion
*/
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("First preHandle 最先执行..");
return true;
} /**
* 执行目标方法之后,渲染视图之前调。 在转向jsp页面之前, 可以对请求域中的属性,或者视图进行修改
*/
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("First postHandle 执行目标方法之后,渲染视图之前调。 在转向jsp页面之前,");
} /**
* 在渲染视图之后被调用,可以进行日志处理
*/
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("First afterCompletion 渲染视图之后调用");
}
}

运行controller则可以看到拦截器执行记录。

如果定义多个拦截器,则执行顺序如下:

1. preHandle是按配置文件中的顺序执行的

2. postHandle是按配置文件中的倒序执行的

3. afterCompletion是按配置文件中的倒序执行的

测试验证:

拦截器的指定范围:配置拦截器时可以根据需要制定拦截器作用范围,针对特定处理器或方法进行拦截。

    <!-- 配置拦截器 -->
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根节点下则拦截所有的请求 -->
<!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->
<mvc:interceptors>
<mvc:interceptor>
        <!-- 指定拦截器作用路径 -->
<mvc:mapping path="/product/*" />
<bean class="com.sl.interceptors.TestInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/order/*" />
<bean class="com.sl.interceptors.TestOrderInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>

<mvc:exclude-mapping path=""/>  表示针对该Path不拦截 ,<mvc:mapping path=""/>  表示针对该Path拦截,Path可以使用通配符。

Spring MVC温故而知新 – 参数绑定、转发与重定向、异常处理、拦截器的更多相关文章

  1. Spring MVC请求参数绑定

    所谓请求参数绑定,就是在控制器方法中,将请求参数绑定到方法参数上 @RequestParam 绑定单个请求参数到方法参数上 @RequestParam("id") Integer ...

  2. Spring MVC请求参数绑定 自定义类型转化 和获取原声带额servlet request response信息

    首先还在我们的框架的基础上建立文件 在domian下建立Account实体类 import org.springframework.stereotype.Controller; import org. ...

  3. Spring MVC初始化参数绑定

    初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法  使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型   proper ...

  4. Spring MVC 3.0 请求转发和重定向

    首先看一下如何获得request对象.session对象: 普通的Controller类,示例代码如下: @Controller @RequestMapping(value = "user& ...

  5. Spring MVC-学习笔记(5)spring MVC的文件上传、下载、拦截器

    1.文件上传.      spring MVC为文件上传提供了直接的支持,这种支持是即插即用的MultipartResolver(多部分解析器)实现的.spring MVC使用Apache Commo ...

  6. Spring MVC中forward请求转发2种方式(带参数)

    Spring MVC中forward请求转发2种方式(带参数) http://www.51gjie.com/javaweb/956.html  

  7. Spring MVC接收参数(Map,List,JSON,Date,2个Bean)(记录一次面试惨状)

    题目Spring MVC 接收参数 MapListDate2个BeanJSON Spring MVC接收参数 -Map Spring MVC接收参数 -List Spring MVC接收参数 -dat ...

  8. 2017.3.31 spring mvc教程(四)全局的异常处理

    学习的博客:http://elf8848.iteye.com/blog/875830/ 我项目中所用的版本:4.2.0.博客的时间比较早,11年的,学习的是Spring3 MVC.不知道版本上有没有变 ...

  9. Spring Boot实现一个监听用户请求的拦截器

    项目中需要监听用户具体的请求操作,便通过一个拦截器来监听,并继续相应的日志记录 项目构建与Spring Boot,Spring Boot实现一个拦截器很容易. Spring Boot的核心启动类继承W ...

随机推荐

  1. Modify the apache2 default document and home page on ubuntu (ubuntu下修改apache2默认目录和默认主页)

    Change the apache2 default website directory As we know, The apache2 default directory at /var/www/, ...

  2. 迷你MyBank

    该迷你MyBank,存贮是用对象数组来存贮的,所以比较简单,容易理解,适合新手.. 一.创建chengyuan类,在其中声明所需的成员变量: public class chengyuan { //该类 ...

  3. I/O流、文件操作

    1)操作文件 Path和Files是在JavaSE7中新添加进来的类,它们封装了在用户机器上处理文件系统所需的所有功能.Path表示的一个目录名序列,其后还可以跟着一个文件名.路径中的第一个参数可以是 ...

  4. Leecode刷题之旅-C语言/python-70爬楼梯

    /* * @lc app=leetcode.cn id=70 lang=c * * [70] 爬楼梯 * * https://leetcode-cn.com/problems/climbing-sta ...

  5. 博弈dp 以I Love this Game! POJ - 1678 为例

    写在前面的话 知识基础:一些基础的博弈论的方法,动态规划的一些知识 前言:博弈论就是一些关于策略或者游戏之间的最优解,动态规划就是对于一些状态之间转移的一些递推式(or 递归),dp分为很多很多种,比 ...

  6. node 动态页面渲染

    代码: 'use strict' const express = require('express'); const consoldiate = require('consolidate'); con ...

  7. CONVERT TEXT(转换为可排序格式)

    可以将字符 字段转换为 可按字母顺 序排列的格 式: 语法 CONVERT TEXT <c> INTO SORTABLE CODE <sc>. 该语句为字 符字段 填充可排序 ...

  8. 【Android】下拉刷新实现

    关于这方面的文章百度下有很多,我就只写写我自己实现过程. 我觉得学习一门语言不是做了几个项目就可以认为自己会了,这只是暂时的,若没有笔记,时间长了,你是怎么解决某些问题,估计连你自己都忘了,又得费时费 ...

  9. Xshell 清除历史记录方法

    使用电脑久了,就会清理电脑,将一些历史记录清除,使得电脑可以运行的更快,Xshell也是同样的道理.本集小编就教大家如何清除xshell的历史记录. 如何清除历史记录: 1.打开xshell,然后点击 ...

  10. Mac OS下搭建Hadoop + Spark集群

    首先注意版本兼容问题!!!本文采用的是Scala 2.11.8 + Hadoop 2.7.5 + Spark 2.2.0 请在下载Spark时务必看清对应的Scala和Hadoop版本! 一.配置JD ...