SpringMVC框架

一、入门

1、第一个SpringMVC程序

1.1框架搭建

  • 基于框架的搭建,首先还是需要创建一个maven项目,其次导入依赖,此处我们搭建的是一个web项目,所以可以在搭建maven项目的时候就创建一个web项目,当然,最后再创建也是可以的,这里采用最后创建。

  • 配置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_4_0.xsd"
         version="4.0">
<!--    注册前端控制器DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--这里的springMVC.xml要与类路径下面的spring 名字高度一致-->
            <param-value>classpath:springMVC.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>
</web-app>
  • 创建一个class类
public class TestController {
   
}
  • 配置spring.xml文件

下面的thymeleaf是模板

<?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 https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置扫描组件-->
   <context:component-scan base-package="com.study.mvc.controller"/>
   <!-- 配置Thymeleaf视图解析器 -->
   <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
      <property name="order" value="1"/>
      <property name="characterEncoding" value="UTF-8"/>
      <property name="templateEngine">
         <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
            <property name="templateResolver">
               <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                  <!-- 视图前缀 -->
                  <property name="prefix" value="/WEB-INF/templates/"/>

                  <!-- 视图后缀 -->
                  <property name="suffix" value=".html"/>
                  <property name="templateMode" value="HTML5"/>
                  <property name="characterEncoding" value="UTF-8" />
               </bean>
            </property>
         </bean>
      </property>
   </bean>
</beans>
  • 通过配置的视图前缀,我们需要在/WEB-INF/templates/ 该路径下写html文件,在WEB-INF下新建一个templates文件夹,编写html代码。需要注意要使用thymeleaf,所以需要在html标签上配置 xmlns:th=“http://www.thymeleaf.org”
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <h1>首页</h1>
</body>
</html>
  • 编写class类
package com.study.mvc.controller;

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

@Controller
public class TestController {
    @RequestMapping("/")
    public String index() {
        return "index";
    }
}

1.2@RequestMapping注解

1.2.1@RequestMapping注解的功能

它的作用就是将请求和处理请求的控制器方法关联起来,建立一个映射关系,当springMVC接收到这个指定的请求,就会来找到在在映射关系关系中对应的控制器来处理这个请求。

1.2.2@RequestMapping注解的位置

@RequestMapping标识一个类:设置映射请求的请求路径的初始信息

@RequestMapping标识一个方法:设置映射请求请求路径的具体信息

通过查看@RequestMapping的源码可知,它出现在的位置在类和方法上,在类上设置设置属性,就是在请求的路径上再加上一个路径,用来区分不同控制器相同的方法名配置的属性。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}

1.2.3@RequestMapping注解的value属性

此注解的value属性通过请求的请求地址匹配请求映射,它的value属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求,而且注解的value属性必须设置,至少通过请求地址匹配请求映射。

1.2.4@RequestMapping注解的Params属性

@RequestMapping注解的Params属性是通过请求参数匹配请求映射,他是一个字符串类型的数据组,通过四种表达式设置请求参数和请求映射的匹配关系:

param":要求请求映射所匹配的请求必须携带param请求参数

“!param”:要求请求映射所匹配的请求必须不能携带param请求参数

“param=value”:要求请求映射所匹配的请求必须携带param请求参数且param=value

“param!=value”:要求请求映射所匹配的请求必须携带param请求参数但是param!=value

1.2.5springMVC支持的Ant风格路径

这个风格的路径包括以下三个部分

//第一种用?占位,但是此风格不能包含/,/在路径下代表的是一个目录
@RequestMapping("/a?a/testAnt")  
//第二种,用*,此方法代表的是多个字符,同样不能包含/
@RequestMapping("/a*a/testAnt")
//第三种,可以包含/,并且为多个,但是必须是在两个//间就是以下的格式
@RequestMapping("/**/testAnt")//只能是(xxx/**/xxx)
1.2.6路径中的占位符

这就是rest方式:/deleteUser/1,@RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据,在通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参。

<a th:href="@{/hello/TestRest/lisi}">测试路径中的占位符</a>
 @RequestMapping("/TestRest/{username}")
    public String testRest(@PathVariable("username") String username) {
        System.out.println(username);
        return "success";
    }

2、springMVC获取请求参数

2.1通过SevrvletAPI获取参数
 <a th:href="@{/testServletAPI(username='zhangsan',password=123)}">请求参数测试Param</a>

@Controller
public class ParamController {
    @RequestMapping("/testServletAPI")
    public String testServletAPI(HttpServletRequest request) {
        String username = request.getParameter("username");
        int password = Integer.parseInt(request.getParameter("password"));
        System.out.println("username :" +username+ "password:" + password);
        return "success";
    }
}
2.2通过控制器方法的形参获取请求参数

在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在DispatcherServlet中就会将请求参数赋值给相应的形参

<form th:action="@{/testParam}" th:method="get">
        账号:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        爱好:<input type="checkbox" name="hobby" value="跑步">跑步
            <input type="checkbox" name="hobby" value="打球">打球
            <input type="checkbox" name="hobby" value="体哦啊高">体哦啊高
        <input type="submit" value="提交">
    </form>
@RequestMapping("/testParam")
    public String testParam(String username,Integer password,String hobby) {
        System.out.println("username :" +username+ " password:" + password + "hobby" + hobby);
        return "success";
    }

这里需要注意的是,要保证前端的数据和控制器的数据保持一致否则会报400错误,比如上述的password参数类型是Integer,所以前端form表单填入的数据就得是Integer类型,否则在页面跳转中直接报400错误。其次我们的请求参数名和我们的形参名也必须一致,否则获取不到数据。

如果请求参数和形参名不一致,应该怎么解决呢?

我们看可以通过注解来解决

@RequestParam("user_name") String username

@RequestParam注解一共有三个属性:

value:指定为形参赋值的请求参数的参数名

required:设置是否必须传输此请求参数,默认值为true

若设置为true时,则当前请求必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置defaultValue属性,则页面报错400:Required String parameter ‘xxx’ is not present;若设置为false,则当前请求不是必须传输value所指定的请求参数,若没有传输,则注解所标识的形参的值为null

defaultValue:不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值为""时,则使用默认值为形参赋值

2.3解决获取请求参数的乱码问题

解决get请求乱码问题,只需要从TomCat入手,将tomcat中的service.xml配置文件中的以下配置中加上配置UTF-8. URIEncoding=“UTF-8”

<Connector port="8080" URIEncoding="UTF-8" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

而解决post乱码就需要看程序的执行顺序,在tomcat启动前解决,也就是程序运行前,就需要设置编码格式,所以直接配置过滤器来解决这个乱码的问题。

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

二、域对象共享数据

1、获取与对象共享数据的集中方式

1.1通过ServletAPI获取域中的对象

1、通过ServletAPI获取域中的对象

使用th标签拿到request域中的值,通过传入他的name来获取

<p th:text="${testRequestScorp}"></p>
@Controller
public class ScopeController {
    @RequestMapping("/testRequestByServletAPI")
    public String testByServletAPI(HttpServletRequest request) {
        request.setAttribute("testRequestScorp","hello");
        return "success";
    }
}

1.2通过ModelView获取请求域中的对象

在这里需要注意必须设置视图名称,我们要返回的是视图,获取对象的方法也是一样的使用th标签进行获取

<p th:text="${testRequestScorp}"></p>

//使用ModelAndView获取请求域对象
    @RequestMapping("/requestByModelAndView")
    public ModelAndView modelAndView() {
        ModelAndView mdv = new ModelAndView();
        //向请求域共享对象
        mdv.addObject("testRequestScorp1","hello,ModelView");
        //设置视图名称
        mdv.setViewName("success");
        return mdv;
    }

1.3使用Model向request域对象共享数据

@RequestMapping("/testModel")
public String testModel(Model model){
    model.addAttribute("testScope", "hello,Model");
    return "success";
}

1.4使用map向request域对象共享数据

@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
    map.put("testScope", "hello,Map");
    return "success";
}

1.5使用ModelMap向request域对象共享数据

@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
    modelMap.addAttribute("testScope", "hello,ModelMap");
    return "success";
}

2、Model、ModelMap、Map的关系

如下代码所示,我们先通过反射机制获取当前对象实现类的全类名

@RequestMapping("/testRequestModel")
    public String model(Model model) {
        model.addAttribute("testRequest","hello model");
        System.out.println("model" + model.getClass().getName());
        return "success";
    }

    @RequestMapping("/testRequestMap")
    public String testMap(Map<String,Object> map) {
        map.put("testRequest","hello map");
        System.out.println(map.getClass().getName());
        return "success";
    }
    @RequestMapping("/testRequestModelMap")
    public String testModelMap(ModelMap modelMap){
        modelMap.addAttribute("testRequest", "hello,ModelMap");
        System.out.println(modelMap.getClass().getName());
        return "success";
    }

我们可以发现,我们通过反射机制获取当前对象实现类的全类名,发现这三个对象的实现类的全类名居然是完全一样的。
在这里插入图片描述

通过上述的一系列操作,我们不难发现,这三个对象存在一定的关系:Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的

他们之间的继承关系如下:

public interface Model{}
public class ModelMap extends LinkedHashMap<String, Object> {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class BindingAwareModelMap extends ExtendedModelMap {}
  • Model是一个接口,他是模型数据最顶层的接口

  • Map就是JDK中的Map,ModelMap 继承了 LinkedHashMap<String,Object>

  • LinkedHashMap又实现了Map接口!所以ModelMap是Map接口的实现类

  • BindingAwareModelMap继承于ExtendedModelMap。而ExtendedModelMap继承了ModelMap所以BingingAwareModel可以创建ModelMap,同时又实现了Model接口,也可以实例化Model

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值