本节书摘来自异步社区《Spring 3.0就这么简单》一书中的第1章,第1.6节,作者: 陈雄华 , 林开雄著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.6 展现层

业务层和持久层的开发任务已经完成,该是为程序提供界面的时候了。Struts MVC框架由于抢尽天时地利,成为当下最流行的展现层框架。但也有很多人认为Spring MVC相比较于Struts更简单、更强大、更优雅。此外,由于Spring MVC出自于Spring之手,因此和Spring容器没有任何不兼容性,显得天衣无缝。

Spring 1.5新增了基于注解的MVC,而且Spring 3.1还提供了REST风格的MVC,Spring MVC已经变得轻便、强大、易用。我们将会在本书的第8章中学习Spring MVC的详细内容。

1.6.1 配置Spring MVC框架
首先需要对web.xml文件进行配置,以便Web容器启动时能够自动启动Spring容器,如代码清单1-13所示。

代码清单1-13 自动启动Spring容器的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="1.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><!--①从类路径下加载Spring配置文件,classpath关键字特指在类路径下加载_-->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param>
_<!--②负责启动Spring容器的监听器,它将引用①处的上下文参数获得Spring配置文件地址-->_<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>…
</web-app>

首先,通过Web容器上下文参数指定Spring配置文件的地址,如①所示。多个配置文件可用逗号或空格分隔,建议采用逗号分隔的方式。在②处指定Spring所提供的ContextLoaderListener的Web容器监听器,该监听器在Web容器启动时自动运行,它会根据contextConfigLocation Web容器参数获取Spring配置文件,并启动Spring容器。注意需要将log4J.propertis日志配置文件放置在类路径下,以便日志引擎自动生效。

接下来,需要配置Spring MVC相关的信息,Spring MVC像Struts一样,也通过一个Servlet截获URL请求,然后再进行相关的处理,如代码清单1-14所示。

代码清单1-14 Spring MVC地址映射

…
<!-- Spring MVC的主控Servlet -->
<servlet> ①<servlet-name>viewspace</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>2</load-on-startup></servlet>
<!-- Spring MVC处理的URL --><servlet-mapping>② <servlet-name>viewspace</servlet-name><url-pattern>*.html</url-pattern>
</servlet-mapping>

在①处声明了一个Servlet,Spring MVC也拥有一个Spring配置文件(稍后会涉及),该配置文件的文件名和此处定义的Servlet名有一个契约:即采用-servlet.xml的形式。在这里,因为Servlet名为viewspace,所以在/WEB-INF目录下必须提供一个viewspace- servlet.xml的Spring MVC配置文件,但这个配置文件无须通过web.xml的contextConfigLocation上下文参数进行声明,因为Spring MVC的Servlet会自动将viewspace -servlet.xml和Spring其他的配置文件进行拼装。

在②处对这个Servlet的URL路径映射进行定义,在这里让所有以.html为后缀的URL都能被viewspace Servlet截获,进而转由Spring MVC框架进行处理。我们知道,在Struts框架中,一般将URL后缀配置为.do,在Webwork中一般配置为.action,其实,框架本身和URL模式没有任何关系,用户大可使用喜欢的任何后缀。使用.html后缀,一方面,用户不能通过URL直接知道开发者采用了何种服务端技术;另一方面,.html是静态网页的后缀,可以骗过搜索引擎,增加被收录的概率,所以推荐采用这种后缀。对于那些真正的无须任何动态处理的静态网页,则可以使用.htm后缀加以区分,以避免被框架截获。

请求被Spring MVC截获后,首先根据请求的URL查找到目标的处理控制器,并将请求参数封装成一个“命令”对象一起传给控制器处理,控制器调用Spring容器中的业务Bean完成业务处理工作并返回结果视图。

1.6.2 处理登录请求
POJO控制器类
首先要编写的是LoginController,它负责处理登录请求,完成登录业务,并根据登录成功与否转向欢迎页面或失败页面,如代码清单1-15所示。

代码清单1-15 LoginController.java

package com.smart.web;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.smart.domain.User;
import com.smart.service.UserService;
@Controller①
@RequestMapping(value = "/admin"
public class LoginController{@Autowiredprivate UserService userService;@RequestMapping(value = "/login.html")②public String loginPage(){return "login";}@RequestMapping(value = "/loginCheck.html")③public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(),loginCommand.getPassword());if (!isValidUser) {return new ModelAndView("login", "error", "用户名或密码错误。");} else {User user = userService.findUserByUserName(loginCommand.getUserName());user.setLastIp(request.getRemoteAddr());user.setLastVisit(new Date());userService.loginSuccess(user);request.getSession().setAttribute("user", user);return new ModelAndView("main");}}
}

在①处通过Spring MVC的@Controller注解可以将任何一个POJO的类标注为Spring MVC的控制器,处理HTTP的请求。当然标注了@Controller的类首先会是一个Bean,所以可以使用@Autowired进行Bean的注入。

一个控制器可以拥有多个对应不同HTTP请求路径的处理方法,通过@RequestMapping指定方法如何映射请求路径,如②和③所示。

请求的参数会根据参数名称默认契约自动绑定到响应方法的入参中,在③处的loginCheck(HttpServletRequest request,LoginCommand loginCommand)方法中,请求参数会按名称匹配绑定到loginCommand的入参中。

请求响应方法可以返回一个ModelAndView,或直接返回一个字符串,Spring MVC会解析之并转向目标响应页面。

ModelAndView对象既包括了视图信息又包括了视图渲染所需的模型数据信息,在这里用户仅需要了解它代表一个视图就可以了,在后面的内容中,读者将了解到Spring MVC如何根据这个对象转向真正的页面。

前面使用到的LoginCommand对象是一个POJO,它没有继承于特定的父类或实现特定的接口。LoginCommand类仅包括用户/密码这两个属性(和请求的用户/密码参数名称一样),如代码清单1-16所示。

代码清单1-16 LoginCommand

package com.smart.web;
public class LoginCommand {private String userName;private String password;//省略get/setter方法
}

Spring MVC配置文件
编写好LoginCommand后,需要在viewspace-servlet.xml中声明该控制器,扫描Web路径,指定Spring MVC的视图解析器,如代码清单1-17所示。

代码清单1-17 viewspace-servlet.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"><!--①扫描web包,应用Spring的注解 --><context:component-scan base-package="com.smart.web"/><!--②配置视图解析器,将ModelAndView及字符串解析为具体的页面 --><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/"p:suffix=".jsp" />
</beans>

ModelAndView的解析配置
在代码清单1-15 的③处,控制器根据登录处理结果分别返回 ModelAndView ("login", "error", "用户名或密码错误。")和ModelAndView("main")。ModelAndView的第一个参数代表视图的逻辑名,第二个和第三个参数分别为数据模型名称和数据模型对象,数据模型对象将以数据模型名称为参数名放置到request的属性中。

Spring MVC如何将视图逻辑名解析为具体的视图页面呢?解决的思路也和上面的方法类似,需要在viewspace-servlet.xml中提供一个定义解析规则的Bean,如代码清单1-18所示。

代码清单1-18 viewspace-servlet.xml视图解析规则

…
<!--通过prefix指定在视图名前所添加的前缀,通过suffix指定在视图名后添加的后缀-->
<bean   class="org.springframework.web.servlet.view.InternalResourceViewResolver"p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/"p:suffix=".jsp" />

Spring MVC为视图名到具体视图的映射提供了许多可供选择的方法。在这里,使用了InternalResourceViewResolver,它通过为视图逻辑名添加前后缀的方式进行解析。如视图逻辑名“login”将解析为/WEB-INF/jsp/login.jsp;视图逻辑名“main”将解析为/WEB-INF/jsp/main.jsp。

1.6.3 JSP视图页面
景区网站登录模块共包括两个JSP页面,分别是登录页面login.jsp和管理主页面main.jsp,下面将完成这两个页面的开发工作。

登录页面login.jsp
登录页面login.jsp的代码如代码清单1-19所示。

代码清单1-19 login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html><head><title>景区网站登录</title></head><body><c:if test="${!empty error}"> ①<font color="red"><c:out value="${error}" /></font></c:if>        <form action="<c:url value="/ loginCheck.html "/>" method= "post">②用户名:<input type="text" name="userName"><br>密 码:<input type="password" name="password"><br><input type="submit" value="登录" /><input type="reset" value="重置" /></form></body>
</html>

login.jsp页面既作为登录页面又作为登录失败后的响应页面。因此在 ①处使用JSTL标签对登录错误返回的信息进行处理。JSTL标签中引用了error变量,这个变量正是LoginController中返回的ModelAndView("login", "error", "用户名或密码错误。") 对象所声明的error参数。

login.jsp的登录表单提交到/loginController.html,如②所示。的JSTL标签会在URL前自动加上应用程序部署根目录,假设应用部署在网站的viewspace目录下,标签将输出/viewspace/loginController.html。通过标签很好地解决了开发和应用部署目录不一致的问题。

由于 login.jsp 放置在 WEB-INF/jsp 目录下,无法直接通过 URL 进行调用,它由LoginController 控制类中标注了@RequestMapping(value = "/login.html")的loginPage()进行转发,见代码清单1-15。

景区管理主页面main.jsp
登录成功的欢迎页面很简单,仅使用JSTL标签显示一条欢迎信息即可,如代码清单1-20所示。

代码清单1-20 main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>景区后台管理主页面</title></head><body>${user.userName},欢迎您进入景区后台管理! ①</body>
</html>

①处访问Session域中的user对象,显示用户名和积分信息。这样,就完成了实例所有的开发任务。

《Spring 3.0就这么简单》——1.6 展现层相关推荐

  1. 《Spring 3.0就这么简单》——1.5 业务层

    本节书摘来自异步社区<Spring 3.0就这么简单>一书中的第1章,第1.5节,作者: 陈雄华 , 林开雄著,更多章节内容可以访问云栖社区"异步社区"公众号查看 1. ...

  2. www.how2j.com_HOW-TO:快速开始使用Spring 4.0,以构建简单的REST-Like API(演练)

    www.how2j.com HOW-TO:快速开始使用Spring 4.0,以构建简单的REST-Like API(演练) 关于使用Spring MVC创建Web API的另一篇教程. 不太复杂. 只 ...

  3. 如何:从Spring 4.0快速入门以构建简单的REST-Like API(演练)

    如何:从Spring 4.0快速入门以构建简单的REST-Like API(演练) 关于使用Spring MVC创建Web API的另一篇教程. 不太复杂. 只是一个演练. 生成的应用程序将提供简单的 ...

  4. Spring 容器IOC解析及简单实现

    这篇文章来自极客学院 : Spring 容器IOC解析及简单实现 最近一段时间,"容器"两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交 ...

  5. 【转载】详解 Spring 3.0 基于 Annotation 的依赖注入实现

    转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/ Spring 的依赖配置方式与 Spring 框架的 ...

  6. 详解 Spring 3.0 基于 Annotation 的依赖注入实现--转载

    使用 @Repository.@Service.@Controller 和 @Component 将类标识为 Bean Spring 自 2.0 版本开始,陆续引入了一些注解用于简化 Spring 的 ...

  7. Spring 3.0 注解注入详解

    Spring 3.0 注解注入详解 2011-04-15 09:44 17ZOUGUO ITEYE博客 我要评论(1) 字号:T | T AD: 一.各种注解方式 1.@Autowired注解(不推荐 ...

  8. Spring 3.0参考之SpEL

    http://sishuok.com/forum/blogPost/list/2463.html http://docs.spring.io/spring/docs/3.0.x/reference/e ...

  9. Spring 2.0.1 与 BEA WebLogic Server 9.2 的集成

    http://www.oracle.com/technetwork/cn/topics/entarch/spring-2-weblogic-server-9-integrat-091510-zhs.h ...

最新文章

  1. Java泛型的类型擦除
  2. “@react-navigation/native“).createNavigatorFactory) is not a function.
  3. 避免在 ASP.NET Core 3.0 中为启动类注入服务
  4. 怎么才能点一下excel中的超链接就显示出图片?_Excel如何批量建立超链接,搭建工作台...
  5. iOS 动态隐藏状态栏
  6. 聊聊reactive streams的schedulers 1
  7. 《A Tale of Two Worlds (CCS‘19)》笔记
  8. wpf 监听退出事件_【WPF】监听WPF的WebBrowser控件弹出新窗口的事件
  9. Spectral Clustering(谱聚类和其他)
  10. Sklearn上机笔记--标准化
  11. 图书系统(查询图书内容)
  12. 上证指数30年k线图_仔细分析了过去30年的季线图后,我们发现了个秘密……
  13. EUI-64生成IPv6地址
  14. 基于51单片机的交通灯控制系统课程设计(含proteus仿真图及代码)
  15. SIKI学习——贪吃蛇案例05
  16. 设计简单带通滤波电路
  17. The Unarchiver 4.1.0版本在苹果电脑系统10.15.6上解压xcode.xip有问题
  18. Linux下RTP编程(上)
  19. raft协议_将Raft集成到JGroups中
  20. 创建表时出现Duplicate column product问题的解决

热门文章

  1. java web 讲义_Java之品优购课程讲义
  2. python functools import wraps_python装饰器中functools.wraps的作用详解
  3. JavaWeb(五)——Servlet、Mapping问题、ServletContext
  4. 李宏毅机器学习作业2:Winner还是Losser(含训练数据)
  5. Matlab进行录制、存储、绘制、读取音频
  6. python3.7操作kafka_python3.7新增关键字:async、await;带来和kafka-python==1.4.2的兼容性问题...
  7. java基本数据类型_Java 中有几种基本数据类型是什么?
  8. 用电梯服务器怎样解电梯显示E34,默纳克品牌电梯故障代码e41怎么处理
  9. TensorFlow 笔记2--MNIST手写数字分类
  10. rust实战入门到进阶(2)