1.2(Spring MVC学习笔记) Spring MVC核心类及注解

一、DispatcherServlet

  DispatcherServlet在程序中充当着前端控制器的作用,使用时只需在web.xml下配置即可。

  配置格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="true">
  <display-name>SpringMVC</display-name>
  
  <!-- 配置前端控制器 -->
  <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class >
          org.springframework.web.servlet.DispatcherServlet
      </servlet-class> 
      <!-- 初始化时加载配置文件,该配置文件是在src目录下创建的。 -->
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springmvc-config.xml</param-value>
      </init-param>
      <!-- 当前servlet与容器一起加载 -->
      <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 所有请求都会被前端控制器拦截-->
  <servlet-mapping>
      <servlet-name>springmvc</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

其中<init-param>和<load-on-startup>是可选项.

如果<init-param>配置了xml文件的路径,则容器加载时会去指定路径加载文件。

如果没有配置则会在WEB-INF目录下选择命名格式为servletName-servlet.xml的文件。

servletName是我们配置的前端控制器的<servlet-name>,本例为springmvc,则会寻找springmvc-servlet.xml。

<load-on-startup>配置为1,代表当前Servlet在容器启动时加载。

如果没有配置,则在请求该Servelt时才对其进行加载。

二、Controller注解

  在控制类可以通过实现Controller接口,也可以通过注解来实现。

  通过注解实现只需要在控制类上添加@Controller注解即可。

  添加注解后再xml中可通过扫描语句进行扫描。

  扫描语句:<context:component-scan base-package = "指定包" />

  

三、RequestMapping注解

  3.1Spring通过@Controller注解找到控制器类后,还需将请求映射到具体的处理程序。

  RequesMapping注解就是用于映射请求。

  例如:

public class FirstController{
    @RequestMapping(value = "/firstController")
    public String handleRequest(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        model.addAttribute("msg", "hello SpringMVC");
        return "first";
    }
}

上例中间/firstController这个请求映射到handleRequest方法。

在浏览器地址栏输入localhost:8080/SpringMVC/firstController就可以了调用handleRequest方法。

  @RequestMapping注解也可以映射到类上。

@RequestMapping(value = "/hello")
public class FirstController{
    @RequestMapping(value = "/firstController")
    public String handleRequest(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        model.addAttribute("msg", "hello SpringMVC");
        return "first";
    }
}

  映射在类上时,要想访问类中的方法必须加上类的映射请求路径。

  例如想访问handleRequest方法,完整路径为:localhost:8080/SpringMVC/hello/firstController

  

  value属性除了上述直接表示一个固定路径外,还有以下写法:

  

  3.2指定变量和值  {变量}

  例如

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

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(value = "/hello")
public class FirstController{
    @RequestMapping(value = "/firstController/{id}")//指定变量
    public String handleRequest(@PathVariable String id ,HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        
        System.out.println("into mv");
        System.out.println(id);
        model.addAttribute("msg", "hello SpringMVC");
        return "first";
    }
}

在地址栏输入loaclhost:8080/SpringMVC/hello/firsstController/xx,才能访问指定路径所映射的方法。

而xxx可以被@pathVariable String id 中的id获取,形参名xx和路径{xx}中的名称要一致。如果没有/xxx则出现404页面。

  3.3指定变量和正则表达式 ({变量:正则表达式})

  例如将RequestMapping改为:@RequestMapping(value = "/firstController/{id:\\d}")

  \\代表\,正则\d中\d代表0-9任意一个数字,这样配置后:

  /firstController/0-9任意一个数字可以访问成功(注意是一个数字,多个不符合条件),且可以通过@pathVariable获取id的值。

  /firstController/0-9之外的字符或多个数字(大于1个),访问失败,出现404页面。

  

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

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(value = "/hello")
public class FirstController{
        //末尾加上任意一位数字访问成功,反正失败
    @RequestMapping(value = "/firstController/{id:\\d}")
    public String handleRequest(@PathVariable String id ,HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("into mv");
        System.out.println(id);
        model.addAttribute("msg", "hello SpringMVC");
        return "first";
    }
}    

访问失败:

 访问成功:

   RequestMapping中还有一个属性method,用于指定处理何种类型的请求方法。

  例如@RequestMapping(value = "/firstController/{id:\\d}" ,method = RequestMethod.POST)处理POST类型的请求

    @RequestMapping(value = "/firstController/{id:\\d}" ,method = RequestMethod.GET)处理GET类型的请求

  我们来看一个例子

@Controller
@RequestMapping(value = "/hello")
public class FirstController{
    @RequestMapping(value = "/firstController/{id:\\d}" ,method = RequestMethod.POST)//处理POST类型请求
    public String handleRequest(@PathVariable String id ,HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("into mv");
        System.out.println(id);
        model.addAttribute("msg", "hello SpringMVC");
        return "first";
    }
}

  我们将方法设置为处理POST类型请求,使用GET类型的请求去访问会出现不支持GET类型的请求方法。

  method可以设置多个值,中间用“,”隔开@RquestMapping(method = {xxx.GET,xx.xPOST})

  Spring4.3中又引入了组合注解,例如上例中的@RequestMapping(method = Request.GET)可以简化为:

  GetMapping(),从字面上可以看出这个注解是包含了GET和Mapping。处理Get类型的请求映射。

  除此之外,还有一些组合注解:

  PostMapping,PutMapping,DeleteMapping,PatcherMapping.

  

  params属性:指定请求中必须包含、不包含某些参数、或者指定某些参数名和值要对应,才能被当前方法处理。

  例如params = {"name"} 代表请求中要包含name参数。例如:localhost:8080/SpringMVC/hello/firstController/1?name=hcf;

  这样的就可以正确访问指定的方法,反之不行。

  params={“!name”}代表请求中不包含name参数可以正确访问,反正不行。

  params={"name = hcf"},代表请求参数name要和指定的值匹配才可以正常访问,反正不行。例如

  localhost:8080/SpringMVC/hello/firstController/1?name=hcf;可以访问,

  localhost:8080/SpringMVC/hello/firstController/1?name=h;就不能访问。

  

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

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value = "/hello")
public class FirstController{//请求参数name为“hcf”才能访问
    @RequestMapping(value = "/firstController/{id:\\d}" ,method = {RequestMethod.POST,RequestMethod.GET},params = {"name=hcf"})
    public String handleRequest(@PathVariable String id ,HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("into mv");
        System.out.println(id);
        model.addAttribute("msg", "hello SpringMVC");
        return "first";
    }
}

访问成功:

访问失败:

四、请求处理方法类型和返回值。

  支持的请求参数类型

  Request or response objects (Servlet API).

  Session object (Servlet API)

  org.springframework.web.context.request.WebRequest or org.springframework.web.context.request.NativeWebRequest

  java.util.Locale

  java.util.TimeZone (Java 6+) / java.time.ZoneId (on Java 8) 

   java.io.InputStream / java.io.Reader

  java.io.OutputStream / java.io.Writer

   org.springframework.http.HttpMethod

  java.security.Principal

  @PathVariable

  @RequestParam

  @RequestHeader

  @RequestBody

  @RequestPart

  @SessionAttribute

  @RequestAttribute

  HttpEntity<?>

  java.util.Map / org.springframework.ui.Model / org.springframework.ui.ModelMap

  org.springframework.web.servlet.mvc.support.RedirectAttributes

  org.springframework.validation.Errors / org.springframework.validation.BindingResult

  org.springframework.web.bind.support.SessionStatus

  org.springframework.web.util.UriComponentsBuilder

  这些是方法参数支持的类型,

  例如上例中的:

  public String handleRequest(@PathVariable String id ,HttpServletRequest request, HttpServletResponse response, Model model) throws Exce

    参数类型都是受支持的参数类型。

  支持的返回类型:

  

     上例子中的返回值为“first”,返回字符串被解释为逻辑视图名。

  (返回first对应为/WEB-INF/jsp/first.jsp,这是因为在视图解析器中设置了前缀和后缀,后续会有具体使用方法)

五、视图解析器(ViewResolver)

  视图解析器将DispatcherServlet中的view参数传递给视图解析器,视图解析器将解析的视图传递给DispatcherServlet。

  在视图解析中,可以设置前缀和后缀。

  例如我们设置前缀为“/WEB-INF/jsp/”,后缀设置为“.jsp”。

  以前面的Controller类为例,Controller执行完后将“first”返回给HandlerAdapter,然后返回DispathcerServlet。

  DispatcherServlet将“first”交给视图解析器,视图解析器将“first”添加前缀和后缀,变成“/WEB-INF/jsp/first.jsp”.

  然后解析指定路径视图将视图返回给DispatcherServlet。

  我们来看下前缀与后缀的具体设置:

<bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">  <!-- 视图解析器-->        
                 <!--设置前缀-->
           <property name="prefix" value = "/WEB-INF/jsp/"></property>
                 <!--设置后缀-->
           <property name="suffix" value = ".jsp"></property>
       </bean>

最后结合上述,使用注解实现SpringMVC

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="true">
  <display-name>SpringMVC</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置前端控制器 -->
  <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class >
          org.springframework.web.servlet.DispatcherServlet
      </servlet-class> 
      
      <!-- 初始化时加载配置文件,该配置文件是在src目录下创建的。 -->
      <!-- <init-param>  该选项不配做会自动寻找WEB-INF下名为springmvc-servlet.xml的文件。--> 
      <!--    <param-name>contextConfigLocation</param-name>-->
      <!--    <param-value>classpath:springmvc-config.xml</param-value>-->
      <!--</init-param>-->
      <!-- 当前servlet与容器一起加载 -->
      <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 所有请求都会被前端控制器拦截-->
  <servlet-mapping>
      <servlet-name>springmvc</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

Controller类

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

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value = "/hello")
public class FirstController{
    @RequestMapping(value = "/firstController/{id:\\d}" ,method = {RequestMethod.POST,RequestMethod.GET},params = {"name=hcf"})
    public String handleRequest(String name ,HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("into mv");
        name = request.getParameter("name");
        System.out.println(name);
        //返回类型为String会被解释为逻辑视图名View就解决了。
        //Model交由Model对象来完成。
        model.addAttribute("msg", "hello  SpringMVC");
        return "first";
    }
}

springmvc-servlet.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-4.3.xsd 
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.3.xsd"> 
       <!-- 开启扫描 -->
       <context:component-scan base-package = "com.springmvc.firstmvc"></context:component-scan>    
       <!-- 配置处理器(Handle),映射/firstController请求 (Controller类),已由注解完成-->
       <!-- <bean name = "/firstController" class = "com.springmvc.firstmvc.FirstController"/> -->
       <!-- 配置映射处理器(handlerMapping) 将处理器(Handle)的name作为url进行查找(Spirng4.0以后无需配置) -->
       <!-- 配置适配处理器(HandlerAdapter) 适配处理器会调用处理器(Handle)即FirstController类(Spirng4.0以后无需配置) -->
       <!-- 处理器会返回一个ModelAndView,适配处理器将返回的ModelAndView交给前端控制器去处理了 -->
       <!-- 前端控制器根据ModelAndView中的View选择一个视图解析器(ViewReslover) -->
       <!-- 前端控制器将Model(msg "hello SpringMVC")填充进视图解析器返回的视图,用户看到最后页面 -->
       <!-- 设置视图处理器及其前缀后缀 -->
       <bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
           <property name="prefix" value = "/WEB-INF/jsp/"></property>
           <property name="suffix" value = ".jsp"></property>
       </bean>
       <!-- 视图处理器解析后会将视图传递给前端控制器,前端控制对View进行渲染(将模型数据填入视图) -->
       <!-- 渲染结果会返回客户端浏览器显示 -->
</beans>

WEB-INF/jsp/first.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    ${msg}
</body>
</html>

 

可以看到加载的是springmvc-servlet.xml

 如果firstController/后面不是一位数字,或者name不等于hcf都会出现404页面。

完整结构:

 

参考资料:

SpringFramework/spring-framework-4.3.6.RELEASE/docs/spring-framework-reference/html/mvc.html

https://www.cnblogs.com/qq78292959/p/3760560.html 

猜你喜欢

转载自www.cnblogs.com/huang-changfan/p/10398369.html