1、什么是mvc?
步骤二.请求的接收(拦截)
在上面的文件中,我们配置了一个叫做learnspring的servlet,它会拦截所有后缀为.do的请求。
看完这段代码,你会不会有点疑惑,这个是用注解的方式进行的配置,难道springmvc可以不用任何其他的配置就能自己去初始化注解吗?别急,接着往下看。
model-view-control的缩写,百度百科上定义这是一种软件设计典范,使用一种数据、业务逻辑、页面分离的方式组织代码。我个人把这个理解为一种大的设计模式,像工厂模式、代理模式都是在编写代码时遇到具体问题的一种解决方法,但是mvc是整个软件的设计模式,是一个大的框架。具体的mvc解释在网上很多,我现在也没有理解它的精髓。我自己写东西的时候总觉得mvc很臃肿,需
要些很多代码才能完成一个功能,也许以后项目实战多了会用好的吧。
2、
mvc中web的请求与响应
一次http请求可以被以下图所表示,下图中的服务器就是mvc中的controller(控制器)。我们在一个网页中的每一次
点击每一次刷新都会向服务器发送request,然后服务器就会寻找能够响应这个request的类或者说方法,然后将request处理之后将结果返回给我们。
我们可以看一下一个简单的登陆的mvc过程。
3、spring mvc
spring mvc是现在比较流行的一个web mvc框架,它允许我们采用注解的方式,进行controller层的搭建。
下面是spring文档中的一幅原理图,从图中可以看出,所有的请求都会被一个叫做front controller(前端控制器)
的东西拦截,然后由这个front controller来控制请求的处理。
话不多说,还是直接看代码,这样比较容易理解。我们以用一个登陆的例子,然后按照一个请求的产生与结束来进行讲解。
首先,是工程的搭建,我用的maven搭建工程,下面是引入的jar包,另外还有jstl.jar和standard.jar,需要手动引入,在maven中没有。
pom文件:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.learnspring</groupId> <artifactId>learnspring</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>learnspring Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>3.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>3.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.2.1.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.2.0.RELEASE</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build> </project> |
项目的文件目录(注意,对于java源代码,只要关心package web里面的就行了
)。
环境搭建完了,下面我们开始真正的编码。
步骤一.请求的产生
只有用户对页面进行了某些操作才能产生请求发送给后台,因此我们先写一个登陆页面login.html,在这个页面里,我们可以产生一个/req/login.do的get请求,并将名称和密码传给后台。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="../req/login.do" method="get"> <label>name:</label><input name="name"> <label>password:</label><input name="password" type="password"> <input type="submit" value="submit"> <input type="reset" value="reset"> </form> </body> </html> |
在之前关于原理的图中我们看到,所有的请求都应该先被一个前端控制器拦截下来,然后由这个controller进行分发,在springmvc中,提供了一个DispatcherServlet作为前端控制器。既然是已经有的类,那么我们只需要进行配置就可以使用它。我们在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>learnspring</display-name> <servlet> <servlet-name>learnspring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>learnspring</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app> |
步骤三.请求的分配与处理
好了,如果到现在没有做错的话,我们的请求已经可以安全到达前端控制器了,那么前端控制器怎么将请求分发出去呢?下面我们就来创建真正的业务Controller。我们在com.example.web包下面创建一个LoginController类,用来处理登陆的请求。代码如下:(注意看注释)
package com.example.web;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;/*** Created by Administrator on 2016/4/7.*/@Controller//声明这是一个Controller类,这样服务器初始化的时候就能被spring容器识别@RequestMapping(value = "/req")//这是声明请求的名称(路径)用的public class LoginController {@RequestMapping(value = "/login.do",method = RequestMethod.GET)//和前一个requestmapping组合形成了名为/req/login.do的请求public Object login(@RequestParam String name, @RequestParam String password){//表示这个请求接收名为name和password的参数String data_password = getPasswordByName(name);if(password.equals(data_password)){return "index" ;//返回字符串index,它的本意是向返回一个index.html页面}else{return "login" ;//如果密码不对,就返回login.html页面}}String getPasswordByName(String name){//根据名称获取密码return "admin" ;}} |
这样,我们对请求的分发和处理都结束了。
那好,我们就来创建这个xml文件:
步骤三.对结果的渲染和发送
在上一步中,我们在Controller里面返回了index/login字符串,显然,我们的本意是想要返回一个index.html页面或者login.html页面,但是怎么把字符串变成页面呢?还记得之前的原理图里面有一个view template吗?我们们通过一个叫ViewResolver的东西对Controller返回的字符串进行转换。当然,这个前端控制器一样,是springmvc为我们提供的,这次是UrlBasedViewResolver类。显然,这也需要一个配置文件,我们在web.xml文件的同一级目录下创建一个名叫learnspring-servlet.xml的文件,记住,这个文件是必须的,而且命名有要求,必须是你设定的servlet的名称+减号+servlet.xml,至于原因,文档里有解释:
Upon initialization of a
DispatcherServlet , Spring MVC looks for a file named
[servlet-name]-servlet.xml
in the
WEB-INF
directory of your web application and creates the beans defined there, overriding the definitions of any beans defined with the same name in the global scope.
在初始化DispatcherServlet的同时,springmvc会在web-inf文件夹下寻找一个名为
[servlet-name]-servlet.xml的文件,然后创建在这个文件中定义的相关的bean。
|
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="com.example.web"/> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/pages/"/> <property name="suffix" value=".html"/> </bean> </beans> |
在这个文件里面,我们定义了一个viewResolver,它是一个UrlBasedViewResolver类,有三个属性,viewClass、prefix和suffix。显然,prefix是某种前缀,suffix是某种后缀,我们的Controller返回一个字符串的时候,这个viewResolver会自动的将前缀和后缀加到那个字符串上,然后返回相应的页面。比如我们之前返回的login,现在就变成了/pages/login.html了。
OK,这样一个简单的spring mvc程序就写好了,启动服务器试一下。注意我们要学会看服务器的日志,我启动的时候有这么一段,这说明一个名为/req/login.do的get类型请求已经被服务器初始化了,我们只要以正确的url访问就可以了。