猿蜕变系列3——SpringMVC之初体验

时间:2022-07-22
本文章向大家介绍猿蜕变系列3——SpringMVC之初体验,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

看过之前的spring系列文章,相信你对java方面的基础有了一定的认识。经过之前的进化和思考的锻炼,也该是时候像模像样的做一些事情了。比如框架的学习。

Spring MVC 又叫做Spring Web MVC,现在已经成功的融合到Spring Web Flow里了。

顾名思义,MVC嘛,Spring MVC 是一个MVC框架嘛。我们之前已经学习一些了web开发的动态技术,我们为了处理客户端发起的请求,使用servlet去获取请求参数,根据参数做不出同的响应(比如调用service的业务代码,实现业务需求,转发请求、重定向等等)。之前,我们也聊了聊MVC的开发模式,也聊了聊MVC的web框架。虽然我们的框架很简陋,但还是有一点点框架的雏形的。没错,web服务器(姑且就理解为tom猫吧)提供的http编程处理接口是servlet,所以所谓的MVC框架其都是对servlet进行了封装,解决web开发中框架性功能的软件。

Web框架在发展的过程中也有很多不错的产品。比如大名鼎鼎的struts,想当年一提起三大框架ssh(Struts2 SpringHibernate),其中第一个s可是struts或者是struts2,但是由于struts2因为OGNL引起的安全性问题,导致很多的公司从入门到精通,再从精通到放弃。再加上SpringMVC本来就是Sprig生态圈的产品,和Spring几乎是天然融合的,很快就快速扩张了市场,目前Java Web 方面最为流行的Web MVC框架也就是Spring MVC了。之前我们聊到了框架的作用,其中很重要的一个就是,框架其实是一个“施工标准”——好嘛,既然是施工标准,自然是各大包工头的硬性要求了。不黑不吹,spring MVC 早就是Java工程师的招聘硬性要求了。

使用框架有利于更规范的编码,框架也提供了很多典型场景的公共解决办法,提供了很多类和方法,大大简化了程序员的开发工作。接下来,就让我们一起来学习Spring MVC吧。

我们采用了一个比较稳定的版本4.2.4RELEASE。

第一步

我们依然使用Maven来创建一个web项目(7天教程里有不多说了),我们要学的是MVC框架嘛,自然离不开web。当然,如果你愿意不辞辛劳的去手动下载各个jar包,我也没啥意见。

第二步

修改我们的pom.xml文件,我们这次做一个简单的程序,我们依赖spring-webmvc就好:

<?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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.pz.study.frame</groupId>
  <artifactId>springMVC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <name>springMVC Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
   
       <!--servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- -->
        <dependency>
                     <groupId>com.alibaba</groupId>
                     <artifactId>fastjson</artifactId>
                     <version>1.2.8</version>
              </dependency>
             
               <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
  </dependencies>
 
  <build>
    <finalName>springMVC</finalName>
     <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    <pluginManagement><!-- lock down plugins versions to avoid using Mavendefaults (may be moved to parent pom) -->
     <plugins>
         <!--maven插件-->
            <!--jdk编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <!--tomcat插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <!-- tomcat7的插件, 不同tomcat版本这个也不一样 -->
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 -->
                    <port>80</port>
                    <!-- 项目访问路径  本例:localhost:9090,  如果配置的aa,则访问路径为localhost:9090/aa-->
                    <path>/</path>
                    <uriEncoding>UTF-8</uriEncoding>
                </configuration>
            </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

第三步

编写spring MVC 的配置文件:在项目的java/src/resources(如果这个目录不是source floder记得将该目录设置为 source floder)目录中,新建配置文件spring-servlet.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: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/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd
      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"
       default-autowire="byName">
 
 
</beans>

第四步

配置Spring MVC中央控制器——DispatcherServlet,修改web.xml文件,在文件中加入以下内容:

<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-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
</servlet-mapping>

注意:param-value的值一定要和第三步创建的文件名保持一致,因为第三步中的文件内容,是定义spring MVC的相关配置的,而spring MVC的配置是由中央处理器去初始化的,所以param-value的值要保持和第三步的文件名一致。

第五步

编写Controller类,springMVC提供了org.springframework.web.servlet.mvc.Controller接口,用于让使用者去实现,springMVC的中央控制器会将请求转发给对应的Controller进行处理。其实就是对Servlet进行了封装,建立了请求和方法之间的映射关系(这个我们之前的“小框架”已经实现了),在servlet的基础上进行扩展,提供更加强大的功能。

package com.pz.web.study.springmvc.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
 
public class HelloSpringWebMVC implements Controller{
      
        public ModelAndViewhandleRequest(HttpServletRequest req, HttpServletResponse res) throws Exception {
      
        ModelAndView mv = new ModelAndView();
     mv.addObject("hello", "hello spring web mvc");
     mv.setViewName("/WEB-INF/hello.jsp");
     return mv;
 }
}

第六步

配置Controller,在spring-servlet.xml中增加配置:

<bean id="/helloWebMvc.do"class="com.pz.web.study.springmvc.controller.HelloSpringWebMVC" />

第七步

编写视图页面,在WEB-INF目录中创建一个hello.jsp的文件。

<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" isELIgnored="false" %>
<html>
<head>
<title>以第一springMvc程序</title>
</head>
<body>
${hello}
</body>
</html>

第八步

打包项目并启动。在浏览器中输入:http://127.0.0.1/helloWebMvc.do看到页面输出:hello spring web mvc就OK了。

在第四步中,我们对web.xml的内容做了修改,在web.xml中配置了一servlet——org.springframework.web.servlet.DispatcherServlet。这个DispatcherServlet是一个什么东西呢?DispatcherServlet,被叫做前端控制器,我们一直在强调一个事情,web服务器留给我们处理请求和响应的接口就是servlet.我们也自己定义过一个小框架,我们同样配置了一个servlet,那个servlet做了哪些事情呢?1.初始化程序配置,建立了url和我们要被调用的方法之间的映射关系。2.接收请求,据URL匹配请求,讲请求转发到对应的方法。

我们先回到我们编写HelloSpringWebMVC程序,在第四步中,我们对DispatcherServlet增加了以下配置:

load-on-startup:设置为1,我们之前学过servlet的生命周期,当这个值被设置为大于0的正整数时,当web服务器(也就是咱的tom猫)启动时,这个servlet就会被实例化,并且调用init方法。实际上我们自己编写的小框架也是这么搞的。

init-param:我们看到param-name是contextConfigLocation,param-value是classpath: spring-servlet.xml。为什么param-name是contextConfigLocation?因为DispatcherServlet中有这个属性(DispatcherServlet继承了FrameworkServlet,而contextConfigLocation是它的一个属性)这段内容是告诉DispatcherServlet,去查找class:path下,也就是WEB-INF目录下的子目录classes目录下的spring-servlet.xml文件。因为spring-servlet.xml文件里,描述了Spring MVC的具体使用情况。spring-servlet.xml这个文件名不是固定的,但是param-value的值一定是和Spring MVC的配置文件名一致,要不DispatcherServlet找不到配置文件,又怎么完成程序的初始化工作呢?

url-pattern:我们配置的是*.do,这其实是一个正则表达式规则,我们配置为*.do之后,所有以.do结尾的请求都会被web服务器匹配,然后转发到匹配DispatcherServlet中,最后DispatcherServlet再去将请求分发到具体的Controller中,我们自己编写的框架也是这样搞的,前端控制器嘛,自然需要控制所有需要转发到的请求,才能叫前端控制啊。当然,你也可以配置成其他的URL规则,只是主流不这样搞而已,对了你要是配置成/*,那所有的请求都要经过前端控制器DispatcherServlet 的处理,还可能引发其他问题,这个以后再说。

在第五步,我们编写了一个Controller,实现org.springframe.work.web.servlet.mvc.Controller接口,重写了handleRequest方法,我们看到方法的返回值为ModelAndView,ModelAndView是一个类,抽象了模型和视图,我们在方法中调用了两个方法:

mv.addObject("hello","hello spring web mvc");

表示我们向ModelAndView类的对象mv中,增加了一条数据,名字是hello,值是hello spring web mvc(这个值也可以是一个对象)。其实ModelAndView和我们之前用到的Map有些类似,在实现上,ModelAndView是将值放进了spring定义的ModelMap类,而这个类继承了java.util.LinkedHashMap^_^.

mv.setViewName("/WEB-INF/hello.jsp");

是告诉Spring MVC 需要返回的视图名称,和视图的位置(也就是方法执行完成后,需要转发的jsp文件的路径和位置)。

我们编写Controller,如果每一次都在程序的末尾写上mv.setViewName("/WEB-INF/xxx.jsp"),看起来会比较麻烦,因为往往我们在一套程序里用到的视图工具不会有那么多,很多时候就一个jsp.Spring MVC 提供了视图解析器来解决这个问题。

我们修改下配置文件spring-servlet.xml,我们在配置文件中增加一个视图解析器:

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

prefix属性,表示视图前缀,表示视图所在的路径,jsp文件存放的位置,这是一个相对位置,相对于webapp目录而言的,也就是webapp目录下的WEB-INF目录。 suffix表示视图后缀,即视图文件的后缀名,我们使用的是jsp,所以我们的后缀名是.jsp。 最后,我们修改下HelloSpringWebMVC的代码,将之前的:

mv.setViewName("/WEB-INF/hello.jsp");

修改为:

mv.setViewName("hello");

设置视图解析器以后我们就不用再写上完整的路径名了。