SpringMVC基本知识点

2021-06-17 16:47:22 浏览数 (1)

# SpringMVC

# hello world

1.加入Jar包

2.在web.xml中配置DispathcherServlet

3.加入SpringMVC的配置文件

4.编写处理请求的处理器,并标识为处理器

5.编写视图

代码语言:javascript复制
<?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_4_0.xsd"
         version="4.0">
    <!--配置DispatcherServlet-->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--配置DispatcherServlet的一个初始化参数:配置Springmvc配置文件位置和名称-->
        <!--
            实际上也可以不通过contextConfigLocation来配置SpringMVC的配置文件,而使用默认的。
            默认配置文件为:/WEB-INF/<servlet-name>-servlet.xml
        -->
        <!--
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
代码语言:javascript复制
<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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-4.0.xsd
      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
    <context:component-scan base-package="top.finen.springmvc"></context:component-scan>

    <!--配置视图解析器,如何把handler方法返回值解析为实际的物理视图-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>


</beans>
代码语言:javascript复制
package top.finen.springmvc.handlers;

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

@Controller
public class HelloWorld {
    /**
     * 1. 使用 @RequestMapping 注解来映射请求的 URL
     * 2. 返回值会通过视图解析器解析为实际的物理视图, 对于 InternalResourceViewResolver 视图解析器, 会做如下的解析:
     * 通过 prefix   returnVal   后缀 这样的方式得到实际的物理视图, 然会做转发操作
     *
     * /WEB-INF/views/success.jsp
     *
     * @return
     */
    @RequestMapping("helloworld")
    public String hello(){
        System.out.println("hello world");
        return "success";
    }
}
# @RequestMapping映射请求

在控制器的类定义以及方法定义出都可以标注

@RequestMapping

-类定义处:提供初步的请求映射信息,相对于WEB应用的根目录。

**-方法处:**提供进一步的细分映射信息,若未定义类标注,则直接标记URL相对于WEB应用的根目录。

DispatcherServlet截获请求后,就通过控制器上@RequestMapping提供的映射信息确定请求所处的处理方法。

代码语言:javascript复制
/**
 * 1. @RequestMapping 除了修饰方法,还可以修饰类
 * 2.
 *  1).类定义处:提供初步的请求映射信息,相对于WEB应用的根目录。
 *  2).方法处:提供进一步的细分映射信息。
 *  相对于类定义处的URL,若类定义处未标注 @RequestMapping,则方法标记处的URL相对于WEB应用的根目录。
 * @return
 */
@RequestMapping("/testRequestMapping")
public String testRequestMapping() {

    System.out.println("testRequestMapping");
    return SUCCESS;
}

/**
 * 使用method属性来指定请求方式
 * @return
 */
@RequestMapping(value = "/testMethod", method = RequestMethod.POST)
public String testMethod() {
    System.out.println("testMethod");
    return SUCCESS;
}
# 映射请求参数、请求方法或者请求头

@RequestMapping除了 可以使用请求URL映射请求外,还可以使用请求方法,请求参数以及请求头映射请求。

@RequestMapping的value,method,param以及heads分别表示请求URL,请求方法,请求参数以及请求头的映射条件。他们之间是与的关系。联合使用多个条件可让请求映射更加精确化。

  • Ant风格资源地址支持三种匹配符: ?:匹配文件名中一个字符 *:匹配文件中任意字符 ** : ** 匹配多层路径
代码语言:javascript复制
package top.finen.springmvc.handlers;

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

@Controller
@RequestMapping("/springmvc")
public class SpringMVCTest {
    private static final String SUCCESS = "success";

    /**
     * 1. @RequestMapping 除了修饰方法,还可以修饰类
     * 2.
     *  1).类定义处:提供初步的请求映射信息,相对于WEB应用的根目录。
     *  2).方法处:提供进一步的细分映射信息。
     *  相对于类定义处的URL,若类定义处未标注 @RequestMapping,则方法标记处的URL相对于WEB应用的根目录。
     * @return
     */
    @RequestMapping("testRequestMapping")
    public String testRequestMapping() {

        System.out.println("testRequestMapping");
        return SUCCESS;
    }

    /**
     * 使用method属性来指定请求方式
     * @return
     */
    @RequestMapping(value = "testMethod", method = RequestMethod.POST)
    public String testMethod() {
        System.out.println("testMethod");
        return SUCCESS;
    }

    /**
     * 了解:使用params和headers来更加精确的映射请求,params和headers支持简单的表达式
     * @return
     */
    @RequestMapping(value = "testParamsAndHeaders",
            params = {"username", "age!=10"},
            headers = {"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8"})
    public String testParamsAndHeaders() {
        System.out.println("testParamsAndHeaders");
        return SUCCESS;
    }

    @RequestMapping("testAntPath/*/abc")
    public String testAntPath() {
        System.out.println("testAntPath");
        return SUCCESS;
    }

    /**
     * @PathVariable 可以来映射URL中的占位符到目标方法的参数中
     * @param id
     * @return
     */
    @RequestMapping("testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") Integer id){
        System.out.println("testPathVariable"   id);
        return SUCCESS;
    }

}

# REST(资源表现层转化)

资源:网络上的一个实体或者说网络的一个具体信息。URI即为每一个资源的独一无二的识别符。

表现层:把资源具体呈现出来的形式,叫做表现层。

状态转化:如果客户端想要操作服务器,必须通过某种手段,让服务器发生状态转化。HTTP协议中,四个表示操作方式的动词:GET、POST、PUT、DELETE。他们分别是对应四种基本的操作。GET来获取资源。POST来新建资源。PUT来更新资源。DELETE来删除资源。

HiddenHttpMethodFilter:

代码语言:javascript复制
/**
 * REST 风格的url
 * 以CRUD为例:
 *      新增: /order POST
 *      修改: /order/1 PUT
 *      获取: /order/1 GET
 *      删除: /order/1 DELETE
 * 如何发送PUT请求和DELETE请求
 * 1.需要配置HiddenHttpMethodFilter
 * 2.需要发送POST请求
 * 3.需要在发送POST请求请求时携带一个域name="_method"的隐藏域,值为DELETE或者PUT
 *
 * 在springmvc的目标方法中如何得到id呢?
 * 使用:@PathVariable 注解
 * @param id
 * @return
 */
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.GET)
public String testRest(@PathVariable Integer id) {
    System.out.println("testRest GET"   id);
    return SUCCESS;
}

@RequestMapping(value = "/testRest", method = RequestMethod.POST)
public String testRest() {
    System.out.println("testRest POST");
    return SUCCESS;
}

@RequestMapping(value = "/testRest/{id}", method = RequestMethod.DELETE)
public String testRestDelete(@PathVariable Integer id) {
    System.out.println("testRest DELETE"   id);
    return SUCCESS;
}

@RequestMapping(value = "/testRest/{id}", method = RequestMethod.PUT)
public String testRestPut(@PathVariable Integer id) {
    System.out.println("testRest GET"   id);
    return SUCCESS;
}

# 请求处理方法签名

SpringMVC通过分析处理方法的签名,将HTTP请求信息绑定到处理方法的相应入参中。

必要时可以对方法以及方法入参标注相应的注解:@PathVariable @RequestParam @RequestHeader

# 请求参数
代码语言:javascript复制
/**
 * @RequestParam 来映射请求参数
 * value值即为请求参数的参数名
 * required 请求参数是否为必须
 * defaultValue 请求参数的默认值:默认为true
 * @param username
 * @param age
 * @return
 */
@RequestMapping(value = "testRequestParam")
public String testRequestParam(@RequestParam(value = "username") String username,
                               @RequestParam(value = "age", required = false) Integer age){
    System.out.println("testRequestParam===>"   "username: "   username   " age: "   age);
    return SUCCESS;
}
代码语言:javascript复制
/**
 * 映射请求头
 * @param al
 * @return
 */
@RequestMapping(value = "testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept-Language") String al) {
    System.out.println("testRequestHeader===>"   al);
    return SUCCESS;
}
代码语言:javascript复制
/**
 * 了解:
 * @cookieValue 映射一个cookie值,属性同@RequestParam
 * @param sessionId
 * @return
 */
@RequestMapping(value = "testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId){
    System.out.println("testCookieValue: "   sessionId);
    return SUCCESS;
}

# POJO级联属性

代码语言:javascript复制
/**
 * SpringMVC 会按照请求参数名和POJO属性名进行自动匹配。
 * 自动为该对象填充属性值,支持级联属性。如dept.deptId, dept.address.tel
 * @param user
 * @return
 */
@RequestMapping(value = "testPojo")
public String testPojo(User user){
    System.out.println(user);
    return SUCCESS;
}

# 使用Servlet API作为入参

原生api:

  • HttpServletRequest
  • HttpServletResponse
  • HttpSession
  • java.security.Principal
  • Locale
  • InputStream
  • OutputStream
  • Reader
  • Writer

# 处理模型数据

代码语言:javascript复制
/**
 * 目标方法的返回值可以是 ModelAndView 类型。
 * 其中可以包含视图和模型信息
 * SpringMVC 会把 ModelAndView 的 model 中数据放入到 request 域对象中.
 * @return
 */
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
    String viewName = SUCCESS;
    ModelAndView modelAndView = new ModelAndView(viewName);

    //添加模型数据到 ModelAndView 中.
    modelAndView.addObject("time", new Date());

    return modelAndView;
}

Map以及Model

代码语言:javascript复制
/**
 * 目标方法可以添加 Map 类型(实际上也可以是 Model 类型或 ModelMap 类型)的参数.
 * @param map
 * @return
 */
@RequestMapping(value = "/testMap")
public String testMap(Map<String, Object> map) {
    map.put("name", Arrays.asList("Tom", "Jerry", "Mike"));
    return SUCCESS;
}

# SessionAttribute

代码语言:javascript复制
/**
 * @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
 * 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
 *
 * 注意: 该注解只能放在类的上面. 而不能修饰放方法.
 */
@RequestMapping(value = "/testSessionAttributes")
public String testSessionAttributes(Map<String, Object> map){
    User user = new User("Tom", "1123", "fine.top@top.com", 15);
    map.put("user", user);
    return SUCCESS;
}

# ModelAttribute

代码语言:javascript复制
/**
     * 1. 有 @ModelAttribute 标记的方法, 会在每个目标方法执行之前被 SpringMVC 调用!
     * 2. @ModelAttribute 注解也可以来修饰目标方法 POJO 类型的入参, 其 value 属性值有如下的作用:
     * 1). SpringMVC 会使用 value 属性值在 implicitModel 中查找对应的对象, 若存在则会直接传入到目标方法的入参中.
     * 2). SpringMVC 会一 value 为 key, POJO 类型的对象为 value, 存入到 request 中.
     */
    @ModelAttribute
    public void getUser(@RequestParam(value = "id", required = false) Integer id,
                        Map<String, Object> map) {
        if (id != null) {
           User user = new User("Tom", "123", "ssss@fine.top", 12);
           System.out.println(user);
           map.put("user", user);
        }
    }

    /**
     * 运行流程:
     * 1.执行@ModelAttribute注解修饰的方法:从数据库中取出对象,把对象放入到Map中;key为:user
     * 2.SpringMVC把Map的中取出User对象,并把表单的请求参数赋给User对象的对应属性
     * 3.SpringMVC把上述对象传入目标方法的参数
     * 注意:在ModelAttribute修饰的方法中,放入到Map的键需要和目标方法入参类型的第一个小写字母的字符串一致。
     *
     * SpringMVC确定目标方法POJO类型入参的过程
     * 1.确定一个key
     *   1).若目标方法的POJO类型的参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写。
     *   2).若使用了@ModelAttribute来修饰,则key为@ModelAttribute注解的value属性值。
     *      若在@ModelAttribute标记的方法中Map中保存过,且key和1确定的key一致,则会获取到。
     * 2.在implicitModel中查找key对应的对象,若存在,则作为入参传入
     * 3.若implicitModel不存在key对应的对象,则检查当前的Handler是否使用了@SessionAttribute注解来修饰
     * 若使用了该注解,且@SessionAttribute注解的Value属性值中包含了key,则会从HTTPSession中获取key所对应的value值。
     * 若存在直接传入目标方法的入参中,若不存在则抛出异常。
     * 4.若Handler没有标识@SessionAttribute注解或者@SessionAttribute注解的value值中不包含key,则会通过反射创建POJO类型的参数,传入
     * 为目标方法的参数。
     * 5.SpringMVC会把key和POJO类型的对象保存到implicitModel中,进而保存到request中。
     *
     * 源码分析:
     *  1.调用@ModelAttribute注解修饰的方法,实际把@ModelAttitude方法中的Map中的数据放在implicitModel中
     *  2.解析请求处理器的目标参数,实际上把该目标参数来自于WedDataBinder对象的target属性
     *      1).创建WebDataBinder对象
     *          ① 确定objectName属性:若传入的attrName属性为“”,则objectName为类名第一个字母小写。
     *          **** 注意:attrName 若目标方法的POJO属性使用了@ModelAttitude来修饰,则attribute值即为@ModelAttitude的value属性值
     *          ② 确定target属性
     *              > 在implicitModel中茶盅attrName对应的属性值
     *              > 若不存在:则验证当前的Handler是否使用了@SessionAttributes进行修饰,若使用了,则尝试从Session中获取attrName所对应的
     *              属性值,若session中没有对应的属性值,则抛出异常。
     *              > 若handler没有使用@SessionAttributes进行修饰,或者@SessionAttribute中没有使用value值指定的键和attrName相匹配。
     *              则通过反射进行创建。
     *      2).SpringMVC把表单的请求参数赋给了WebDataBinder的target对应到的属性。
     *      3).SpringMVC会把WebDataBinder的attrName和target给到implicitModel
     *      4).把WebDataBinder的target作为参数传递给目标方法的入参。
     *
     *
     */
    @RequestMapping(value = "testModelAttribute")
    public String testModelAttribute(User user){
        System.out.println(user);
        return SUCCESS;
    }

# ViewAndViewResolver

代码语言:javascript复制
 @RequestMapping("/testViewAndViewResolver")
    public String testViewAndViewResolver(){
        System.out.println("testViewAndViewResolver");
        return SUCCESS;
    }
    @RequestMapping("/testView")
    public String testView() {
        System.out.println("testView");
        return "helloView";
    }
代码语言:javascript复制
    <!--配置转发页面-->
    <mvc:view-controller path="/success" view-name="success"></mvc:view-controller>

    <!--在实际开发中通常需要配置mvc:annotation-driven-->
    <mvc:annotation-driven></mvc:annotation-driven>

0 人点赞