-
controller 的返回值:
-
字符串时:可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
-
返回值是void
-
可以使用请求转发或者重定向跳转到指定的页面
Servlet 原始 API 可以作为控制器中方法的参数:@RequestMapping("/testReturnVoid") public void testReturnVoid(HttpServletRequest request,HttpServletResponseresponse)throws Exception { }
在 controller 方法形参上可以定义 request 和 response,使用 request 或 response 指定响应结果:
1、使用 request 转向页面,如下:
request.getRequestDispatcher("/WEBINF/pages/success.jsp").forward(request,response);
2、也可以通过 response 页面重定向:
response.sendRedirect("testRetrunString")
3、也可以通过 response 指定响应结果,例如响应 json 数据:
response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json 串");
-
-
返回值是ModelAndView对象
1. ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
2. 具体的代码如下/** * 返回ModelAndView对象 * 可以传入视图的名称(即跳转的页面),还可以传入对象。 * @return * @throws Exception */ @RequestMapping(value="/findAll") public ModelAndView findAll() throws Exception { ModelAndView mv = new ModelAndView(); // 跳转到list.jsp的页面 mv.setViewName("list"); // 模拟从数据库中查询所有的用户信息 List<User> users = new ArrayList<>(); User user1 = new User(); user1.setUsername("张三"); user1.setPassword("123"); User user2 = new User(); user2.setUsername("赵四"); user2.setPassword("456");users.add(user1); users.add(user2); // 添加对象 mv.addObject("users", users); return mv; } <%@ 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>Insert title here</title> </head> <body> <h3>查询所有的数据</h3> <c:forEach items="${ users }" var="user"> ${ user.username } </c:forEach> </body> </html>
-
-
ResponseBody 响应 json 数据
- 使用说明
- 作用:
该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 Response 响应给客户端 - 使用示例
-
需求:使用@ResponseBody 注解实现将 controller 方法返回对象转换为 json 响应给客户端。
-
前置知识点:
Springmvc 默认用 MappingJacksonHttpMessageConverter 对 json 数据进行转换,需要加入jackson 的包。<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>
jsp 中的代码: <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $("#testJson").click(function(){ $.ajax({ type:"post", url:"${pageContext.request.contextPath}/testResponseJson", contentType:"application/json;charset=utf-8", data:'{"id":1,"name":"test","money":999.0}', dataType:"json", success:function(data){ alert(data); } }); }); }) </script> <!-- 测试异步请求 --> <input type="button" value=" 测试 ajax 请求 json 和响应 json" id="testJson"/> 控制器中的代码: /** * 响应 json 数据的控制器 */ @Controller("jsonController") public class JsonController { /** * 测试响应 json 数据 */ @RequestMapping("/testResponseJson") public @ResponseBody Account testResponseJson(@RequestBody Account account) { System.out.println("异步请求:"+account); return account; } }
-
- 作用:
- 使用说明
-
文件的上传略
-
异常处理,不断向上抛,然后返回到一个异常页面,在框架里操作流程如下。
/** * 自定义异常 */ public class CustomException extends Exception { private String message; public CustomException(String message) { this.message = message; } public String getMessage() { return message; } } jsp 页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>执行失败</title> </head> <body> 执行失败! ${message } </body> </html> 自定义异常处理器 /** * 自定义异常处理器 */ public class CustomExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex) { ex.printStackTrace(); ce(); CustomException customException = null; //如果抛出的是系统自定义异常则直接转换 if(ex instanceof CustomException){ customException = (CustomException)ex; }else{ //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。 customException = new CustomException("系统错误,请与系统管理 员联系!"); }``` /** * 自定义异常 */ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", customException.getMessage()); modelAndView.setViewName("error"); return modelAndView; } } 3.2.3 配置异常处理器 <!-- 配置自定义异常处理器 --> <bean id="handlerExceptionResolver" class="com.itheima.exception.CustomExceptionResolver"/> ```
-
拦截器
Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
用户可以自己定义一些拦截器来实现特定的功能。
谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦
截的。
它也是 AOP 思想的具体应用。
我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。
-
拦截器要实现了接口:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable; public interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } } 可以看到这个类里有是三个默认方法
-
简单的拦截器实现:
/** * 自定义拦截器 */ public class HandlerInterceptorDemo1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request,HttpServletResponseresponse, Object handler) throws Exception { System.out.println("preHandle 拦截器拦截了"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception { System.out.println("postHandle 方法执行了"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion 方法执行了"); } } 第二步:配置拦截器 <!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean id="handlerInterceptorDemo1" class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean> </mvc:interceptor> </mvc:interceptors>
-
拦截器的作用路径
作用路径可以通过在配置文件中配置。 <!-- 配置拦截器的作用范围 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /><!-- 用于指定对拦截的 url --> <mvc:exclude-mapping path=""/><!-- 用于指定排除的 url--> <bean id="handlerInterceptorDemo1" class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean> </mvc:interceptor> </mvc:interceptors>
-
拦截器的执行顺序
-
拦截器的简单案例(验证用户是否登录)
- 实现思路
1、有一个登录页面,需要写一个 controller 访问页面
2、登录页面有一提交表单的动作。需要在 controller 中处理。
2.1、判断用户名密码是否正确
2.2、如果正确 向 session 中写入用户信息
2.3、返回登录成功。
3、拦截用户请求,判断用户是否登录
3.1、如果用户已经登录。放行
3.2、如果用户未登录,跳转到登录页面
控制器代码 //登陆页面 @RequestMapping("/login") public String login(Model model)throws Exception{ return "login"; } //登陆提交 //userid:用户账号,pwd:密码 @RequestMapping("/loginsubmit") public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{ //向 session 记录用户身份信息 session.setAttribute("activeUser", userid); return "redirect:/main.jsp"; } //退出 @RequestMapping("/logout") public String logout(HttpSession session)throws Exception{ //session 过期 session.invalidate(); return "redirect:index.jsp"; } 拦截器代码 public class LoginInterceptor implements HandlerInterceptor{ @Override Public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception { //如果是登录页面则放行 if(request.getRequestURI().indexOf("login.action")>=0){ /** * request.getRequestURL() 返回全路径 * request.getRequestURI() 返回除去host(域名或者ip)部分的路径 * request.getContextPath() 返回工程名部分,如果工程映射为/,此处返回则为空 * request.getServletPath() 返回除去host和工程名部分的路径 * 例如: * request.getRequestURL() http://localhost:8080/jqueryLearn/resources/request.jsp * request.getRequestURI() /jqueryLearn/resources/request.jsp * request.getContextPath()/jqueryLearn * request.getServletPath()/resources/request.jsp */ return true; } HttpSession session = request.getSession(); //如果用户已登录也放行 if(session.getAttribute("user")!=null){ return true; } //用户没有登录挑战到登录页面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response); return false; } }
- 实现思路