美文网首页
21.SpringMVC

21.SpringMVC

作者: 星野君 | 来源:发表于2022-05-04 14:44 被阅读0次

一、快速入门

  • xml方式:
  1. 导入坐标
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>80</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
  1. 在web.xml里配置前端控制器
    <!--SpringMVC的前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--加载第四步的spring-mvc.xml文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  1. 创建controller
package com.ylf.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller // 把UserController放在spring容器
public class UserController {
  @RequestMapping("/index") // 请求映射
  public String save() {
    System.out.println("save running...");
    return "index.jsp"; // 跳转的jsp地址
  }
}

4.创建spring-mvc.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--controller包扫描-->
    <context:component-scan base-package="com.ylf.controller"></context:component-scan>
</beans>
  • 注解方式(推荐):
  1. 导入坐标同上
  2. 创建SpringMvcConfig配置类
package com.ylf.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.ylf.controller")
public class SpringMvcConfig {}

  1. 创建ServletContainersIntiConfig配置类
package com.ylf.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

public class ServletContainersIntiConfig
    extends AbstractAnnotationConfigDispatcherServletInitializer {
  //加载Spring容器
  @Override
  protected Class<?>[] getRootConfigClasses() {
    return new Class[] {SpringConfig.class};
  }
  // 加载SpringMvc容器
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class[] {SpringMvcConfig.class};
  }
  // 所有请求都归SpringMvc处理
  @Override
  protected String[] getServletMappings() {
    return new String[] {"/"};
  }
}

  1. 创建controller
package com.ylf.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
  @RequestMapping("/save")
  @ResponseBody
  public String save() {
    return "{'info':'xxx'}";
  }
}

二、SpringMVC执行流程

  1. 工作原理图


    image.png
  2. springmvc工作流程
    1、 用户向服务端发送一次请求,这个请求会先到前端控制器DispatcherServlet(也叫中央控制器)。
    2、DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器。由此得知,该请求该由哪个Controller来处理(并未调用Controller,只是得知)
    3、DispatcherServlet调用HandlerAdapter处理器适配器,告诉处理器适配器应该要去执行哪个Controller
    4、HandlerAdapter处理器适配器去执行Controller并得到ModelAndView(数据和视图),并层层返回给DispatcherServlet
    5、DispatcherServlet将ModelAndView交给ViewReslover视图解析器解析,然后返回真正的视图。
    6、DispatcherServlet将模型数据填充到视图中
    7、DispatcherServlet将结果响应给用户

  3. 组件说明

  • DispatcherServlet:前端控制器,也称为中央控制器,它是整个请求响应的控制中心,组件的调用由它统一调度。
  • HandlerMapping:处理器映射器,它根据用户访问的 URL 映射到对应的后端处理器 Handler。也就是说它知道处理用户请求的后端处理器,但是它并不执行后端处理器,而是将处理器告诉给中央处理器。
  • HandlerAdapter:处理器适配器,它调用后端处理器中的方法,返回逻辑视图 ModelAndView 对象。
  • ViewResolver:视图解析器,将 ModelAndView 逻辑视图解析为具体的视图(如 JSP)。
  • Handler:后端处理器,对用户具体请求进行处理,也就是我们编写的 Controller 类。

三、注解解析

  1. @RequestMapping:
    作用:用于建立请求url和处理请求方法之间的对应关系
    位置:类上,请求访问url的第一级访问目录,此处不写就相当于应用的根目录。方法上,请求url的第二级访问目录,与类上使用@RequestMapping标注的一级目录组成访问目录如/user/xxx
    属性:
    value,用于指定请求的url,它和path的属性一样。
    mathod,用于指定请求的方式,比如:method=RequestMethod.POST。
    params,用于指定限制请求参数的条件,它支持简单的表达式,要求请求参数的key和value必须和配置的一样。

四、bean加载控制
为了避免spring加载到本应该由SpringMVC加载的内容
SpringMVCConfig

//根据注解排除,controller
@ComponentScan(
    value = "com.ylf",
    excludeFilters =
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class))

或者直接精确包扫描
五、数据响应和数据请求

  1. 乱码处理:
    在ServletContainersIntiConfig配置类
  //乱码处理
  @Override
  protected Filter[] getServletFilters() {
    final CharacterEncodingFilter filter = new CharacterEncodingFilter();
    filter.setEncoding("utf-8");
    return new Filter[]{filter};
  }
  1. 参数传递
  // 普通参数
  @RequestMapping("/save")
  @ResponseBody
  public String save(String name) {
    System.out.println(name);
    return "{'info':'ok'}";
  }
  // pojo参数
  @RequestMapping("/add")
  @ResponseBody
  public String add(User user) {
    System.out.println(user);
    return "{'info':'ok'}";
  }

  // 数组参数
  @RequestMapping("/arrayParam")
  @ResponseBody
  public String arrayParam(String[] likes) {
    System.out.println(likes);
    return "{'info':'ok'}";
  }

  // 集合参数
  @RequestMapping("/listParam")
  @ResponseBody
  public String arrayParam(@RequestParam ArrayList<String> likes) {
    System.out.println(likes);
    return "{'info':'ok'}";
  }
  1. json参数传递
  • 第一步导入坐标
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
  • 在SpringMvcConfig加上
@EnableWebMvc
public class SpringMvcConfig {}
  • 获得参数
  // json参数
  @RequestMapping("/jsonParam")
  @ResponseBody
  public String jsonParam(@RequestBody User user) {
    System.out.println(user);
    return "{'info':'ok'}";
  }

  // json参数
  @RequestMapping("/jsonListParam")
  @ResponseBody
  public String jsonListParam(@RequestBody List<User> user) {
    System.out.println(user);
    return "{'info':'ok'}";
  }

  // 日期参数
  @RequestMapping("/dateParam")
  @ResponseBody
  public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date) {
    System.out.println(date);
    return "{'info':'ok'}";
  }
  1. 数据响应
  // 返回json对象
  @RequestMapping("/toJson")
  @ResponseBody
  public User toJson(){
    final User user = new User();
    user.setId(1);
    user.setName("张三");
    return user;
  }

  // 返回json集合对象
  @RequestMapping("/toListJson")
  @ResponseBody
  public List<User> toListJson(){
    final User user1 = new User();
    user1.setId(1);
    user1.setName("张三");
    final User user2 = new User();
    user2.setId(1);
    user2.setName("李四");
    final List<User> users = new ArrayList<User>();
    users.add(user1);
    users.add(user2);
    return users;
  }
  1. rest风格
// @RestController等于@Controller和@ResponseBody
@RestController
@RequestMapping("/users")
public class UserController {
  // 普通参数
  @RequestMapping(value = "/{id}",method = RequestMethod.POST)
  public String save(@PathVariable Integer id) {
    System.out.println(id);
    return "{'message':'ok'}";
  }
}
  // @PostMapping 相当于@RequestMapping(method = RequestMethod.POST)
  @PostMapping
  public String save(){
    return "{'message':'ok'}";
  }

  // @DeleteMapping 相当于@RequestMapping(value = "/{id}",method = RequestMethod.Delete)
  @DeleteMapping("/{id}")
  public String delete(){
    return "{'message':'ok'}";
  }
  1. 拦截器
  • 创建controller.interceptor.ProjectInterceptor
package com.ylf.controller.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ProjectInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    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");
  }
}

  • 创建config.SpringMvcSupport
package com.ylf.config;

import com.ylf.controller.interceptor.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
  @Autowired private ProjectInterceptor projectInterceptor;

  /**
   * SpringMVC不去拦截pages页面
   *
   * @param registry
   */
  @Override
  protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
  }

  /**
   * 拦截/students下的所有请求
   *
   * @param registry
   */
  @Override
  protected void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(projectInterceptor).addPathPatterns("/students");
  }
}

  • 在SpringMvc下加载SpringMvcSupport
@Configuration
@ComponentScan({"com.ylf.controller", "com.ylf.config"})
@EnableWebMvc
public class SpringMvcConfig {}
  • 或者直接在SpringMvcConfig下实现WebMvcConfigurer接口,这样就不用去创建新的配置类
package com.ylf.config;

import com.ylf.controller.interceptor.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@ComponentScan({"com.ylf.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
  @Autowired private ProjectInterceptor projectInterceptor;
  /**
   * 拦截/students下的所有请求
   *
   * @param registry
   */
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(projectInterceptor).addPathPatterns("/students/*");
  }
  /**
   * SpringMVC不去拦截pages页面
   *
   * @param registry
   */
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
  }
}

相关文章

  • 21.SpringMVC

    一、快速入门 xml方式: 导入坐标 在web.xml里配置前端控制器 创建controller 4.创建spri...

网友评论

      本文标题:21.SpringMVC

      本文链接:https://www.haomeiwen.com/subject/ioagertx.html