上一篇总结了使用返回字符串的方式实现重定向以及重定向过程中传递字符串参数和pojo参数的过程,本篇总结另一种重定向的实现方式--返回ModelAndView
这次的场景是这样的:在页面输入一些信息添加到数据库,当添加成功时跳转到列表页,获取数据库中所有记录,添加失败时返回到错误页面,获取添加失败的记录信息。
1、创建添加页面
我在这里贴的是表单部分的代码:
<!--pojo参数传递 --> <div class="pojo public"> <p style="text-align: center;">视图重定向</p> <form id="pojoForm" action="<%=basePath%>param/addParam" method="post"> <table> <tr> <td>名称:</td> <td><input type="text" name="paramName" value=""></td> </tr> <tr> <td>描述:</td> <td><input type="text" name="paramDesc" value=""></td> </tr> <tr> <td>时间:</td> <td><input type="text" name="pramTime" value=""></td> </tr> <tr> <td></td> <td style="text-align: right;"><input type="submit" value="添加" id="redirectByModelView"></td> </tr> </table> </form> </div>
页面效果图如下:
是我用红色框框圈起来的那部分,其他的是其他功能部分的。上面代码中直接将表单提交到了<%=basePath%>param/addParam中,所以下一步就是完成控制器部分。
2、实现控制器
@Controller @RequestMapping("/param") public class ParamController { @Autowired @Qualifier("paramService") ParamService paramService = null; @RequestMapping("indexParam") public ModelAndView indexParam(String paramId) { ModelAndView mv = new ModelAndView(); System.out.println("paramId:" + paramId); List<Param> paramList = paramService.getAllParams(); mv.addObject(paramList); mv.setViewName("param/indexParam"); return mv; } /** * 重定向到失败页面 * * @param param 重定向目标方法接受pojo参数 * @return */ @RequestMapping("error") public ModelAndView error(Param param) { ModelAndView mv = new ModelAndView(); System.out.println("paramId:" + param.getParamId()); mv.addObject(param); mv.setViewName("param/error"); return mv; } /** * 通过页面添加一个参数 * * @param mv 通过ModelAndView实现重定向 * @param ra 添加失败时通过RedirectAttributes类,向重定向的目标传递pojo参数 * @param param 接受pojo参数 * @return */ @RequestMapping(value = "addParam", method = RequestMethod.POST) public ModelAndView addParam(ModelAndView mv, RedirectAttributes ra, Param param) { boolean res = paramService.insertParam(param); if (res) { // 数据库插入数据时,已经设置了逐渐自动增长,所以此处能获取到主键的前提是设置主键回填
// 添加成功时通过ModelAndView传递字符串参数 mv.addObject("paramId", param.getParamId()); mv.setViewName("redirect:./indexParam"); } else {
//添加失败时通过RedirectAttributes传递pojo参数 ra.addFlashAttribute("param", param); mv.setViewName("redirect:./error"); } return mv; } }
上面代码中的重点有:
- 表单提交到addParam方法中,接受参数的方式是pojo方式,所以需要注意pojo参数传递的几个事项,前面已经介绍过;
- 在addParam这个方法中完成重定向逻辑,且重定向是通过返回ModelAndView实现的:如果添加成功,则直接重定向到indexParam方法中,并且通过ModelAndView传递字符串参数;如果添加失败,则重定向到失败页面,且将接受的pojo对象当作参数传递给重定向之后的方法;
- 在添加成功后传递的参数是param对象的ID,因为数据库设置的是自动增长,所以前端传过来的pojo对象中没有ID,但是此时能够获取到,为什么呢?这就要在 MyBatis的映射器配置文件中设置主键自动回填,后面代码中会介绍;
- 不管重定向传递的是字符串还是pojo对象,在重定向后的方法中接受这个参数时,参数名称都是传递时设置的key;
因为调用了service层,所以还需要写service层的代码。
3、创建service层
因为上面代码中,除了添加操作外,还有添加成功之后显示所有列表的重定向页面,所以接口需定义两个方法,一个插入数据,一个获取所有数据;
1⃣️创建接口
public interface ParamService { /** * 获取所有的参数列表 * * @return */ public List<Param> getAllParams(); /* * 插入一条数据 */ public boolean insertParam(Param param); }
2⃣️创建接口实现类
@Service("paramService") public class ParamServiceImpl implements ParamService { @Autowired ParamMapper paramMapper = null; @Override public List<Param> getAllParams() { return paramMapper.getAllParams(); } @Override public boolean insertParam(Param param) { int res = paramMapper.insertParam(param); return res > 0 ? true : false; } }
实现类中主要是调用了DAO层的方法,所以接下来实现DAO层,在MyBatis中就是映射器。
4、DAO层
1⃣️映射器接口
@Repository public interface ParamMapper { /** * 获取所有的参数列表 * * @return */ public List<Param> getAllParams(); /** * 插入 * @param param * @return */ public int insertParam(Param param); }
2⃣️映射器配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mvc.dao.ParamMapper"> <resultMap id="BaseResultMap" type="com.mvc.pojo.Param"> <id column="param_id" jdbcType="INTEGER" property="paramId" /> <result column="param_name" jdbcType="VARCHAR" property="paramName" /> <result column="param_desc" jdbcType="VARCHAR" property="paramDesc" /> <result column="pram_time" jdbcType="VARCHAR" property="pramTime" /> </resultMap> <select id="getAllParams" resultMap="BaseResultMap"> SELECT * FROM param </select>
//需要配置主键回填:useGeneratedKeys="true" keyProperty="paramId"
<insert id="insertParam" parameterType="com.mvc.pojo.Param" useGeneratedKeys="true" keyProperty="paramId">
INSERT INTO param(param_name,param_desc,pram_time) values(#{paramName,jdbcType=VARCHAR},#{paramDesc,jdbcType=VARCHAR},#{pramTime,jdbcType=VARCHAR})
</insert>
</mapper>
注意⚠️:在插入的SQL中配置了主键回填,这样就可以在插入成功后将主键保存在paramId属性中,并且可以获取了。
5、重定向成功页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <% String root = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + root + "/"; %> <script type="text/javascript" src="<%=basePath%>jslib/jquery-1.8.3.min.js"></script> <script type="text/javascript" src="<%=basePath%>jslib/jquery.form.js"></script> <script type="text/javascript" src="<%=basePath%>js/param.js"></script> <link href="<%=basePath%>css/param.css" type="text/css" rel="stylesheet"> <title>参数列表</title> </head> <body> <div> <table> <thead> <tr> <td>参数ID</td> <td>参数名称</td> <td>参数描述</td> <td>入库时间</td> </tr> </thead> <tbody> <c:forEach var="paramItem" items="${paramList }"> <tr> <td>${paramItem.paramId}</td> <td>${paramItem.paramName }</td> <td>${paramItem.paramDesc }</td> <td>${paramItem.pramTime }</td> </tr> </c:forEach> </tbody> </table> </div> </body> </html>
成功之后的页面,通过JSTL标签遍历并展示获取到的数据列表,这里有个坑,就是遍历的时候会给每个元素定义一个名称var,如果这个值为param,那么获取它的属性时就会获取不到,因为我的pojo类名就是Param,所以我将var的值设置为param时获取属性失败了,这真的很坑!!!
6、重定向失败页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>error</title> </head> <body> 出错啦!!!! <p>${param.paramName}</p> </body> </html>
因为之前重定向的时候,如果失败了传递的参数是个pojo对象,所以这里可以获取对象的属性;
至此,所有代码完成,下面进行测试。
7、测试
在页面输入以下内容:
点击添加按钮后的结果如下:
从上图中可以看出,成功之后URL变成了重定向路径,并且参数传递成功,而且这个参数是通过设置主键回填才能获取到的;
下面看一下失败之后的结果,先在页面输入以下信息:
重定向结果:
上图中的失败,就是传过来的对象的name属性值,所以重定向传递pojo对象成功!!
8、总结
通过返回ModelAndView对象实现重定向时,需要注意:
传递字符串参数时使用ModelAndView即可,传递pojo参数时,还是要使用RedirectAttributes的addFlashAttribute方法;