SpringMVC 学习笔记

    技术2022-07-10  87

    一、SpringMVC请求流程

    用户发送请求,到前端控制器(servlet,DispatcherServlet)配置在web.xml中;前端控制器去找处理器映射器(HandlerMapping) 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理拦截器一并返回给 DispatcherServlet;根据处理器映射器返回的处理器,DispatcherServlet 会找“合适”的处理器适配器(HandlerAdapter);处理器适配器HandlerAdapter 会去执行处理器(Handler开发的时候会被叫成Controller也叫后端控制器)执行前会有转换器、数据绑定、校验器等等完成上面这些才会去正式执行Handler后端控制器Handler执行完成之后返回一个ViewResolver对象处理器适配器HandlerAdapter会将这个ModelAndView返回前端控制器DispatcherServlet 前端控制器会将ModelAndView对象交给视图解析器ViewResolver视图解析器ViewResolver解析ViewResolver对象之后返回逻辑视图前端控制器DispatcherServlet对逻辑视图进行渲染 (数据填充) 之后返回真正的物理View并响应给浏览器

    二、配置文件

    1. web.xml

    <!-- 1. 配置DispatcherServlet --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 2. 配置初始化参数 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc2.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

    2. springmvc.xml

    <!-- 1. 注解的扫描 --> <context:component-scan base-package="com.lyzzz"/> <!-- 自动配置RequestMappingHandlerMapping 和RequestMappingHandlerAdapter注解的驱动 --> <mvc:annotation-driven/> <!-- 2. 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 3. 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 不拦截登录请求 --> <!--<mvc:exclude-mapping path="/login"/>--> <bean class="com.lyzzz.interceptor.MyInterceptor"/> </mvc:interceptor> <!-- 当设置多个拦截器时,先按顺序调用preHandler方法 然后逆序调用每个拦截器的postHandler和afterCompletion方法--> </mvc:interceptors> <!-- 4. 异常处理器 --> <bean id="customExceptionResolver" class="com.lyzzz.exception.CustomExceptionResolver"></bean> <!-- 5. 前端控制器拦截的是 / 释放静态资源的handler --> <mvc:default-servlet-handler/>

    三、@RequestMapping注解

    @RequestMapping

    value: 可配置多个地址 @RequestMapping(value = {"/method1","/method2","/method3"}) public String method() method:配置请求方式 @RequestMapping(method = {RequestMethod.POST,RequestMethod.GET}) public void method() 如有多个重复地址,可在类上添加@RequestMapping @Controller @RequestMapping("/param") public class ParamController 响应数据格式consumes:指定处理请求的提交内容的类型(content-Type) @RequestMapping(consumes = "application/json;charset=utf-8") // 接收json public void method() 读取数据格式produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回 @RequestMapping(produces = "application/json;charset=utf-8") // 返回json public void method() params:指定request中必须包含某些参数值,才让该方法处理 @RequestMapping(params = {"/num"}) public void method() headers:指定request中必须包含某些指定的header值,才让该方法处理请求 @RequestMapping(headers = {"\"Referer=http://www.hello.com/\""}) public void method()

    四、@ResponseBody和 @RequestBody

    @ResponseBody 发送 json // 在方法上添加@ResponseBody,恒不跳转 @RequestMapping(value = "/method1",produces = "application/json;charset=utf-8") @ResponseBody public String method1(){ String json = "{\"name\":\"zs\",\"age\":\"18\"}"; return json; } @RequestBody 接收 json 封装参数 @RequestMapping(value = "/method2" ,method = {RequestMethod.POST}) @ResponseBody // @RequestBody 接收json 封装参数 public Teacher method2(@RequestBody Teacher teacher){ System.out.println(teacher); return teacher; }

    要添加jackson jar包 * tomcat报错conf>catalina.properties * 添加 ,\ jackson-databind-2.10.0.jar,jackson-annotations-2.10.0.jar,jackson-core-2.10.0.jar

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

    @RestController

    @RestController //设置该类的所有方法返回 JSON 数据 //等价于 @Controller + @RequestBody

    五、reseful @PathVariable

    @RequestMapping("/method6/{name}/{age}") public String method6(@PathVariable("name") String name, @PathVariable("age") int age){ System.out.println(name); System.out.println(age); return "param"; }

    六、封装数据

    方法参数不同 @RequestParam @RequestMapping("/method2") // 参数名称不同@RequestParam(value = "names") public String method2(@RequestParam(value = "names",required = true) String name, @RequestParam(defaultValue = "20") Integer age){ System.out.println(name); System.out.println(age); return "param"; } 日期类型 @RequestMapping(value = "/method3") public String method3(Date birthday){ System.out.println(birthday); return "param"; } // 处理日期格式 @InitBinder public void bindValue(WebDataBinder binder){ binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); } // JavaBean属性 @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthday;

    七、返回值

    /** * Controller中方法的返回值 * */ // 1. 返回ModelAndView @RequestMapping("method1") public ModelAndView method1(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("result","返回值是modelandview"); modelAndView.setViewName("method1"); return modelAndView; } // 2. 返回void @RequestMapping("method2") public void method2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 在controller形参上可以定义 request和response,并指定响应结果 // request request.setAttribute("request","request"); request.getRequestDispatcher("/WEB-INF/view/method1.jsp").forward(request,response); // session HttpSession session = request.getSession(); session.setAttribute("response","response1"); // 不能直接访问WEB-INF下的文件,受保护 response.sendRedirect("/index.jsp"); // 响应json response.setContentType("application/json;charset=utf-8"); response.getWriter().println("{\"name\":\"中国\"}"); String method3 = (String) request.getAttribute("method3"); System.out.println(method3); String name = request.getParameter("name"); System.out.println(name); } // 3. 返回字符串 @RequestMapping("method3") public String method3(HttpServletRequest request){ /** * 返回逻辑视图名 * controller方法返回字符串可以指定逻辑视图名 * 通过视图解析为物理视图地址 * * */ // 转发操作 request.setAttribute("method3","转发到另一个"); return "method1"; //转发跳转到页面 return "forward:/return/method2"; // 转发到另一个controller return "redirect:/return/method2?name=zsss"; // 重定向到另一个controller }

    八、拦截器

    * 8. 拦截器 interceptor * 在controller之后view视图解析之前执行 * 过滤器和拦截器的区别 * 1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。 * 2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。 * 3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。 * 4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。 * 5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 * * |-- 拦截器配置 * |-- 编写拦截器类,实现HandlerInterceptor接口,重写方法 * |-- springmvc.xml中配置拦截器 * <!-- 配置拦截器 --> * <mvc:interceptors> * <mvc:interceptor> * <!-- 匹配url路径,如果不配置或者 设置为 "/**" 将拦截所有controller --> * <mvc:mapping path="/**"/> * <!-- 不拦截登录请求 --> * <!--<mvc:exclude-mapping path="/login"/>--> * <bean class="com.lyzzz.interceptor.MyInterceptor"/> * </mvc:interceptor> * <!-- 当设置多个拦截器时,先按顺序调用preHandler方法 * 然后逆序调用每个拦截器的postHandler和afterCompletion方法--> * </mvc:interceptors> * |-- preHandle() * 在控制器方法调用前执行,返回值为是否中断 * true表示继续执行 * false则会中断后续的所有操作,所以我们使用response来继续响应后续请求 * * |-- postHandle() * 在控制器方法调用后,解析视图前调用 * 可以对模型和视图进一步进行修改或渲染 * 可在ModelAndView中加入数据,比如当前时间 * * |-- afterCompletion() * 整个请求完成,即视图渲染结束后调用, * 可做资源清理工作,或日志记录

    九、异常机制

    Processed: 0.014, SQL: 12