实际开发中,我们通常需要编写多个Web相关的Servlet的时候,如下
package com.kang.service; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/userServlet") public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ApplicationContext app = new ClassPathXmlApplicationContext("applicatonContext.xml"); UserService userService = (UserService) app.getBean("userService"); userService.save(); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
这里就会出现一个问题,spring的xml文件只需要加载一次即可,并不需要每启动一个Servlet就加载一个xml文件,应用上下文的对象也被创建多次,这明显是一个不太好的弊端
这时候spring以及给我们封装好一个工具类用于返回加载这个xml配置文件的ApplicationContext对象
引入:ServletContext
ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
作用:
是一个域对象
可以读取全局配置参数
可以搜索当前工程目录下面的资源文件
可以获取当前工程名字(了解)
首先在web.xml配置全局参数(spring配置文件名称)和spring监听器(用于服务开始的时候加载springxml文件)
通过这个方法来减少spring配置文件的加载次数,从而提高程序的加载速度
使用步骤:
在web.xml配置ContextLoaderListener监听器(导入spring-web坐标)
<dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webartifactId> <version>5.0.5.RELEASEversion> dependency>
使用WebApplicationContextUtils获得应用上下文对象ApplicationContext
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicatonContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextCleanupListenerlistener-class>
listener>
package com.kang.service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象,用于读取全局参数
ServletContext servletContext = request.getServletContext();
//获取监听器返回的WebApplicationContext对象
WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于 SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 中。
它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时 它还支持 RESTful 编程风格的请求。
导入SpringMVC相关坐标
<dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webmvcartifactId> <version>5.0.5.RELEASEversion> dependency>
配置SpringMVC核心控制器DispathcerServlet
<servlet> <servlet-name>DispatcherServletservlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class> <init-param> <param-name>contextConfigLocationparam-name> <param-value>classpath:spring-mvc.xmlparam-value> init-param> <load-on-startup>1load-on-startup> servlet> <servlet-mapping> <servlet-name>DispatcherServletservlet-name> <url-pattern>/url-pattern> servlet-mapping>
创建Controller类和视图页面
- 创建一个Controller包,编写QuickController类
使用注解配置Controller类中业务方法的映射地址
@Controller //使用在web层类上用于实例化Bean(放到容器当中) public class QuickController { @RequestMapping("/quick") //请求映射 public String quickMethod(){ System.out.println("quickMethod running......."); //return:要跳转的视图 return "quick.jsp"; } }
配置SpringMVC核心文件 spring-mvc.xml
- 将下面代码放在web.xml的前端控制器的servlet标签中
<init-param> <param-name>contextConfigLocationparam-name> <param-value>classpath:spring-mvc.xmlparam-value> init-param>
<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 http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.kang.controller"/>
beans>
访问
http://localhost:8080/SpringMVC/quick
就可以看见控制台输出
quickMethod running.......
访问流程如下
- 在浏览器访问地址
- 然后tomcat寻找前端控制器,这里前端控制器配置缺省
- 然后前端控制器根据输入的url找到对应的Controller映射的“/quick”,从而返回视图
浏览器请求访问某一个资源到视图的展示,并不是靠一个前端控制器来实现的
- 用户发送请求到前端控制器DispatcherServlet
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- HandlerMapping处理器映射器对请求进行解析,找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果 有则生成)一并返回(一串资源的地址)给DispatcherServlet
- DispatcherServlet调用HandlerAdapter处理器适配器
- HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
- Controller执行完成返回ModelAndView。
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View。
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户。
前端控制器:DispatcherServlet
用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的中心,由 它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。
处理器映射器:HandlerMapping
HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的 映射方式,例如:配置文件方式,实现接口方式,注解方式等。
处理器适配器:HandlerAdapter
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理 器进行执行
它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由 Handler 对具体的用户请求进行处理。
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名,即 具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
视图:View
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。最 常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程 序员根据业务需求开发具体的页面
@RequestMapping 作用:用于建立请求 URL 和处理请求方法之间的对应关系(加的位置不同,意义也不同)
- 类上,请求URL 的第一级访问目录。此处不写的话,就相当于应用的根目录
@Controller //使用在web层类上用于实例化Bean(放到容器当中) @RequestMapping("/user") public class QuickController { @RequestMapping("/quick") //请求映射 public String quickMethod(){ System.out.println("quickMethod running......."); //return:要跳转的视图 //要加一个/表示当前web目录下 return "/quick.jsp"; } } //访问地址变为:http://localhost:8080/SpringMVC/user/quick
- 方法上,请求 URL 的第二级访问目录,与类上的使用@ReqquestMapping标注的一级目录一起组成访问虚拟路径
其中@RequestMapping 注解还有很多属性,可以用来规定请求方式等等
相关属性:
- value:用于指定请求的URL。它和path属性的作用是一样的
- method:用于指定请求的方式
- params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和配置的一模一样 例如:
- params = {“accountName”},表示请求参数必须有accountName
- params = {“moeny!100”},表示请求参数中money不能是100
@Controller //使用在web层类上用于实例化Bean(放到容器当中) @RequestMapping("/user") public class QuickController { @RequestMapping(value = "/quick", method = RequestMethod.GET, params = {"username"}) //请求映射 public String quickMethod(){ System.out.println("quickMethod running......."); //return:要跳转的视图 //要加一个/表示当前web目录下 return "/quick.jsp"; } } //访问地址:http://localhost:8080/SpringMVC/user/quick?username=xxx
在使用@Controller等注解解析之后,都要进行组件扫描
<context:component-scan base-package="com.kang.controller"/>
这里是规定了扫描的包名,除此之外,还可以规定扫描哪些注解
<context:component-scan base-package="com.kang.controller"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> context:component-scan>
在前面的Controller返回了"quick.jsp"视图,若是不想编写
jsp后缀,我们可以通过视图解析器来修改视图前后缀
除此之外,还可以规定视图的显示形式,是请求转发还是重定向都可以
只需要在返回的字符串加:
- forward:转发
- redirect:重定向