Spring MVC温故而知新 – 参数绑定、转发与重定向、异常处理、拦截器
请求参数绑定
当用户发送请求时,根据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温故而知新 – 参数绑定、转发与重定向、异常处理、拦截器的更多相关文章
- Spring MVC请求参数绑定
所谓请求参数绑定,就是在控制器方法中,将请求参数绑定到方法参数上 @RequestParam 绑定单个请求参数到方法参数上 @RequestParam("id") Integer ...
- Spring MVC请求参数绑定 自定义类型转化 和获取原声带额servlet request response信息
首先还在我们的框架的基础上建立文件 在domian下建立Account实体类 import org.springframework.stereotype.Controller; import org. ...
- Spring MVC初始化参数绑定
初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法 使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型 proper ...
- Spring MVC 3.0 请求转发和重定向
首先看一下如何获得request对象.session对象: 普通的Controller类,示例代码如下: @Controller @RequestMapping(value = "user& ...
- Spring MVC-学习笔记(5)spring MVC的文件上传、下载、拦截器
1.文件上传. spring MVC为文件上传提供了直接的支持,这种支持是即插即用的MultipartResolver(多部分解析器)实现的.spring MVC使用Apache Commo ...
- Spring MVC中forward请求转发2种方式(带参数)
Spring MVC中forward请求转发2种方式(带参数) http://www.51gjie.com/javaweb/956.html
- Spring MVC接收参数(Map,List,JSON,Date,2个Bean)(记录一次面试惨状)
题目Spring MVC 接收参数 MapListDate2个BeanJSON Spring MVC接收参数 -Map Spring MVC接收参数 -List Spring MVC接收参数 -dat ...
- 2017.3.31 spring mvc教程(四)全局的异常处理
学习的博客:http://elf8848.iteye.com/blog/875830/ 我项目中所用的版本:4.2.0.博客的时间比较早,11年的,学习的是Spring3 MVC.不知道版本上有没有变 ...
- Spring Boot实现一个监听用户请求的拦截器
项目中需要监听用户具体的请求操作,便通过一个拦截器来监听,并继续相应的日志记录 项目构建与Spring Boot,Spring Boot实现一个拦截器很容易. Spring Boot的核心启动类继承W ...
随机推荐
- python写爬虫的弯路
一开始按照视频上的找了笔趣阁的网站先爬一部小说, 找了<遮天>,但是章节太多,爬起来太慢, 就换了一个几十章的小说. 根据视频里的去写了代码, 在正则表达式哪里出了很大的问题. from ...
- java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=testSelect], {ExactMatcher:fDisplayName=testSelect(cool.zsn.Dao.UserMapperTest)], {LeadingIdentifierMatcher:fClassName=cool.zsn
@Before:每次调用类中的方法,都会先执行@Before下的方法 @Before下的方法应该是 public : @Before public void init() { application ...
- MySQL传输表空间使用方法
1.目标端创建同样的表结构 CREATE TABLE `test` ( `id` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHAR ...
- Docker 入坑教程笔记
Docker 入坑教程笔记 视频网址B站:点这里 查询命令 man docker 简单启动和退出 docker run --name [容器名] -i -t ubuntu /bin/bash 交互启动 ...
- 在Closing事件中,将e.Cancle设置成true,则Windows无法关机和重启系统的解决办法
最近在设计一个WinForm程序的时候遇到一个bug,就是From1窗体的关闭事件中设置了e.Cancle设置成true,导致系统无法关机重启,windows7 和windows xp都是这样. 我这 ...
- bean工具类
package com.zq.utils; import java.lang.reflect.Method;import java.util.Arrays;import java.util.Colle ...
- iOS 开发中保留小数问题
保留两位小数(四舍五入) - (void)viewDidLoad { [super viewDidLoad]; // 有时候我们需要对数据保留两位小数,而且需要四舍五入,并且需要把末尾多余的0给去掉\ ...
- thinkphp 3.2中依靠关联模型来关联三个表
这里说的是用thinkphp3.2关联模型关联三个表 根据用户表查询出三个表的数据,需要两个model来配合,第一个model是根据user表来查询到班级的信息,然后第二个model是根绝banji中 ...
- SpringMVC+Mybatis框架搭建
一.新建javaweb项目,并建好相应的包结构 二.添加项目jar到lib目录下 三.在config包中新建配置文件 sping-mvc.xml,内容如下: <?xml version=&quo ...
- 配置vue-yarm-PM2工具环境
步骤: 第一步:安装yarn 参考网址:https://yarn.bootcss.com/docs/install.html#linux-tab a.用pm2启动已创建的server.js #pm ...