Java Web系列:Spring MVC 基础

1.Web MVC基础

MVC的本质是表现层模式,我们以视图模型为中心,将视图和控制器分离出来。就如同分层模式一样,我们以业务逻辑为中心,把表现层和数据访问层代码分离出来是一样的方法。框架只能在技术层面上给我们帮助,无法在思考和过程上帮助我们,而我们很多人都不喜欢思考和尝试。

2.实现Web MVC的基础

实现Web MVC基础可以概括为1个前段控制器和2个映射。

(1)前端控制器FrontController

ASP.NET和JSP都是以Page路径和URL一一对应,Web MVC要通过URL映射Controller和View,就需要一个前端控制器统一接收和解析请求,再根据的URL将请求分发到Controller。由于ASP.NET和Java分别以IHttpHandler和Servlet作为核心,因此ASP.NET MVC和Spring MVC分别使用实现了对应接口的MvcHandler和DispatcherServlet作为前段控制器。

ASP.NET中通过HttpModule的实现类处理URL映射,UrlRoutingModule根据URL将请求转发给前端控制器MvcHandler。Spring MVC中,则根据URL的配置,直接将请求转发给前端控制器DispatcherServlet。

(2)URL和Contrller的映射

ASP.NET MVC将URL和Controller的映射规则存储在RouteCollection中,前端控制器MvcHandler通过IController接口查找控制器。Spring MVC则通过RequestMapping和Controller注解标识映射规则,无需通过接口依赖实现控制i器。

(3)URL和View的映射

ASP.NET MVC 默认通过RazorViewEngine来根据URL和视图名称查找视图,核心接口是IViewEngine。Spring MVC 通过internalResourceViewResolver根据URL和视图名称查找视图,核心接口是ViewResolver。

3.Spring MVC快速上手

(1)Spring MVC初始化

ASP.NET MVC初始化需要我们在HttpApplication.Application_Start方法中注册默认的URL和Controller规则,Spring MVC由于采用注解映射URL和Controller,因此没有对应的步骤。ASP.NET在根web.config中配置了UrlRoutingModule可以将请求转发给MvcHandler,Spring MVC我们需要我们配置DispatcherServlet以及其对应的URL来达到接管所有请求的目的,Spring已经利用Servlet3.0定义的ServletContainerInitializer机制,为我们提供了默认的AbstractAnnotationConfigDispatcherServletInitializer,只要只需要像继承HttpApplication的MvcApplication一样,写一个MyWebApplicationInitializer。

(2)URL和View的映射

ASP.NET的RazorViewEngine内置了View的Path和扩展名.cshtml的规则。Spring MVC的internalResourceViewResolver没有提供默认值,因此如果我们如果不定义Path和扩展名,只需要MyWebApplicationInitializer即可。一般我们会指定将View放置在统一的视图目录中,使用特定的扩展名。Spring同样提供了DelegatingWebMvcConfiguration,我们只需写一个自己的AppConfig继承它,重写configureViewResolvers方法即可。完整的代码如下:

package s4s;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

@Configuration
@ComponentScan
class AppConfig extends DelegatingWebMvcConfiguration {

    @Override
    protected void configureViewResolvers(ViewResolverRegistry registry) {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        registry.viewResolver(viewResolver);
    }
}

(3)URL和Controller的映射

上文提到过Spring MVC和ASP.NET MVC的不同,不通过IController接口标识Controller,也不通过RouteCollection定义URL和Controller,取而代之的是两个注解:Controller和RequestMapping。我们简单的定义一个POJO MyController以及其简单的Home方法。并应用上述注解:

package s4s;

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

@Controller
public class MyController {

    @RequestMapping("/")
    public String Home() {
        return "home";
    }
}

添加/WEB-INF/views/home.jsp视图文件,就完成了最简单的示例。无需web.xml的任何配置。

(4)使用Model

ASP.NET将视图最终编译为WebViewPage<object>,View和Model是一一对应并且类型匹配的,Model可以是任意的POCO。Spring MVC中View和Model是一对多的,提供了ModelMap和其子类ModelAndView提供类似ASP.NET MVC中ViewResult的功能。ModelMap的基类是LinkedHashMap<String, Object>。

我们修改MyController的代码,使用ModelAndView来传递一个简单UserModel模型,作为参数的UserModel对象model和ASP.NET MVC中一样,会自动将请求参数映射到model的属性。返回值ModelAndView时和ASP.NET MVC的return View(viewName,model)类似。只不过因为Spring MVC模型是多个模型的列表,我们还需要指定返回模型的Name。

package s4s;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MyController {
    @RequestMapping("/")
    public ModelAndView Home(@ModelAttribute UserModel model) {
        model.setUserName(model.getUserName() + "~");
        return new ModelAndView("home", "model", model);
    }
}

class UserModel {
    String userName = "";

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

(5)使用View

修改home.jsp,添加jstl和spring的tag支持。由于Spring MVC中的View和ASP.NET MVC中的区别较大,没有办法指定View持有的Model类型也就没有了智能提示和错误检测的优势,一切回归到了脚本语言的时代。

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h2>spring tag</h2>
    <form action="<%=request.getContextPath()%>" method="get">
        <spring:bind path="model.userName">
            <input type="text" name="userName" value="${status.value}" />
        </spring:bind>
        <input type="submit" value="submit">
    </form>
    <h2>spring form tag</h2>
    <form:form modelAttribute="model" method="get">
        <form:input path="userName" />
        <input type="submit" value="submit">
    </form:form>
</html>

附上pom.xml。其中junit是可选的,jstl是View中使用jstl语法需要引入的。

<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>me.test</groupId>
    <artifactId>s4s</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>s4s Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>s4s</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4.Spring MVC的初始化机制

(1)应用初始化:

Spring实现了Servlet 3.0规范定义的javax.servlet.ServletContainerInitializer接口并通过javax.servlet.annotation.HandlesTypes注解引用了WebApplicationInitializer接口。因此在Servlet容器初始化时,在当前class path路径下的WebApplicationInitializer实现类的onStartup方法会自动执行(这和ASP.NET的Application_Start作用类似,在系列中的Java Web基础时曾经提到过)。

(2)依赖注入的初始化:

ASP.NET中我们在Application_Start中初始化依赖注入容器。在Spring MVC中,我们实现WebApplicationInitializer接口同样可以执行依赖注入的初始化。在Web环境中,我们使用的ApplicationContext接口的实现类为基于注解的AnnotationConfigWebApplicationContext(在系列中的Spring依赖注入基础中曾经提到过),但我们无需直接实现WebApplicationInitializer并手动初始化AnnotationConfigWebApplicationContext对象,因为Spring已经定义了AbstractAnnotationConfigDispatcherServletInitializer作为WebApplicationInitializer接口的实现类,已经包含了AnnotationConfigWebApplicationContext的初始化。

(3)依赖注入配置:

采用基于Annotation注解时可以通过@Configurateion指定POJO来替代web.xml配置依赖注入。同样,@ComponentScan可以替代web.xml中的扫描配置功能,使用ComponentScan配合Configurateion可以达到0xml配置的方式。上文中提到的Contrller相关的注解,都是启用ComponentScan后才会被扫描生效。

(4)DispatcherServlet的初始化:

AbstractAnnotationConfigDispatcherServletInitializer类的父类AbstractDispatcherServletInitializer中已经包含DispatcherServlet的初始化。相关类图如下:

5.Spring MVC的Action Filter

.NET MVC提供了众多Filter接口和一个ActionFilterAttribute抽象类作为Filter的基础,其中以实现了IAuthorizationFilter接口的AuthorizeAttribute拦截器最为我们熟知。Spring MVC则提供了基于HandlerInterceptor接口的众多接口、抽象类和实现类,其中也有和.NET MVC类似的权限验证UserRoleAuthorizationInterceptor拦截器。内置的拦截器可以满足大部分需求,为了省事图就画在一张上了,上面是Spring MVC的,下面是.NET MVC的。

关于模型验证和权限验证的部分以后再续。

总结

(1)MVC实现的要点是前端控制器、URL和Controller的映射、URL和View的映射

(2)MvcHandler和DispatcherServlet

(3)ServletContainerInitializer和HttpApplication.Application_Start

(4)RazorViewEngine和internalResourceViewResolver

(5)IMvcFilter和HandlerInterceptor

时间: 2024-11-03 21:28:25

Java Web系列:Spring MVC 基础的相关文章

[Java Web – 3A] – Spring MVC开发注意事项

1.使用Maven构建项目 2.SpringMVC 绝对路径的问题 首先要明确一点,在html中,资源文件也是有自己的URL,即href中是支持绝对路径.如下代码: <link href="<%=request.getContextPath() %>/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> 用浏览器打开后 <link href=&

Java Web系列:Spring Security 基础

Spring Security虽然比JAAS进步很大,但还是先天不足,达不到ASP.NET中的认证和授权的方便快捷.这里演示登录.注销.记住我的常规功能,认证上自定义提供程序避免对数据库的依赖,授权上自定义提供程序消除从缓存加载角色信息造成的角色变更无效副作用. 1.基于java config的Spring Security基础配置 (1)使用AbstractSecurityWebApplicationInitializer集成到Spring MVC 1 public class Securit

Spring MVC 基础

Spring MVC 基础 1.Web MVC基础 MVC的本质是表现层模式,我们以视图模型为中心,将视图和控制器分离出来.就如同分层模式一样,我们以业务逻辑为中心,把表现层和数据访问层代码分离出来是一样的方法.框架只能在技术层面上给我们帮助,无法在思考和过程上帮助我们,而我们很多人都不喜欢思考和尝试. 2.实现Web MVC的基础 实现Web MVC基础可以概括为1个前段控制器和2个映射. (1)前端控制器FrontController ASP.NET和JSP都是以Page路径和URL一一对应

Spring MVC 基础篇 1

Spring MVC基础篇  @RequestMapping使用 [email protected]RequestMapping 注解 进行请求映射 (1)指定Controller或者Method可以处理那些url请求. (2)适用范围:类定义上或者方法定义上都可以加. (3)在类定义处添加该注解是相对于WEB应用的根目录,在方法处是对类定义的请求处理的进一步细化.可以在类定义上没有添加该注解,但是方法定义上有该注解,此时 方法处的该注解标记的URL就是相对于WEB应用根目录. (4) 思考:此

java 使用框架Spring MVC批量上传图片

java 使用框架Spring MVC批量上传图片 运行环境:jdk1.8.0_17+tomcat 8 + spring:4.3.4+mybatis:3.2.7+ eclipse ide 2018+maven管理 最近写项目时候用到上传图片文件等功能之前写过没有总结,以及记录等,今天总结下写的批量上传图片功能 前段只需要把所有的选择的图片提交上来即可,后台会逐个处理,并且会在服务器或者当前电脑自己新建一个存放图片的文件夹,在application.properties配置里面你可以指定你所存放图

Java Web(3):JSP基础

JSP:Java Server Pages JSP 源代码包含了 JSP 元素和 Template data(<% %>标签以外的部分) JSP 文件最终都会转换成 Servlet 去执行,执行过程: JSP 语法:1.编译器指令:2.脚本语法:3.动作语法 注释: <!-- HTML注释 --> <%-- JSP注释 --%> <!-- <%=new java.util.Date()%> --> 编译器指令:包含在<%@  %>中

Java Web开发环境搭建基础[Windows篇]

1. 准备软件: JDK:(jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe) Tomcat:(apache-tomcat-7.0.54-windows-x86.zip) Eclipse:(eclipse-java-helios-SR1-win32.zip) MySQL:(mysql-5.5.20-win32.msi) MySQL JDBC:(mysql-connector-java-5.1.31.zip) Navicat for MySQL

(转)Java Web系列:Spring依赖注入基础

一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码

Java Web系列:Spring依赖注入基础

一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是可以专注业务逻辑.因此学习Spring Framework在架构和模式方面的结构和原理,对我们在架构和模块级别的理解帮助极大.Spring Framework(参考1)的宗旨是简化Java开发,主要的手段如下: (1)在架构上解耦:通过DI(依赖注入)管理类型依赖,通过AOP分离关注点,减少重复代码