spring开发笔记(3)spring mvc原理及入门
我们开发的web应用程序是要放到tomcat之类的web容器里运行的,当http请求到来时,tomcat会把请求交给web应用的某个servlet处理。在开发web应用时,自然而然的,我们会想到有多少种http请求需要处理,就编写多少个servlet,然后在web.xml里配置好servlet和http请求uri的对应关系。比如,要处理/add、/query、/delete、/update这4个请求,可以编写AddHttpServlet、QueryHttpServlet、DeleteHttpServlet和UpdateHttpServlet这4个servlet,然后在web.xml文件里配置如下:
<servlet>
<servlet-name>addServlet</servlet-name>
<servlet-class>com.myTest.servlet.AddHttpServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>queryServlet</servlet-name>
<servlet-class>com.myTest.servlet.QueryHttpServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>deleteServlet</servlet-name>
<servlet-class>com.myTest.servlet.DeleteHttpServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>updateServlet</servlet-name>
<servlet-class>com.myTest.servlet.UpdateHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addServlet</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>queyrServlet</servlet-name>
<url-pattern>/query</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>deleteServlet</servlet-name>
<url-pattern>/delete</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>updateServlet</servlet-name>
<url-pattern>/update</url-pattern>
</servlet-mapping>
这样,当用户访问/add时,tomcat就会调用AddHttpServlet来处理;访问/query时,tomcat会调用QueryHttpServlet来处理。以此类推,访问/update、/delete时分别调用UpdateHttpServlet和DeleteHttpServlet来处理。显然,对于每个请求都这样配置一遍是很麻烦的。前面讲了spring的种种好处,那我们在开发web应用时可不可以获得spring带来的便利呢?答案是可以的,spring家族里利用spring容器来帮助我们开发web应用的框架,就是spring mvc。
spring mvc的原理
spring mvc提供了一个DispatcherServlet(类的全名是org.springframework.web.servlet.DispatcherServlet),在web.xml文件里,我们一般都这么配置它:
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
也就是说,让DispatcherServlet接管(即处理)所有的http请求。显然DispatcherServlet是spring mvc框架提供的类,我们不能也无法修改它的代码,那么它怎么知道每个具体的http请求该如何处理呢?
所谓mvc,就是model-view-controller的首字母缩写,就是模型-视图-控制器。控制器(controller)就是用来处理具体的http请求的组件。我们需要编写好处理各个http请求的controller类。DispatcherServlet在接收到http请求后,其实它自己不会去处理,而是根据http请求uri的映射规则,将请求转交给相应的controller对象处理。
前面已经学过,spring容器是用来自动创建并管理对象的,显然,controller对象的创建工作也应当交给spring容器来负责(不仅是controller对象,web应用的业务层的serivce对象、数据层的dao对象也应当交给spring容器来创建和管理)。DispatcherServlet在启动时会创建一个spring容器(我们需要告诉spring容器我们的代码在哪个包里,以便spring容器去这个包扫描),spring容器在启动时又会自动创建好所有的controller对象(包括业务层的对象)。DispatcherServlet在初始化时会创建好http请求uri和controller对象的映射关系。当一个http请求到达时,会根据http请求的uri,从spring容器中获取相应的controller对象,将请求交给这个controller对象处理。
示例
下面我们一步步来搭建一个springmvc工程。
1.首先创建一个名为mvc-demo的空的maven工程:
2.修改pom.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.mytest</groupId>
<artifactId>mvc-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
工程的打包方式为war,引入spring框架以及springmvc的相关依赖。
3.在工程的src/main路径下创建webapp目录,在webapp目录下创建WEB-INF目录,在WEB-INF目录下创建web.xml文件,这样,打包后的工程就是一个web应用程序了,可以放到tomcat容器中运行:
4.在web.xml文件中添加如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.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>
定义了一个DispathcherServlet,<url-patterm>的值为"/",表示它接管所有的http请求。注意,这里给DispathcherServlet提供了一个名为"contextConfigLocation"的初始化参数,其值为"classpath:spring.xml"。前面我们说过,DispathcherServlet在初始化时会创建一个spring容器,这个参数就是用来告诉DispathcherServlet,用spring.xml这个文件来对spring容器进行配置。也就是说,这里的spring容器我们采用的是基于xml文件的配置方式。load-on-startup设置为1,表示让tomcat在启动时就创建好DispathcherServlet的实例。
5.在资源文件目录resources下创建spring.xml文件:
6.在spring.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: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-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd" >
<context:component-scan base-package="com.mytest" />
</beans>
配置文件中其实就是一句话,告诉spring容器去扫描"com.mytest"这个包(我们的代码都位于com.mytest包下)。spring容器在启动时会去扫描“com.mytest”这个包下的所有类,为所有标注了@Bean、@Controller、@Service、@Component之类注解的类创建对象并装配好。
7.接下来,开始着手编写业务代码。我们编写的源代码都保存在src/main/java路径下,在该路径下创建com.mytest包,在该包下创建controller包和service包,然后在controller包下创建HelloController类,service包下创建HelloService接口。在service包下创建impl包,在impl包下创建HelloServiceImpl类:
HelloController的内容如下:
package com.mytest.controller;
import com.mytest.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/")
public class HelloController {
@Autowired
private HelloService helloService;
@RequestMapping("hello")
@ResponseBody
public String doHello(@RequestParam(value = "name", required = true) String name) {
return helloService.sayHello(name);
}
}
@RequestMapping注解定义了Controller类(或方法)和http请求uri的映射关系。@RequestMapping注解既可以标注在类上,也可以标注在方法上。标注在类上,那么就应用到这个类的所有方法上。标注在类上的@RequestMapping提供初步的请求映射信息,标注在方法上的@RequestMapping则提供进一步的请求映射信息。
HelloController类上的@RequestMapping的值是"/",它的doHello方法上的@RequestMapping的值是"hello",因此,当请求"/hello"到来时,DispatherServlet会将请求交给HelloController的doHello方法来处理。前面说DispatherServlet会根据uri的映射关系从spring容器中获取相应的controller对象来处理,更进一步说,uri其实是和controller上的方法建立映射关系的。
doHello方法上标注了@ResponseBody注解,表示将方法返回的字符串作为http response直接返回客户端。doHello方法还有个参数为name,其上加了@RequestParam注解,表示http请求应当携带名为name的参数过来。
HelloService接口的代码如下:
package com.mytest.service;
public interface HelloService {
String sayHello(String to);
}
HelloServiceImpl类的代码如下:
package com.mytest.service.impl;
import com.mytest.service.HelloService;
import org.springframework.stereotype.Service;
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String to) {
return "hello " + to;
}
}
8.打开工程上的maven命令行,输入mvn clean package,编译所有源代码,并将整个工程打成war包。输出的包文件在工程的target目录下,名称为mvc-test-1.0-SNAPSHOT.war,将这个文件拷贝到tomcat的webapps目录下,改名为mvc-test.war,然后启动tomcat,可以看到tomcat把war包解压到了webapps目录下的mvc-test目录中,mvc-test目录的内容如下:
可以看出,工程里资源文件目录resources下的资源文件,打包后在WEB-INF目录的classes目录下。
9.在浏览器中输入http://localhost:8080/mvc-test/hello?name=tom,可以看到http响应的结果:
至此,我们就搭建了一个最基本的spring mvc应用,不过这个功能非常简单,离实际生产环境的应用还很远。生产环境下的应用,还需要添加许多功能和配置。
推荐阅读
-
spring开发笔记(3)spring mvc原理及入门
-
博客开发笔记一——Spring3最小配置 博客分类: 个人独立博客计划 注解Spring 3配置
-
spring boot开发web api应用实践(一)入门 博客分类: spring boot 实践笔记 spring boot入门教程
-
spring mvc 原理及应用 博客分类: Java
-
spring mvc 原理及应用 博客分类: Java
-
Spring学习(二)---在IoC容器中装配Bean 博客分类: Spring 3.x 企业应用开发笔记 springbeanioc框架
-
Java学习笔记-全栈-web开发-14-Spring入门&AOP编程&Spring注解开发&Spring事务
-
基于Spring MVC 简介及入门小例子(推荐)
-
Java Spring开发环境搭建及简单入门示例教程
-
基于Spring MVC 简介及入门小例子(推荐)