练习spring mvc

1. 项目结构总结

这个Spring MVC项目采用Maven管理,遵循标准的Web项目结构。以下是详细的文件级别结构:

核心目录结构

复制代码
springmvc_helloword/
├── .idea/                      # IDEA项目配置目录
│   ├── artifacts/              # 项目打包配置
│   └── libraries/              # 项目依赖库配置
├── src/                        # 源代码目录
│   ├── main/                   # 主源码
│   │   ├── java/com/zhang/controller/  # 控制器包
│   │   │   ├── HelloController.java    # 主要控制器
│   │   │   └── PathVariableController.java # 路径变量控制器
│   │   └── resources/          # 资源文件目录
│   │       └── springmvc.xml   # Spring MVC核心配置文件
│   └── test/                   # 测试代码目录
├── web/                        # Web资源目录
│   ├── WEB-INF/                # Web应用配置目录
│   │   ├── page/               # 视图页面目录
│   │   │   └── hello.jsp       # 主视图页面
│   │   └── web.xml             # Web应用配置文件
│   ├── heihei.html             # 静态HTML页面
│   └── index.jsp               # 首页JSP
├── target/                     # 编译构建输出目录
│   ├── classes/                # 编译后的class文件
│   └── springmvc_helloword-1.0-SNAPSHOT.war # 打包后的War文件
├── pom.xml                     # Maven项目配置文件
└── springmvc_helloword.iml     # IDEA模块配置文件

2. Demo练习内容详解

这个Spring MVC演示项目主要练习了以下核心功能和知识点:

2.1 Spring MVC基本架构和请求处理流程

  • 演示了完整的Spring MVC请求处理流程:从浏览器请求 → DispatcherServlet前端控制器 → Controller控制器处理 → 视图解析 → 响应页面
  • 配置了核心组件:DispatcherServlet、Controller、ViewResolver

2.2 控制器(Controller)的配置与使用

  • 练习了基于注解的控制器开发(@Controller、@RequestMapping)
  • 实现了两个不同的控制器:HelloController和PathVariableController
  • 展示了控制器方法如何返回视图名称

2.3 请求映射(Request Mapping)的多种配置方式

  • 基础URL映射:通过@RequestMapping注解映射请求路径
  • 类级和方法级映射组合:在类和方法上同时使用@RequestMapping,形成组合路径
  • 请求头限制:通过headers参数限制特定请求头的请求
  • 请求方式限制:支持配置GET/POST等请求方法
  • 模糊匹配:使用通配符*进行路径模糊匹配
  • 参数限制:通过params参数限制请求必须包含特定参数

2.4 路径变量(PathVariable)的使用

  • 演示了@PathVariable注解获取URL路径中的变量值
  • 展示了如何将路径变量绑定到方法参数
  • 实现了RESTful风格的URL设计

2.5 视图解析器的配置与使用

  • 配置了InternalResourceViewResolver视图解析器
  • 设置了前缀(prefix)和后缀(suffix),实现视图名称到物理路径的映射
  • 练习了控制器向视图传递数据(使用Map传递属性)

2.6 静态资源处理

  • 配置了DefaultServlet处理静态HTML资源
  • 演示了如何避免DispatcherServlet拦截静态资源的问题
  • 添加了mvc:default-servlet-handler和mvc:annotation-driven配置解决静态资源访问

2.7 Spring MVC配置方式

  • 练习了XML配置方式:在springmvc.xml中配置组件扫描、视图解析器等
  • 练习了注解配置方式:使用@ComponentScan、@Controller等注解
  • 解决了XML配置和注解配置冲突的问题

2.8 Maven项目配置与打包

  • 配置了Spring相关依赖(spring-context、spring-web、spring-webmvc)
  • 设置了打包类型为war包
  • 配置了maven-war-plugin插件自定义Web资源目录

2.9 JSP视图开发

  • 创建了JSP页面并使用EL表达式(${hello})获取控制器传递的数据
  • 实现了简单的表单提交功能

这个项目作为Spring MVC的入门练习,涵盖了MVC架构的核心概念和Spring MVC框架的基础功能,帮助理解Web应用的分层设计和请求处理机制。

访问: http://localhost:8083/testPathVariable/456/mary

http://localhost:8083/

代码

controller层

java 复制代码
package com.zhang.controller;

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

import java.util.Map;

/**
 *
 * springmvc处理过程
 *  1、浏览器要发送一个请求 http://localhost:8080/springmvc_helloworld_war_exploded/hello
 *  2、首先交给tomcat容器
 *  3、在web.xml文件中配置了DispatcherServlet的类,所以此时会由当前的DispatcherServlet来接受请求
 *  4、接受到请求之后找到对应的Controller,去Controller中寻找@RequestMapping注解标识的方法
 *  5、找到匹配的方法之后,执行方法的逻辑
 *  6、处理完成之后需要返回一个前端页面的名称,
 *  7、有视图处理器来根据名称映射到对应的jsp页面的路径
 *  8、DispatcherServlet拿到对应的路径地址之后返回给浏览器
 *
 */
@Controller
@RequestMapping("/hello")
public class HelloController{

    /*
    * @RequestMapping表示用来匹配当前方法要处理的请求,其中/可以写也可以不写,一般推荐协商
    *
    * @RequestMapping可以添加在类上,也可以添加在方法上
    *      方法:http://localhost:8080/springmvc_helloworld_war_exploded/hello
    *       类:http://localhost:8080/springmvc_helloworld_war_exploded/hello/hello
    * 当添加在类上的时候表示给所有的当前类的方法钱添加一个访问路径
    *     什么时候需要在类上添加此注解?
    *       当包含多个Controller,通过在不同的Controller中包含同名的请求的时候,需要添加
    *
    * @RequestMapping配置的参数
    *   value:表示要匹配的请求
    *   method:表示请求的方式,post  get
    *   params:表示要求请求中必须要包含的参数
    *           必须要包含username的属性值
    *           @RequestMapping( value = "/hello",params = {"username"})
    *           不能包含的参数名称
                @RequestMapping( value = "/hello",params = {"!username"})
                必须要包含username,age两个属性值,并且username的值为zhangsan
                @RequestMapping( value = "/hello",params = {"username=zhangsan","age"})
     *  headers:表示限制请求头中的相关属性值,用来做请求的限制
     * produces:限制请求中的Content-Type
     * consumers:限制响应中的Content-Type
     *
     *
     * @RequestMapping可以进行模糊匹配
     *      ?:替代任意一个字符
     *      *:替代多个字符
     *      **:替代多层路径
     * 如果能匹配到多个请求,那么优先是精准匹配,其次是模糊匹配
    * */
    @RequestMapping( value = "/hello",headers = {"User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36"})
    public String hello(Map<String,String> map){
        map.put("hello","hello,Springmvc");
        return "hello";
    }

    @RequestMapping( value = "/hello*")
    public String hello2(Map<String,String> map){
        map.put("hello","hello,heihei");
        return "hello";
    }
}


package com.zhang.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Controller
public class PathVariableController {

    /**
     * @PathVariable可以获取请求路径中的值
     *  在路径中要使用{变量名称}做标识
     *  在方法参数中可以添加@PathVariable做识别,如果路径中的名称跟参数的名称不一致的时候,可以添加路径中的变量名称
     *  推荐添加
     * @param id
     * @param name
     * @return
     */
    @RequestMapping("/testPathVariable/{id}/{name}")
    public String testPathVariable(@PathVariable("id") Integer id ,@PathVariable("name") String name){
        //request.getParameter("name")
        System.out.println(id);
        System.out.println(name);
        return "hello";
    }
}

配置文件

springmvc.xml

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"
       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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <context:component-scan base-package="com.zhang"></context:component-scan>
<!--加个注解处理html-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>
    <!-- 添加注解驱动配置,这会注册必要的处理器适配器和处理器映射 -->
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 跟注解冲突了, 二者留其一 -->
<!--        <bean id="/hello" class="com.zhang.controller.HelloController"></bean>-->

</beans>

web.xml

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>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--
        设置初始化参数,指定默认的springmvc的配置文件
        可以选择将springmvc的配置文件添加到/WEB-INF/的目录下。默认是从此目录查找配置文件
        但是需要注意的是,配置文件的名称必须是  (DispatcherServlet的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>

    <!--
    添加前端控制器对应的mapping映射:
    映射所有的请求,因此最好写成/  /*(区别?)
    /:用来匹配所有请求,但是/不会拦截jsp页面
    /*:用来匹配所有的请求,会拦截jsp页面

    此时如果创建一个html页面之后,是无法请求到的,原因是:
    每个项目的web.xml文件会继承tomcat下的web.xml文件,而在tomcat-web.xml文件中包含了一个DefaultServlet的处理类
    用来处理静态资源,但是我们在编写自己的DispatcherServlet的时候使用了/的方式,此方式覆盖了父web,xml对于静态资源的处理
    所以此时所有的静态资源的访问也需要由DispatcherServlet来进行处理,但是我们并没有设置对应的Controller,所以报404

    为什么jsp能处理呢?
    在父web.xml文件中包含了一个JSPServlet的处理类,会有tomcat进行处理,而不是我们定义的DispatcherServlet
    -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
</web-app>

前端页面

html 复制代码
<!-- heihei.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hello,html
</body>
</html>



<!-- index.jsp-->
<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/3/14
  Time: 15:44
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>$Title$</title>
</head>
<%
  pageContext.setAttribute("ctp",request.getContextPath());
%>
<body>
<form action="${ctp}/hello/hello" method="post">
  <input type="text" name="username"><br>
  <input type="submit" value="提交">
</form>
</body>
</html>




<!-- /WEB-INF/page/heihei.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
heihei.html
heihei.html
heihei.html
</body>
</html>



<!-- /WEB-INF/page/hello.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

hello.html
</body>
</html>



<!-- /WEB-INF/page/hello.jsp-->
<html>
<head>
    <title>Title</title>
</head>
<body>
谢
${hello}
</body>
</html>

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zhang</groupId>
    <artifactId>springmvc_helloword</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-catalina</artifactId>
        <version>8.0.36</version>
    </dependency>
<!--    &lt;!&ndash;        Servlet依赖&ndash;&gt;-->
<!--    <dependency>-->
<!--        <groupId>javax.servlet</groupId>-->
<!--        <artifactId>javax.servlet-api</artifactId>-->
<!--        <version>3.1.0</version>-->
<!--        <scope>provided</scope>-->
<!--    </dependency>-->
<!--    &lt;!&ndash;        JSP依赖&ndash;&gt;-->
<!--    <dependency>-->
<!--        <groupId>javax.servlet.jsp</groupId>-->
<!--        <artifactId>javax.servlet.jsp-api</artifactId>-->
<!--        <version>2.3.3</version>-->
<!--        <scope>provided</scope>-->
<!--    </dependency>-->
<!--    &lt;!&ndash;        jstl表达式的依赖&ndash;&gt;-->
<!--    <dependency>-->
<!--        <groupId>javax.servlet</groupId>-->
<!--        <artifactId>jstl</artifactId>-->
<!--        <version>1.2</version>-->
<!--    </dependency>-->
<!--    &lt;!&ndash;        standar标签库&ndash;&gt;-->
<!--    <dependency>-->
<!--        <groupId>taglibs</groupId>-->
<!--        <artifactId>standard</artifactId>-->
<!--        <version>1.1.2</version>-->
<!--    </dependency>-->
</dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
                <configuration>
                    <webResources>
                        <resource>
                            <directory>web</directory>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>