链接
本期目标
- 成功添加SpringMVC的配置文件
- 添加/hello路径,通过 http://localhost:8080/tutorial_war_exploded/hello
访问新的页面
上期我们已经成功地通过Maven引入SpringMVC,但是没有配置文件,SpringMVC是没有用的。在这里,我们需要先明确下Servlet,SpringMVC之间的关系。
Servlet -> SpringMVC
Servlet
Servlet是一个小型的JAVA程序,运行在Web 服务器中来处理用户的请求。javax 提供了接口Servlet 来描述可控制这个程序:

关键就是第三个函数,用来接收Request,处理Response
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
所有后台都是进行这一步操作的。
javax 提供的 servlet有以下几种:

实现Servlet接口的时候必须将所有的方法进行实现,即便有些根本没有包含任何代码。但是GenericServlet抽象类实现了Servlet和ServletConfig接口简化了任务。在GenericServlet抽象类的帮助下,我们只需要重写service方法中实现我们的任务就可以了。
而GenericServlet并不常用,因为HttpServlet才是主角,并且不需要覆盖service()方法而是doGet(),doPost()来编写逻辑。HttpServlet覆盖了GenericServlet类,它将ServletRequest和ServletRespond对象分别转换成了HttpServletRequest和HttpServletRespond对象,并调用最常用的doGet()(从服务器端向客户端呈现),doPost()(从客户端获得到服务器端处理)等七种方法而不需要重写service方法。
JSP本质上是一个Servlet,然而其不需要编译,JSP页面是一个以.jsp扩展名的文本文件。简单的JSP页面在第一次请求后被翻译为(JSP名)_jsp的Servlet。
SpringMVC
SpringMVC是对Servlet的封装。
- 它自带一个开箱即用的Dispatcher Servlet。并提供了Controller接口并公开了handleRequest方法, 要使用这个Servlet,需要在部署描述符中进行配置,并且会寻找一个对应的配置文件servletName-servlet.xml。
- 作为Spring家族的一员,可以使用Spring提供的功能。特别是通过注解而实现的AOP功能,现代的后台程序应该没有不用的。
SpringMVC的配置文件
SpringMVC要配置的东西有以下几个
- Spring框架支持
- Dispatch Servlet
- 类的声明
1和2需要放在web.xml 中进行声明:
<web-app version="3.0" 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
https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<!--Spring框架支持 ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--Dispatch Servlet-->
<servlet>
<servlet-name>business</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>business</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
ContextLoaderListener 的原理可以参考
https://www.jianshu.com/p/a1de61032344
xxx-servlet.xml 与 applicationContext.xml
- Servlet需要配置的xml文件, 用于配置控制器、拦截uri转发view。其默认地址是:/WEB-INF/${servletName}-servlet.xml,这里就是
/WEB-INF/business-servlet.xml - 系统需要一个applicationContext.xml配置文件, 是Spring的全局配置文件,用来控制Spring特性。其默认地址是:/WEB-INF/applicationContext.xml
SpringMVC官方介绍如下:
Spring lets you define multiple contexts in a parent-child hierarchy.
The applicationContext.xml defines the beans for the "root webapp context", i.e. the context associated with the webapp.
The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context.
There can be many of these in a webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml
for servlet spring2).
Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.
All Spring MVC controllers must go in the spring-servlet.xml context.
In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared
between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.
- 一个bean如果在两个文件中都被定义了(比如两个文件中都定义了component scan扫描相同的package), spring会在application context和 servlet context中都生成一个实例,他们处于不同的上下文空间中,他们的行为方式是有可能不一样的
- 如果在application context和 servlet context中都存在同一个 @Service 的实例,controller(在servlet context中) 通过 @Resource引用时,会优先选择servlet context中的实例
- servlet context可以引用application context里的实例,反之不可以。
- 多个servlet共享application context里的实例
- 在applicationContext和dispatcher-servlet定义的bean最好不要重复,dispatcher-servlet最好只扫描@controler,applicationContext扫描其它
配置的实例
通过url访问网页
网上很多H5网页的网址,像www.baidu.com,实际上是没有html, php, jsp等后缀的。现在我们新建一个aa.jsp,想通过 http://127.0.0.1/xxxx/hello来访问它。
-aa.jsp-
<html>
<body>
<h2>aa</h2>
<br/>
${requestScope.name}<br/>
</body>
</html>
我们新建一个Helloworld的java类
-HelloWorld.java-
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloWorldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 找到名为 aa 的 jsp 文件
ModelAndView mv = new ModelAndView("aa");
// 更新 aa.jsp的name属性
mv.addObject("name", "javaboy");
return mv;
}
}
下面就要通过配置文件关联这两个组件了。
首先是 bussiness-servlet.xml, 这里连接路径和java类:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 指明/hello 和 HelloWorldController java 类,这样通过http://127.0.0.1/xxxx/hello网址就可以访问到这个java类上-->
<bean class="com.zhoushijie.mock.controllers.HelloWorldController" name="/hello"/>
</beans>
然后是 applicationContext.xml,要在这里配置,使得 ModelView可以找到aa.jsp
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- <context:component-scan base-package="com.zhoushijie.mock">-->
<!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
<!-- </context:component-scan>-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 逻辑地址的映射 -->
<!-- 定义前缀 -->
<property name="prefix" value="/"></property>
<!-- 定义后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
这时运行工程,访问 http://127.0.0.1/xxxx/hello 就可以访问 jsp页面了
xml配置文件的路径
之前说过的配置文件都有默认路径,但是通常不会放在默认路径下,而是将配置文件放在一起方便管理。
在第一章里,我们新建了一个Resources文件夹,我们可以在这个组件中创建Spring文件夹作为配置文件的保存文件夹。

对 xxx-servlet.xml 文件,其默认路径的修正在 Web.xml 的 servlet 定义中,配置 contextConfigLocation :
<servlet>
<servlet-name>business</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

对 applicationContext.xml 文件,其默认路径的修正在 Web.xml 的 context-params 标签
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/spring-context.xml</param-value>
</context-param>

总结:

SpringMVC需要在Web.xml中添加配置,创建 servlet 配置文件:xxx-servlet.xml (当前的spring-servlet.xml) ; 全局配置文件:applicationContext.xml (当前的spring-context.xml)
现在我们应该可以成功运行,并且可以通过 http://localhost:8080/tutorial_war_exploded/hello 访问 aa.jsp
下一篇,我们将进行Spring注解的配置,尝试返回JSON数据

git地址:
https://github.com/milawoai/fed-teacher
tag:1.0.2
网友评论