Spring MVC(1):文件配置 & 使用示例

Spring MVC 体系概述


 Spring MVC 是基于 Model2 实现的 MVC 框架,Model 2是经典 MVC 模型在 Web 应用中的变体,这个改变是源于 HTTP 协议的无状态性;
Spring MVC 模型的整体架构如下:

其中 DispatcherServlet 处于核心地位,负责协调和组织不同的组件以完成请求处理并返回响应结果;DispatcherServlet 就是 Spring MVC 的前端 Servlet , 负责接受所有请求,并将具体的工作委托给其他组件进行处理,这一点如同其他大部分的 MVC 框架;

以下是 Spring MVC 处理请求的整体过程

1)客户端发送一个 HTTP 请求,Web 服务器接受这个请求,如果请求路径符合 DispatcherServlet 的请求路径(web.xml 中定义),则 Web 服务器将该请求交给 DispatcherServlet 进行处理;

2)DispatcherServlet 接受请求后,根据请求的消息和 HandlerMapping 的配置查找处理请求的处理器 Handler(即可以把 HandlerMapping 看成路由控制器,Handler 看成目标主机);

3)当 DispatherServlet 获取相应的 Handler 后,通过 HandlerAdapter 对 Handler 进行封装,再以统一的适配器接口调用 Handler(这是由于 Spring MVC 并没有定义 Handler 接口,任何一个 Obejct 都可以作为 Handler);

4)Handler 完成业务逻辑处理后,返回一个 ModelAndView (包含了视图逻辑名,模型数据信息)给 DispatcherServlet;

5)DispatcherServlet 借助 ViewResolver 解析 ModelAndView 中的逻辑视图名到真实视图对象;

6)当获取真实视图对象 View 后,DispatcherServlet 使用该 View 对象对 ModelAndView 中的模型数据进行解析;

7)客户端获取响应结果(可能为一个HTML,XML,JSON 或 图片、PDF 等);




配置 DispatcherServlet 

在使用 Spring MVC 的第一步是在 web.xml 中对 DispatcherServlet 进行配置,一个示例的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app .....>
    <!--加载 Spring WebApplicationContext: Service 层和 Dao 层的配置文件加载到 Spring 容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--启动 Spring 容器监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--以下部分为 DispatcherServlet 的配置-->
    <!--声明 DispatcherServlet-->
    <servlet>
        <servlet-name>assad</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--配置 DispatcherServlet 的匹配 URL 模式-->
    <servlet-mapping>
        <servlet-name>assad</servlet-name>
        <url-pattern>/</url-pattern>     <!--匹配任何url请求,像 *.html 匹配 html 页面请求-->
    </servlet-mapping>
    
</web-app>


DispatcherServlet 遵循约定大于配置的原则,在大多情况下,用户无需进行额外的配置,只需配置 DispatcherServlet 的 <servlet> 和 <servlet-mapping> ,其中一个 <servlet-mapping> 可以配置多个<url-pattern>;
其他的 DisptahcerServlet 默认配置参数,可以通过 <servlet> 的 <init-param> 指定 ,如下:

namespace

DispatcherServlet 的命名空间,默认为 <servlet-name>-servlet(即:WEB-INF/<servlet-name>-servlet.xml ),
显示指定该属性后,可以将该配置文件的路径更改为 WEB-INF/<namespace>.xml ; 

contextConifgLocation

如果 DispatcherServlet 对应的上下文配置文件有多个,可以用该属性指定这些配置文件的路径,如:
<contextConifgLocation>classpath:smaple1.xml, classpath:sample2.xml</contextConifgLocation>

publishContext

指定 DispatcherServlet 是否将 WevApplicationContext 分布到 ServletContext 的属性列表中(通过 DispatcherServlet#getServletContextAttributeName() 方法可以从ServletContext 中获取 WebApplicationContex 的实例),
默认值为 true;

publishEvents

指定 DispatcherServlet 处理完一个请求后,是否需要向容器发布一个 ServletRequesthandledEvent 事件,
默认值为 true;如果容器中没有任何事件监听器,可以将改值设置为 false 以提高性能;




一个简单的示例


Spring MVC 应用开发一般包括以下几个步骤:
1)配置 web.xml ,指定业务层对应的 Spring 配置文件,定义 DispatcherServlet;
2)编写处理请求的处理器 Handler;
3)编写视图对象;
4)配置 Spring MVC 的配置文件,使控制器、视图解析器等生效;

以下是一个简单的 Spring MVC 示例,演示一个登陆业务流程;

示例模块:
site/assad/domain/User,LoginLog(领域对象)
site/assad/dao/UserDao,LoginLogDao(DAO对象)
site/assad/service/UserService(Service对象)
site/assad/web/LoginController(Web层控制器对象)
site/assad/applicationContext.xml(Spring 容器配置文件:针对 Dao,Service 层的配置)
webapps/WEB-INF/web.xml
webapps/WEB-INF/assad-servlet.xml(Spring-mvc 配置文件:针对 Web 层的配置)
webapps/WEB-INF/login/login.jsp,login_success.jsp(View 层  jsp视图文件)


1)编写 web.xml ,配置 Dispatcher

<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
    <!--加载 Spring WebApplicationContext: Service 层和 Dao 层的配置文件加载到 Spring 容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--启动 Spring 容器监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--声明 DispatcherServlet-->
    <servlet>
        <servlet-name>assad</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--配置 DispatcherServlet 的匹配 URL 模式-->
    <servlet-mapping>
        <servlet-name>assad</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--配置请求编码过滤器,解决HttpRequest传输时中文乱码的问题-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>
以上配置文件,为了解决 Request 中文乱码问题,配置了一个编码过滤器;

2)编写 Web 层的控制器(处理器Handler)
Spring MVC 通过 @Controller ,或 @RestController 可以标注一个控制器对象,主要负责响应 URL 请求,对其进行逻辑处理后,转发到视图对象(逻辑视图);
以下控制器,分别将 “/login” “/loginCheck” 的url请求进行处理后,分别映射到 “login/login”,“login/login_success” 逻辑视图;
package site.assad.web;

@RestController  //标记为一个 Spring MVC 的Controller
public class LoginController {

    @Autowired
    private UserService userService;

    //响应 index.html 请求,并将其转发到 login/login 逻辑视图
    @RequestMapping(value="/login")
    public String loginPage(){
        return "login/login";
    }

    //响应 loginCheck.html 请求
    @RequestMapping(value="/loginCheck",method = RequestMethod.POST)
    public ModelAndView loginCheck(HttpServletRequest request, LoginCommand loginCommand ) throws UnsupportedEncodingException {
        //验证登陆用户密码
        boolean isValidUser = userService.checkUser(loginCommand.getUserName(),loginCommand.getPassword());
        //验证结果处理逻辑
        if(!isValidUser){
            //验证失败,返回 login/login 物理视图,并携带错误信息
            return new ModelAndView("login/login","error", new String("用户名或密码错误".getBytes(),"UTF-8"));
        }else{
            User user = userService.findUserByName(loginCommand.getUserName());
            user.setLastIp(request.getLocalAddr());
            user.setLastVisit(new Date());
            userService.loginSuccess(user);                         //执行验证成功的业务操作
            request.getSession().setAttribute("user",user);  //设置 session
            //验证成功,转发到 login/login_success 逻辑视图
            return new ModelAndView("login/login_success");
        }
    }
}

3)编写 View 视图文件
在本例子中用 JSP 编写视图文件,一般项目的视图文件会放置到 webapps/WEB-INF/views 路径中(当然也可以根据需求自定义路径);
例子中包含2个JSP文件,“login/login.jsp” 为登陆页面(同时负责登陆失败的信息显示),“login/login_success.jsp” 为登陆成功页面;
login/login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Login Page</title>
</head>
<body>
<p>
    <c:if test="${!empty error}">
        <c:out value="${error}" />
    </c:if>
</p>
    <form action="<c:url value="/loginCheck" />" method="post">
        <label>用户名</label><input type="text" name="userName" /><br />
        <label>密码</label><input type="password" name="password"/><br />
        <input type="submit" value="登陆" />
        <input type="reset" value="重置信息" />
    </form>
</body>
</html>
login/login_success.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Login Success Page</title>
</head>
<body>
    <h1>登陆成功!${user.name}, 您当前的积分为 ${user.credits} </h1>
</body>
</html>

4)编写 Spring-mvc 配置文件
spring-mvc 配置文件默认命名为 <DispatcherServlet-name>-servlet.xml,其中 <DispatcherServlet-name>为 web.xml 中DispatcherServlet 节点的名称,如示例中为 “assad-servlet.xml” ;
一般该文件默认位于 web.xml 同目录下;
assad-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <!--自动注入 site.assad.web 包的 bean-->
    <context:component-scan base-package="site.assad.web" />

    <!--配置视图解析器,映射逻辑视图名的解析-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:viewClass="org.springframework.web.servlet.view.JstlView"
          p:prefix="/WEB-INF/views/"
          p:suffix=".jsp" />
</beans>
示例代码配置了一个 JSP 视图解析器,配置逻辑视图映射到物理视图的规则为:物理视图文件路径 =“ /WEB-INF/views/ ” + 逻辑视图名 + “.jsp ” ;
如:“login/login” 逻辑视图名映射为 “ /WEB-INF/views/login/login.jsp ” 的物理视图文件;



附:示例代码使用 gradle 作依赖管理,通过 build.gradle 配置的 gretty 插件启动内嵌 tomcat,通过 url ” http://127.0.0.1:8080/login  “ 即可测试登陆流程;
构建文件为:
build.gradle
group 'site.assad'
version '1.0'

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'org.akhikhl.gretty'
sourceCompatibility = 1.8

//导入 gretty 调试插件
buildscript{
    repositories{
        jcenter()
    }
    dependencies{
        classpath 'org.akhikhl.gretty:gretty:1.2.4'
    }
}

repositories {
    mavenCentral()
}

ext{
    servlet_api_version = '3.0-alpha-1'
    jstl_version = '1.2'
    jsp_api_version = '2.0'
    spring_version = '4.3.11.RELEASE'
    log4j_core_version = '2.9.0'
    log4j_api_version = '2.9.0'
    junit_version = '4.12'
    commons_dbcp_version = '1.4'
    mysql_connector_java_version = '5.1.44'
    hibernate_version = '5.2.12.Final'
}

dependencies {
    //log4j 依赖
    testCompile "org.apache.logging.log4j:log4j-core:${log4j_core_version}"
    testCompile "org.apache.logging.log4j:log4j-api:${log4j_api_version}"
    compile "org.apache.logging.log4j:log4j-core:${log4j_core_version}"
    compile "org.apache.logging.log4j:log4j-api:${log4j_api_version}"

    //servlet 依赖
    compile "javax.servlet:servlet-api:${servlet_api_version}"
    compile "javax.servlet:jstl:${jstl_version}"
    compile "javax.servlet.jsp:jsp-api:${jsp_api_version}"

    //spring core 依赖
    compile "org.springframework:spring-beans:${spring_version}"
    compile "org.springframework:spring-core:${spring_version}"
    compile "org.springframework:spring-context:${spring_version}"
    compile "org.springframework:spring-context-support:${spring_version}"

    //spring dao 依赖
    compile "org.springframework:spring-jdbc:${spring_version}"
    compile "org.springframework:spring-tx:${spring_version}"
    //数据源和数据库驱动:使用 Mysql,DBCP数据源
    compile "commons-dbcp:commons-dbcp:${commons_dbcp_version}"
    compile "mysql:mysql-connector-java:${mysql_connector_java_version}"

    //spring test 依赖,使用 Junit
    compile "org.springframework:spring-test:${spring_version}"
    testCompile "junit:junit:${junit_version}"

    //spring mvc 框架
    compile "org.springframework:spring-webmvc:${spring_version}"
}
//设置 gretty 参数
gretty {
    port = 8080
    servletContainer = 'tomcat8'
    contextPath = "/"
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值