02_SpringMVC从0开始框架搭建

SpringMVC从0开始框架搭建

0x01_创建项目

为了以后SpringMVC的学习,决定将所有作为练习的demo作为模块放在一个项目中(IDEA中项目和模块的概念)

首先创建一个空的项目:

image-20221106154439209

创建一个模块:archetype选择webapp

image-20221106154600447

创建完成之后,项目结构:

image-20221106154700399

需要补充项目结构:

image-20221106154758194

注意:

1.首先创建目录。

2.然后右键Mark directory as:

  • main/java:变成Sources Root
  • main/resources:变成Resources Root
  • test/java:变成Test Sources Root

3.我碰到过类似的情况:当隔段时间之后打开项目之后,项目很多目录又变成了普通目录,这时候在手动Mark direcory as之前,可以让IDEA重新识别一下pom.xml文件,识别pom之后,会自动调整项目。(IDEA难得抽风也是正常的)

完成模块创建之后,需要注意更改web.xml的内容。在没有更改之前:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

版本太老了,建议改成版本4:

<?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">
</web-app>

然后检查maven的配置和lombok相关的注解配置:

image-20221106163952947

image-20221106164026216

0x02_写点代码,测试一下tomcat

导入依赖

为了项目搭建之后,项目能够跑,先写点代码测试一下:

准备一个Servlet,完成页面的跳转(这里不需要SpringMVC的知识,学过Servlet就能理解)

pom.xml导入servlet-api和jsp-api的依赖(这两个依赖在tomcat中有,但是为了编程方便,需要导入依赖,但是导入的依赖不会编译进项目)

注意,删除掉pom.xml文件中version标签后的依赖或者配置,方便我们自己导入。

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.servlet.jsp</groupId>
  <artifactId>jsp-api</artifactId>
  <version>2.2</version>
  <scope>provided</scope>
</dependency>

上面两个依赖都是<scope>provided</scope>,意味着项目的编写时期这两个依赖才会起作用,不会编译进项目,也不会在运行时起作用,因为tomcat中有这2个依赖。

导入成功:

image-20221106160507923

配置Tomcat

Edit Configuration—》

image-20221106160807631

image-20221106160824393

image-20221106160851098

image-20221106160907784

apply—>OK

代码

image-20221106161018725

MyServlet

package com.bones.controller;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/myServlet.do")
public class MyServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher("aaa.jsp").forward(req,resp);
    }
}

aaa.jsp


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 this is page aaa
</body>
</html>

然后运行(绿色小三角),会自动弹出浏览器,然后访问http://localhost:8080/SpringMVC_pro01_buildAProject_war_exploded/myServlet.do会自动请求转发至aaa.jsp

image-20221106161158597

确保以上环境没有问题才可以。

0x03_SpringMVC框架搭建

导入依赖

pom.xml中的依赖如下

里面可选的依赖,可以不用导入,一般都是有相互依赖关系,所以有些可以不用导入。

<dependencies>
<!--spring容器核心包-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.3.23</version>
</dependency>
<!--spring切面包-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>5.3.23</version>
</dependency>
<!--aop联盟包-->
<dependency>
  <groupId>aopalliance</groupId>
  <artifactId>aopalliance</artifactId>
  <version>1.0</version>
</dependency>
<!--druid数据源(连接池)-->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.10</version>
</dependency>
<!--mysql驱动-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.30</version>
</dependency>
<!--SpringJDBC包-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.3.23</version>
</dependency>
<!--spring事务控制-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>5.3.23</version>
</dependency>
<!--springORM映射依赖-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>5.3.23</version>
</dependency>
<!--apache commons日志-->
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
</dependency>
<!--log4j2 slf4j-->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.19.0</version>
  <scope>test</scope>
</dependency>
<!--lombok-->
  <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
      <scope>provided</scope>
  </dependency>
<!--junit5-->
  <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.9.1</version>
      <scope>test</scope>
  </dependency>
<!--spring-test-->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.3.23</version>
      <scope>test</scope>
  </dependency>
<!--spring mvc web-->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.23</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.3.23</version>
  </dependency>
<!--servlet和jsp依赖,    可选-->
  <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
  </dependency>
  <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
  </dependency>
</dependencies>

配置文件

在web.xml中配置前端控制器DispatcherServlet
<?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">

    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        读取springmvc.xml中的配置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
<!--        启动tomcat就配置-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
<!--        配置DispatcherServlet的映射路径是/,除了jsp之外的其他所有资源-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

注意:

1.配置前端处理器(DispatcherServlet),前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制

2.前端控制器配置的url-pattern/,是除了JSP之外其他所有的资源;如果想要配置所有的资源,可以用/*

3.DispatcherServlet可以设置参数init-param,参数的名字是contextConfigLocation,用于定义了要装入的Spring 配置文件。

这里不配置init-param也可以,请看0x04_框架搭建的配置细节问题

4.关于视图解析器的配置,见0x04_框架搭建的配置细节问题

springmvc.xml

在resources目录下创建Spring MVC的核心配置文件springmvc.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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
">

<!--    扫描-->
    <context:component-scan base-package="com.bones"/>
</beans>

删除controller层的MyServet,准备SpringMVC框架下的开发。

controller层的代码

在controller层创建MyController类。

MyController

package com.bones.controller;

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

@Controller
public class MyController {
    @RequestMapping("/aaaController.do")
    public String aaaControl(){
        System.out.println("aaaControl invoked");
        return "aaa.jsp";
    }
}

访问http://localhost:8080/SpringMVC_pro01_buildAProject_war_exploded/aaaController.do成功跳转到aaa.jsp

image-20221106170350745

注意:

1.controller层的类加上注解@Controller,包扫描时会当作controller

2.映射路径是定义在方法上的,这个和Servlet不同:@RequestMapping("/aaaController.do")

由此,相比于Servlet,SpringMVC中只要写一个方法就可以对应一个映射路径,这样可以大大减少类的数量。

3.加上注解@RequestMapping的方法,返回值这里写的是String,就是页面跳转的路径。

0x04_框架搭建的配置细节问题

DispatcherServlet的参数

在前面的web.xml中,配置前端控制器DispatcherServlet中的参数:

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value>
</init-param>

其实不配置也可以,因为DispatcherServletcontextConfigLocation参数有默认值:

可以自定义servlet.xml配置文件的位置和名称,默认为WEB-INF目录下,名称为[<servlet-name>]-servlet.xml,如spring-servlet.xml

比如:在WEB-INF目录下有和springmvc.xml文件内容一样的配置文件spring-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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
">

<!--    扫描-->
    <context:component-scan base-package="com.bones"/>


</beans>

此时应该把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">

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        读取springmvc.xml中的配置-->
<!--        <init-param>-->
<!--            <param-name>contextConfigLocation</param-name>-->
<!--            <param-value>classpath:springmvc.xml</param-value>-->
<!--        </init-param>-->

<!--        启动tomcat就配置-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
<!--        配置DispatcherServlet的映射路径是/,除了jsp之外的其他所有资源-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

项目一样生效

以上情况用的极少,不建议这么使用,一般会将配置放在resources目录下。

RequestMapping注解

前面的实验中,@RequestMapping注解加在方法前,可以明确的减少类的数量。

@RequestMapping也可以加在类前面,此时相当于一个命名空间,即访问该 Controller 下的任意方法都需要带上这个命名空间。

比如:

package com.bones.controller;

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

@Controller
@RequestMapping("/bones")
public class MyController {
    @RequestMapping("/aaaController.do")
    public String aaaControl(){
        System.out.println("aaaControl invoked");
        return "aaa.jsp";
    }
}

此时访问

http://localhost:8080/SpringMVC_pro01_buildAProject_war_exploded/aaaController.do

image-20221106194918749

显然上面的路径忽略了加在类上的命名空间,

按照命名空间的用法,如果访问

http://localhost:8080/SpringMVC_pro01_buildAProject_war_exploded/bones/aaaController.do

image-20221106195019549

此时显示要访问(请求转发)的文件为找到,因为上面返回的是“aaa.jsp”,而不是“/aaa.jsp”。

将代码改为:

package com.bones.controller;

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

@Controller
@RequestMapping("/bones")
public class MyController {
    @RequestMapping("/aaaController.do")
    public String aaaControl(){
        System.out.println("aaaControl invoked");
        return "/aaa.jsp";
    }
}

热部署项目之后,访问:

http://localhost:8080/SpringMVC_pro01_buildAProject_war_exploded/bones/aaaController.do

可以正常访问(请求转发):

image-20221106195226574

配置视图解析器

根据上面的MyController类,就可以在springmvc.xml中配置前缀和后缀:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" value=".jsp"/>
</bean>
image-20221106195749939

此时MyController类中方法的return可以更加简单:

package com.bones.controller;

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

@Controller
@RequestMapping("/bones")
public class MyController {
    @RequestMapping("/aaaController.do")
    public String aaaControl(){
        System.out.println("aaaControl invoked");
        return "aaa";
    }
}

0x05_总结

  • web.xml中要配置前端控制器:
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        读取springmvc.xml中的配置-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>

<!--        启动tomcat就配置-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
<!--        配置DispatcherServlet的映射路径是/,除了jsp之外的其他所有资源-->
    <url-pattern>/</url-pattern>
</servlet-mapping>
  • springmvc.xml是SpringMVC框架的核心配置文件,里面需要配置包扫描和视图解析器:
<!--    扫描-->
<context:component-scan base-package="com.bones"/>
<!--    视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" value=".jsp"/>
</bean>
  • controller层:

1.加上注解@Controller

@Controller标记的类实际上就是个SpringMVC Controller对象,它是一个控制器类,而@Contoller注解在org.springframework.stereotype包下。

2.@RequestMapping标记的方法会被分发处理器扫描识别,将不同的请求分发到对应的接口上。

@RequestMapping注解可以加在方法上,也可以加在类上:

@RequestMapping 有两种标注方式,一种是标注在类级别上,一种是标注在方法级别上。标注在方法上时,value 表示访问该方法的 URL 地址。标注在类上时,value 相当于一个命名空间,即访问该 Controller 下的任意方法都需要带上这个命名空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值