SpringMVC

1 什么是SpringMVC

1.1 什么是MVC

  • MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范
    • Model(模型):数据模型、提供要展示的数据,因此包含数据和行为,可以认为是领域模块或JavaBean
    • View(视图):负责进行模型的展示,一般就是我们见到的用户界面
    • Controller(控制器):接收用户请求,委托给模型进行处理,处理完后把返回的模型数据返回给视图,由视图负责展示
  • 用将业务逻辑、数据、显示分离的方法来组织代码
  • MVC主要作用是降低了视图与业务逻辑间的双向耦合
  • MVC是一种架构模式

image-20200811220045716.png

1.2 SpringMVC概述

SpringMVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。

SpringMVC的特点:

  • 轻量级,简洁灵活,简单易学
  • 高效,基于请求响应的MVC框架
  • 与Spring兼容性好,无缝结合
  • 约束优于配置
  • 功能强大:Restful、数据验证、格式化、本地化、主题等

SpringMVC框架围绕DispatcherServlet(调度Servlet)设计,DispatcherServlet的作用是将请求分发到不同的处理器。

1.3 SpringMVC执行原理

image-20200811223030686.png
执行流程:

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
    例如url为:http://localhost:8080/SpringMVC/hello
  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping。HandlerMapping根据请求的url来查找Handler。
  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器。
  4. HandlerExecution将解析后的信息传递给DispatcherServlet。
  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
  6. Handler让具体的Controller执行。
  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
  12. 最终视图呈现给用户。

2 实现SpringMVC操作

2.1 原理版(理解)

  1. 导入SpringMVC、servlet、jsp等依赖包
  2. 配置web.xml,注册DispatcherServlet

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    5. version="4.0">
    6. <!-- 注册DispatcherServlet -->
    7. <servlet>
    8. <servlet-name>springmvc</servlet-name>
    9. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    10. <!-- 关联一个springMVC的配置文件 -->
    11. <init-param>
    12. <param-name>contextConfigLocation</param-name>
    13. <param-value>classpath:springmvc-servlet.xml</param-value>
    14. </init-param>
    15. <!-- 配置启动级别:1 -->
    16. <load-on-startup>1</load-on-startup>
    17. </servlet>
    18. <!--
    19. / 匹配所有请求,不包括.jsp文件
    20. /* 匹配所有请求,包括.jsp文件
    21. -->
    22. <servlet-mapping>
    23. <servlet-name>springmvc</servlet-name>
    24. <url-pattern>/</url-pattern>
    25. </servlet-mapping>
    26. </web-app>
  3. 编写SpringMVC配置文件

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. http://www.springframework.org/schema/beans/spring-beans.xsd">
    6. </beans>
  4. 添加处理映射器

    1. <!-- 配置处理映射器 -->
    2. <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
  5. 添加处理器适配器

    1. <!-- 配置处理器适配器 -->
    2. <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
  6. 添加视图解析器

    1. <!-- 配置视图解析器:DispatcherServlet给他的ModelAndView -->
    2. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    3. <!-- 前缀:prefix -->
    4. <property name="prefix" value="/WEB-INF/jsp/"/>
    5. <!-- 后缀:suffix -->
    6. <property name="suffix" value=".jsp"/>
    7. </bean>
  7. 编写操作业务的Controller,实现Controller接口,需要返回一个ModelAndView,装数据,封视图

    1. public class HelloController implements Controller {
    2. public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    3. // ModeAndView 模型和视图
    4. ModelAndView view = new ModelAndView();
    5. // 处理业务层代码
    6. String message = "HelloSpringMVC";
    7. view.addObject("msg", message);
    8. // 跳转或重定向页面
    9. view.setViewName("hello");
    10. return view;
    11. }
    12. }
  8. 将实现了Controller接口的类注入到Spring,注册bean

    1. <!-- 配置视图名字,即BeanNameUrlHandlerMapping需要controller类的注入 -->
    2. <!-- Handler -->
    3. <bean id="/hello" class="com.falshce.controller.HelloController"/>
  9. 编写跳转的jsp页面,显示存放的数据

2.1 注解版(常用)

  1. 配置web.xml

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    5. version="4.0">
    6. <servlet>
    7. <servlet-name>springmvc</servlet-name>
    8. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    9. <init-param>
    10. <param-name>contextConfigLocation</param-name>
    11. <param-value>classpath:springmvc-servlet.xml</param-value>
    12. </init-param>
    13. <load-on-startup>1</load-on-startup>
    14. </servlet>
    15. <servlet-mapping>
    16. <servlet-name>springmvc</servlet-name>
    17. <url-pattern>/</url-pattern>
    18. </servlet-mapping>
    19. </web-app>
  2. 添加SpringMVC配置文件

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xmlns:mvc="http://www.springframework.org/schema/mvc"
    6. xsi:schemaLocation="http://www.springframework.org/schema/beans
    7. http://www.springframework.org/schema/beans/spring-beans.xsd
    8. http://www.springframework.org/schema/context
    9. https://www.springframework.org/schema/context/spring-context.xsd
    10. http://www.springframework.org/schema/mvc
    11. https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    12. <context:component-scan base-package="com.falsche.controller"/>
    13. <!-- 让SpringMVC不处理静态资源,例如html,js,css等 -->
    14. <mvc:default-servlet-handler/>
    15. <!--
    16. 1、支持mvc注解驱动,使springmvc的注解生效
    17. 例如:@RequestMapping,用来完成映射关系
    18. 2、annotation-driven会自动完成
    19. DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter的注册
    20. -->
    21. <mvc:annotation-driven/>
    22. <!-- 视图解析器 -->
    23. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    24. <property name="prefix" value="/WEB-INF/jsp/"/>
    25. <property name="suffix" value=".jsp"/>
    26. </bean>
    27. </beans>
    1. 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。

      • 让IOC的注解生效
      • 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …..
      • MVC的注解驱动
      • 配置视图解析器
  3. 创建一个控制类,使用@Controller实现

    1. @Controller
    2. public class ControllerTest1 {
    3. @RequestMapping("/h1")
    4. public String hello(@Nullable Model model){
    5. model.addAttribute("msg", "HelloSpringMVC_Annotation");
    6. return "hello";
    7. }
    8. }
    • @Controller是为了让SpringIOC容器初始化时扫描到
    • @RequestMapping是为了映射请求路径
    • 方法中声明Model类型的参数是为了把Action中的数据带到视图中
    • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
  4. 编写跳转的jsp页面,显示存放的数据

3 RestFul风格

POST、GET、DELETE、PUT不同的请求方式


4 数据处理

4.1 前端提交数据到后端

  1. 提交的数据名称和处理方法的参数名一致
    可以直接在方法参数中定义。例如:提交数据为 http://localhost:8080/hello?name=xxx

    1. @RequestMapping("/hello")
    2. public String hello(String name){
    3. return "hello";
    4. }
  2. 提交的数据名称和处理方法的参数名不一致
    例如:提交数据为 http://localhost:8080/hello?username=xxx

    1. @RequestMapping("/hello")
    2. public String hello(@RequestParam("username") String name){
    3. return "hello";
    4. }
  3. 提交的数据是一个对象,比如User对象

4.2 数据显示到前端

  1. 通过该ModelAndView
  2. 通过ModelMap
  3. 通过Model

对比:

  • Model是精简版。(大部分情况用Model)
  • ModelMap继承了LinkedMap。
  • ModelAndView可以在储存数据的同时,也可以进行设置返回的逻辑视图,进行控制展示层的跳转。(原理)

4.3 解决乱码问题

使用SpringMVC自带的过滤器,可以解决大部分乱码问题。

  1. <filter>
  2. <filter-name>encoding</filter-name>
  3. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  4. <init-param>
  5. <param-name>encoding</param-name>
  6. <param-value>utf-8</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>encoding</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>

5 JSON

5.1 什么是JSON

  • JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式。
  • 采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得JSON成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,有效地提升网络传输效率

语法和格式要求:

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

5.2 JSON和JavaScript对象互转

  1. // 把JavaScript对象转换成JSON字符串,使用JSON.stringify()方法
  2. var json = JSON.stringify(user);
  3. // 把JSON字符串转换为JavaScript对象,使用JSON.parse()方法
  4. var parse = JSON.parse(json);

5.3 JSON和Java对象互转(基于fastjson)

fastjson三个主要类:

JSONObject 代表 json 对象

  • JSONObject 实现了 Map 接口。
  • JSONObject 对应 json 对象,通过各种形式的 get() 方法可以获取 json 对象中的数据,也可利用诸如 size() ,isEmpty() 等方法获取”键:值”对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。

JSONArray 代表 json 对象数组

  • 内部是有 List 接口中的方法来完成操作的。

JSON 代表 JSONObject 和 JSONArray 的转化

  • JSON 类源码分析与使用。
  • 主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
  1. 在Controller中,Java转JSON

    • @Controller和@ResponseBody,使这个方法不走视图解析器
    • @RestController,使用这个注解就可以不用@Controller和@ResponseBody了

      1. @RequestMapping("/json")
      2. @ResponseBody // @ResponseBody不会走视图解析器,会直接返回一个字符串
      3. public String json() throws JsonProcessingException {
      4. System.out.println("*******Java对象 转 JSON字符串*******");
      5. String str1 = JSON.toJSONString(list);
      6. System.out.println("JSON.toJSONString(list)==>"+str1);
      7. String str2 = JSON.toJSONString(user1);
      8. System.out.println("JSON.toJSONString(user1)==>"+str2);
      9. System.out.println("\n****** Java对象 转 JSON对象 ******");
      10. JSONObject object = (JSONObject) JSON.toJSON(user2);
      11. System.out.println("(JSONObject) JSON.toJSON(user2)==>" + object.getString("name"));
      12. }
  2. JSON转Java

    1. System.out.println("\n****** JSON字符串 转 Java对象*******");
    2. User jp_user1=JSON.parseObject(str2,User.class);
    3. System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
    4. System.out.println("\n****** JSON对象 转 Java对象 ******");
    5. User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
    6. System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);

5.4 SpringMVC中JSON乱码问题(jackson)

  1. <!--jackson -->
  2. <dependency>
  3. <groupId>com.fasterxml.jackson.core</groupId>
  4. <artifactId>jackson-databind</artifactId>
  5. <version>2.9.5</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.fasterxml.jackson.core</groupId>
  9. <artifactId>jackson-annotations</artifactId>
  10. <version>2.9.5</version>
  11. </dependency>
  1. <!-- JSON解决乱码问题 -->
  2. <mvc:annotation-driven>
  3. <mvc:message-converters register-defaults="true">
  4. <bean class="org.springframework.http.converter.StringHttpMessageConverter">
  5. <constructor-arg value="UTF-8"/>
  6. </bean>
  7. <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  8. <property name="objectMapper">
  9. <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
  10. <property name="failOnEmptyBeans" value="false"/>
  11. </bean>
  12. </property>
  13. </bean>
  14. </mvc:message-converters>
  15. </mvc:annotation-driven>

6 Ajax

6.1 Ajax传值给Controller

无论Ajax以什么形式发送数据,在Controller中的接收方法都没有差异

对象 操作 key/value类型 JSON 序列化表单
Ajax 发送 data: ‘name=’+name data: {‘name’: name} data:$(“#form”).serialize()
Controller 接收 public void receive(String name) / (User user) public void receive(String name) / (User user) public void receive(String name) / (User user)

6.2 Controller返回值给Ajax

  • Controller返回json类型的数据需要加@RespsonseBody注解
  • Ajax的返回值data可以是任何名称 | 对象 | 操作 | JSON | JSON | | :—-: | :—-: | :—-: | :—-: | | | | pojo类型 | map类型 | | Controller | 发送 | return Msg; | return map; | | Ajax | 接收 | success:function(data){ alert(data.result) | success:function(data){ alert(data.result) |

7 拦截器

想要自定义拦截器,必须实现 HandlerInterceptor 接口。

  1. 创建一个拦截器

    1. public class MyInterceptor implements HandlerInterceptor {
    2. //在请求处理的方法之前执行
    3. //如果返回true执行下一个拦截器
    4. //如果返回false就不执行下一个拦截器
    5. public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    6. System.out.println("------------处理前------------");
    7. return true;
    8. }
    9. //在请求处理方法执行之后执行
    10. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    11. System.out.println("------------处理后------------");
    12. }
    13. //在dispatcherServlet处理后执行,做清理工作.
    14. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    15. System.out.println("------------清理------------");
    16. }
    17. }
  2. 在springmvc的配置文件中配置拦截器

    1. <!--关于拦截器的配置-->
    2. <mvc:interceptors>
    3. <mvc:interceptor>
    4. <!--/** 包括路径及其子路径-->
    5. <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
    6. <!--/admin/** 拦截的是/admin/下的所有-->
    7. <mvc:mapping path="/**"/>
    8. <!--bean配置的就是拦截器-->
    9. <bean class="com.kuang.interceptor.MyInterceptor"/>
    10. </mvc:interceptor>
    11. </mvc:interceptors>


@RequestParam注解

1、可以对传入参数指定参数名

  1. 1 @RequestParam String inputStr
  2. 2 // 下面的对传入参数指定为aa,如果前端不传aa参数名,会报错
  3. 3 @RequestParam(value="aa") String inputStr

2、可以通过required=false或者true来要求@RequestParam配置的前端参数是否一定要传

  1. 1 // required=false表示不传的话,会给参数赋值为null,required=true就是必须要有
  2. 2 @RequestMapping("testRequestParam")
  3. 3 public String filesUpload(@RequestParam(value="aa", required=true) String inputStr, HttpServletRequest request)

3、如果@requestParam注解的参数是int类型,并且required=false,此时如果不传参数的话,会报错。原因是,required=false时,不传参数的话,会给参数赋值null,这样就会把null赋值给了int,因此会报错。

  1. 1 // required=false表示不传的话,会给参数赋值为null,required=true就是必须要有
  2. 2 @RequestMapping("testRequestParam")
  3. 3 public String filesUpload(@RequestParam(value="aa", required=false) int inputStr, HttpServletRequest request)
  4. 4 若是前端页面不传参的话,此处就会报错。当然可以用Integer代替int