学习笔记SpringMVC_01 SpringMVC的入门

SpringMVC入门案例

1.新建MAVEN工程,选择webapp骨架。在pom.xml中导入坐标如下:

 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

2.配置SpringMVC组件
将SpringMVC组件注入Spring核心容器: 在工程resource目录下创建文件springmvc.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="cn.itcast"></context:component-scan>

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

    <!--开启注解Springmvc框架注解的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

配置SpringMVC核心控制器DispatcherServlet,并使Spring容器在TOMCAT初始化时创建. 在工程的webapp/WEB_INF目录下配置web.xml如下:

<web-app>
	<!-- 配置核心控制器 -->
	<servlet>
		<servlet-name>dispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 使核心控制器初始化时读取springmvc.xml文件创建Spring核心容器 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
        <!-- 设置该Servlet的优先级别最高,使之最早创建 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

3.编写控制器和视图
编写主页视图index.jsp: 在工程的webapp目录下创建视图index.jsp如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>入门程序</h3>
    <a href="hello">入门程序</a>
</body>
</html>

在工程的java目录下创建控制器类cn.itcast.HelloController如下:

//控制器的类
@Controller
public class HelloController {
    @RequestMapping(path="/hello")
    public String sayHello(){
        System.out.println("Hello SpringMVC");
        return "success";
    }
}

在工程的webapp/WEB_INF/pages目录下创建成功跳转视图success.jsp如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
	<title>Title</title>
</head>
<body>
	<h3>跳转成功</h3>
</body>
</html>

4.配置并启动tomcat服务器。

案例执行流程分析

案例的执行流程

  1. 启动了tomcat服务器之后,加载应用的web.xml文件,读取到了<load-on-startup>标签所以首先创建了DispatcherServlet(前端控制器)对象,读取到了<init-param>标签然后加载了spring.xml配置文件,创建了spring容器,根据配置初始化了容器中的对象(包括HelloController,InternalResourceViewResolver(视图解析器)但不止)。
  2. 根据服务器配置启动了index.jsp页面后,点击入门案例按钮(即jsp文件中<a href="hello">标签),浏览器把href中的URL发送到服务器,被前端控制器捕获,前端控制器把请求转发到HandlerMapping(处理器映射器)中请求查找Handler,处理器映射器在Controller类中根据@RequestMapping注解找到对应的方法即hello方法,但处理器映射器并不能执行方法,它返回一个执行链(包含HelloController类的sayhello方法)到前端控制器。
  3. 前端控制器再根据执行链找到HandlerAdapter(处理器适配器),经过适配器去执行Handler(处理器)也叫Controller(在这个案例中就是执行的HelloController类的sayhello方法)。
  4. 执行过玩方法后,处理器会返回一个ModelAndView对象到适配器,再从适配器转发到前端控制器。
  5. 前端控制器请求ViewResolver(视图解析器)(必须是已经注册到Spring容器中的ViewResolver,即InternalResourceViewResolver)解析ModelAndView,根据注入的prefix,suffix的value值找到对应jsp文件并得到结果视图。
  6. 服务器渲染视图,响应浏览器。

SpringMVC核心组件

在这里插入图片描述 1. 前端控制器(核心控制器)DispatcherServlet:用户请求最先达到的控制器,前端控制器调用其他组件处理请求,是MVC架构中的C,是整个流程控制的核心.其存在降低了组件间的耦合性.
2. 处理器映射器HandlerMapping:负责根据用户请求找到处理器.
3. 处理器Handler:具体的业务方法.
4.处理器适配器HandlAdapter: 对处理器进行执行.这是一种适配器模式的应用.
5. 视图解析器ViewResolver: 负责将处理结果生成视图. ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户.
6.视图View: 具体的页面

其中处理器映射器HandlerMapping,处理器适配器HandlAdapter,视图解析器ViewResolver称为SpringMVC三大组件.在bean.xml中声明<mvc:annotation-driven conversion-service="conversionService"/>标签相当于自动配置了处理器映射器和处理器适配

@RequestMapping注解: 匹配路径与处理器

@RequestMapping注解用于建立请求URL路径和处理器之间的对应关系.

出现位置: 可以出现在类上,也可以出现在方法上.
当它既出现在类上也出现在方法上时,类上注解值为请求URL的一级目录,方法上注解值为请求URL的二级目录,便于模块化管理。
当它只出现在方法上时,该注解值为请求URL的一级目录。

属性:
value,就是path。
指定请求的URL,支持Ant风格表达式,通配符如下:

通配符 说明
匹配文件(路径)名中的一个字符
* 匹配文件(路径)名中的任意数量(包括0个)的字符
** 匹配任意数量(包括0个)的路径

路径/project/*.a匹配项目根路径下所有在/project路径下的.a文件
路径/project/p?ttern匹配项目根路径下的/project/pattern和/project/pXttern,但不能匹配/project/pttern
路径/**/example匹配项目根路径下的/project/example,/project/foo/example,和/example
路径/project/**/dir/file.*匹配项目根路径下的/project/dir/file.jsp,/project/foo/dir/file.html,/project/foo/bar/dir/file.pdf
路径/**/*.jsp匹配项目根路径下的所有jsp文件

另外,遵循最长匹配原则,若URL请求了/project/dir/file.jsp,现在存在两个匹配模式:/**/*.jsp/project/dir/*.jsp,那么会根据/project/dir/*.jsp来匹配.

method: 指定HTTP请求方法(可选RequestMethod.GET,RequestMethod.HEAD,RequestMethod.POST,RequestMethod.PUT等),多个值之间是或的关系.
params: 指定请求参数的限制,支持简单的表达式,如:

@RequestMapping(params={“param1”}),表示请求参数中param1必须出现
@RequestMapping(params={"!param1"}),表示请求参数中param1不能出现
@RequestMapping(params={“param1=value1”}),表示请求参数中param1必须出现且为value1
@RequestMapping(params={“param1!value1”}),表示请求参数中param1必须出现且不为value1
多个值之间是与的关系.

headers: 限定HTTP请求中必须包含的请求头,同样支持简单的表达式
其中path和method属性较常用.

请求参数的绑定(重点)

各种类型请求参数的绑定
SpringMVC支持三种类型的参数绑定:
基本数据类型和String类型
JavaBean类型
集合类型

对于基本数据类型,只需要以方法参数名作为请求参数名即可.示例如下:

<a href="/param/testParam?username=hehe&password=123">请求参数绑定</a>
//请求参数的绑定
@Controller
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("/testParam")
    public String testParam(String username, String password) {
        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);
        System.out.println("执行");
        return "success";
    }

JavaBean类型的参数绑定
Account类

// JavaBean类
public class Account implements Serializable {
    private String username;
    private String password;
    private Double money;
    // 所有属性的getset方法...

表单:

 <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username"><br>
        密码:<input type="text" name="password"><br>
        金额:<input type="text" name="money"><br>
        <input type="submit" value="提交">
    </form>

若JavaBean参数的属性中包含其它JavaBean对象,则以外层类属性名.内层类属性名作为请求参数。

配置解决中文乱码问题

 <!--配置解决中文乱码的过滤器-->
  <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>
  </filter>
  <!-- 过滤所有请求 -->
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

集合类型的参数绑定

对JavaBean类中的集合属性进行参数绑定,可以分为List类型的参数绑定和Set类型的参数绑定

public class Account implements Serializable {

    private String username;
    private Intger age;
    
    private List<User> list;		// List集合属性
    private Map<String, User> map;	// Map集合属性


	// 所有属性的getset方法...
}
则其对应的请求参数名如下:
public class User implements Serializable{

    private String uname;
    private Double umoney;
    
    // 所有属性的getset方法...
}

  <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username"><br>
        密码:<input type="text" name="password"><br>
        金额:<input type="text" name="money"><br>

        用户姓名:<input type="text" name="list[0].uname"><br>
        用户年龄:<input type="text" name="list[0].age"><br>

        用户姓名:<input type="text" name="map['one'].uname"><br>
        用户年龄:<input type="text" name="map['one'].age"><br>
        <input type="submit" value="提交">
    </form>

自定义数据类型参数绑定

表单提交的任何数据类型都是字符串类型,SpringMVC定义了转换器,将字符串转化为我们方法参数的各种类型.我们也可以实现自定义的转换器以实现自定义的参数类型转换
自定义的类型转换器要实现Converter<String, T>接口,并在Spring容器配置bean.xml中配置该实现类. 示例如下:

在工程的java目录下创建控制器类cn.maoritian.util.StringToDateConverter类,实现Converter<String, Date>接口,完成从String类到Date类的转换:

// 自定义的类型转换器,完成从String类到Date类的转换
public class StringToDateConverter implements Converter<String, Date> {

    public Date convert(String source) {
        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Date date = df.parse(source);
            return date;
        } catch (Exception e) {
            throw new RuntimeException("类型转换错误");
        }
    }
}

在Spring容器配置bean.xml中加入如下配置:

<!-- 配置的类型转换器工厂 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <!-- 诸如我们自定义的类型转换器 -->
            <bean class="cn.maoritian.utils.StringToDateConverter"/>
        </set>
    </property>
</bean>

通过原始ServletAPI对象处理请求

SpringMVC支持使用原始ServletAPI作为控制器方法的参数,包括HttpServletRequest,HttpServletResponse,HttpSession对象,他们都可以直接用做控制器方法的参数.示例如下:

@RequestMapping("/path")
public void myHandler(HttpServletRequest request, HttpServletResponse response)  {
    System.out.println(request);
    System.out.println(response);
}

常用注解

@RequestParam注解: 为处理器方法参数起别名
@RequestParam注解作用在方法参数上,把请求中指定名称的参数给处理器方法中的形参赋值,相当于给处理器方法起别名.其属性如下:

name: value属性的别名,指定请求参数的名称
required: 指定该请求参数是否必须的,默认为true

@RequestMapping("/testRequestParam")
public String handlerMethod(@RequestParam("param1") String username) {
    // 方法体...
}

@RequestBody注解:获取请求体内容。
get方法不适用
key=value形式
属性:required:是否必须有请求体 默认是true。true时gei请求方法会报错,false时get请求得到null

@PathVaribale注解
name属性来修饰处理器参数来将占位符对应的值赋给方法的参数

<a href="account/findAccount/10">查询账户</a>
// 控制器类
@Controller
@RequestMapping(path = "/account")
public class HelloController {

    @RequestMapping("/findAccount/{id}")
    public void findAccount(@PathVariable(name = "id") Integer accountId) {
        // accountId = 10
        // 方法体...
    }
}

把10赋值给accoundId

@ModelAttribute注解
用于修饰方法和参数。
出现在方法上修饰的方法会在控制器方法之前执行,出现在参数上,获取指定的数据给参数赋值。
应用场景:当表单提交数据不是完整的实体类数据时,保证没有提交的数据的字段可以使用数据库对象原来的数据。例如在编辑一个用户时,有些字段内容不需要更改但要设置进去,就可以使用这个注解。
修饰的方法带有返回值的:

 @ModelAttribute
    public User showUser(String uname){
    System.out.println("showUser执行了...");
    // 通过用户查询数据库(模拟)
    User user = new User();
    user.setUname(uname);
    user.setAge(20);
    user.setDate(new Date());
    return user;

不带返回值的

 @ModelAttribute
    public void showUser(String uname, Map<String,User> map){
        System.out.println("showUser执行了...");
        // 通过用户查询数据库(模拟)
        User user = new User();
        user.setUname(uname);
        user.setAge(20);
        user.setDate(new Date());
        map.put("abc",user);
    }

@SessionAttribute注解
用于多次执行控制器方法之间的参数共享。只能作用于类上
属性:
value:用于指定存入的属性名称

 /**
     * SessionAttributes的注解
     * @return
     */
    @RequestMapping(value="/testSessionAttributes")
    public String testSessionAttributes(Model model){
        System.out.println("testSessionAttributes...");
        // 底层会存储到request域对象中
        model.addAttribute("msg","美美");
        return "success";
    }

    /**
     * 获取值
     * @param modelMap
     * @return
     */
    @RequestMapping(value="/getSessionAttributes")
    public String getSessionAttributes(ModelMap modelMap){
        System.out.println("getSessionAttributes...");
        String msg = (String) modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }

    /**
     * 清除
     * @param status
     * @return
     */
    @RequestMapping(value="/delSessionAttributes")
    public String delSessionAttributes(SessionStatus status){
        System.out.println("getSessionAttributes...");
        status.setComplete();
        return "success";
    }
发布了33 篇原创文章 · 获赞 0 · 访问量 496

猜你喜欢

转载自blog.csdn.net/naerjiajia207/article/details/103495984