SpringMVC是基于spring的,是spring中的一个模块,做web开发用的。springmvc叫做spring web mvc,说明他是spring的核心技术,做web开发,springmvc内部是使用mvc框架模式。
SpringMVC是一个容器,管理对象的,使用IoC核心技术。
SpringMVC管理界面层中的控制器对象。
SpringMVC底层也是Servlet,以Servlet为核心,接收请求,处理请求。显示处理结果给用户。
处理用户的请求:
用户发起请求—SpringMVC—Spring—MyBatis—Mysql数据库
DispatcherServlet是框架中的一个Servlet对象。负责接收请求,响应处理结果。
DispatcherServlet他的父类是HttpServlet
DispatcherServlet也叫做前端控制器(front controller)
SpringMVC是管理控制器对象,原来没有SpringMVC之前使用Servlet作为控制器对象使用。现在通过SpringMVC容器创建一种叫做控制器的对象,代替Servlet行使控制器的功能。
例子:
需求:用户发起一个请求,springmvc接收请求,显示请求的处理结果
servlet的实现方式:
jsp发起请求---servlet---jsp显示结果
步骤:
1.新建web应用
2.加入web依赖
spring-webmvc依赖(springmvc框架依赖),servlet依赖
3.声明springmvc核心对象DispatcherServlet
1) DispatcherServlet是一个Servlet对象
2) DispatcherServlet叫做前端控制器(front controller)
3) DispatcherServlet作用:
1.在servlet的init()方法中,创建springmvc中的容器对象
2.作为servlet,接收请求
4.创建一个jsp,发起请求
5.创建一个普通的类,作为控制器使用(代替之前的servlet)
1) 在类的上面加入@Controller注解
2) 在类中定义方法,方法的上面加入@RequestMapping注解
方法处理请求的,相当于servlet的doGet,doPost
6.创建作为结果的jsp页面
7.创建springmvc的配置文件(spring的配置文件一样)
1) 声明组件扫描器,指定@Controller注解所在的包
2) 声明视图解析器对象
pom.xml文件:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>SpringMVC-01artifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>SpringMVC-01 Maven Webappname>
<url>http://www.example.comurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>10maven.compiler.source>
<maven.compiler.target>10maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.4version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
dependency>
dependencies>
<build>
<finalName>SpringMVC-01finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-pluginartifactId>
<version>3.1.0version>
plugin>
<plugin>
<artifactId>maven-resources-pluginartifactId>
<version>3.0.2version>
plugin>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.0version>
plugin>
<plugin>
<artifactId>maven-surefire-pluginartifactId>
<version>2.22.1version>
plugin>
<plugin>
<artifactId>maven-war-pluginartifactId>
<version>3.2.2version>
plugin>
<plugin>
<artifactId>maven-install-pluginartifactId>
<version>2.5.2version>
plugin>
<plugin>
<artifactId>maven-deploy-pluginartifactId>
<version>2.8.2version>
plugin>
plugins>
pluginManagement>
build>
project>
web.xml文件:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
web-app>
springmvc-servlet.xml文件:
<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.lu.controller">context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/">property>
<property name="suffix" value=".jsp">property>
bean>
beans>
Controller类:
package com.lu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @Controller:创建控制器对象
* 控制器:叫做后端控制器(back controller),自定义的类处理请求的
* 位置:在类的上面,表示创建此类的对象,对象放在springmvc的容器中
* */
@Controller
public class MyController {
//定义方法,处理请求。public void doGet(){}
/**
* springmvc框架,使用控制器类中的方法,处理请求
* 方法的特点:
* 1. 方法的形参,表示请求中的参数
* 2.方法的返回值,表示本次请求的处理结果
*
*
* @RequestMapping:请求映射
* 属性:value 请求中的url地址,唯一值,以 "/" 开头
* 位置:1.在方法的上面(必须) 2.在类定义的上面(可选)
* 作用:把指定的请求,交给指定的方法处理,等同于url-pattern
*
* 返回值ModelAndView:表示本次请求的处理结果(数据和视图)
* Model:表示数据
* View:表示视图
* */
@RequestMapping(value = {"/some.do","/first.do"})
public ModelAndView doSome() { //doGet()
//使用这个方法处理请求。能处理请求的方法叫做控制器方法
//调用service对象,处理请求,返回数据
ModelAndView mv = new ModelAndView();
//添加数据
mv.addObject("msg","处理了some.do请求");
mv.addObject("fun","执行了doSome方法");
//指定视图,setViewName("视图的完整路径")
//mv.setViewName("/show.jsp");
//mv.setViewName("/WEB-INF/view/show.jsp");
//当配置了视图解析器,使用文件名称作为视图名使用,叫做视图逻辑名称
//使用了逻辑名称,框架使用配置文件中视图解析器的前缀和后缀,拼接为完整视图路径
// /WEB-INF/view/ + show + .jsp
mv.setViewName("show");
//返回结果
return mv;
}
/**
* 当框架调用完doSome()方法后,得到返回中ModelAndView
* 框架会在后续的处理逻辑值,处理mv对象里面的数据和视图
* 对数据执行 request.setAttribute("msg","处理了some.do请求"); 把数据放入到request作用域
* 对视图执行forward转发操作。等同于request.getRuestDispather("/show.jsp").forward(..)
* */
@RequestMapping(value = {"/other.do","/test/second.do"})
public ModelAndView doOther() { //doGet()
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了other.do请求");
mv.addObject("fun","执行了doOther方法");
mv.setViewName("other");
return mv;
}
}
简单的处理过程:
用户发起请求some.do—>tomcat接收了请求—>DispatcherServlet—>分配MyController(doSome() 返回mv对象)—>mv显示给用户
省略tomcat
用户some.do-------->DispatcherServlet-------->MyController
如果使用servlet处理请求
用户发起请求----------->没有其他对象-------------->Servlet
用户发起some.do----DispatcherServlet(Servlet接收请求)-----转发给MyController
public class DispatcherServlet extends HttpServlet() {
public void service(HttpServletRequest request,HttpServletResponse response) {
if("some.do".equals(request.getURL())){
//从容器中获取MyController
MyController c = ctx.getBean("some");
c.doSome();
}else if("other.do".equals(request.getURL())){
OtherController c = ctx.getBean("other");
c.doOther();
}
}
}
1.web.xml 部署描述符文件,给服务器(tomcat)
作用:服务器在启动的时候,读取web.xml。根据文件中的声明去创建各种对象
根据文件中的声明,知道 请求和servlet等对象的关系
2.框架的配置文件,springmvc的配置文件
作用:声明框架创建的各种对象,主要是创建Controller对象
配置文件的加载顺序和声明
1.tomcat服务器启动,读取web,xml,根据web.xml文件中的说明,创建对象
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
web-app>
创建DispatcherServlet他的对象,会执行init()方法。在init()方法中会执行springmvc容器对象创建
WebApplicationContext ctx = new ClassPathXmlApplicationContext(“classpath:springmvc.xml”)
2.springmvc框架,new ClassPathXmlApplicationContext() 读取springmvc的配置文件
<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.lu.controller">context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/">property>
<property name="suffix" value=".jsp">property>
bean>
beans>
使用组件扫描器base-package=“com.lu.controller”,遍历controller包中的所有类
MyController类,找到这个类中的@Controller,@RequestMapping注解,就能创建MyController对象。
知道some.do请求时执行doSome()方法、
3.用户发起请求some.do----DispatcherServlet
DispatcherServlet里面有WebApplicationContext,WebApplicationContext里面有MyController对象
请求some.do,DispatcherServlet就知道时MyController处理的
属性:value 请求的url地址
位置:
先看Controller类
package com.lu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
@RequestMapping(value = {"/test/some.do","/test/first.do"})
public ModelAndView doSome() {
System.out.println("执行了MyController的doSome()方法");
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了some.do请求");
mv.addObject("fun","执行了doSome方法");
mv.setViewName("show");
return mv;
}
@RequestMapping(value = {"/test/other.do","/test/second.do"})
public ModelAndView doOther() {
System.out.println("执行了MyController的doOther()方法");
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了other.do请求");
mv.addObject("fun","执行了doOther方法");
mv.setViewName("other");
return mv;
}
}
配置tomcat后我们访问地址,是下面这两行
https://localhost:8443/test/some.do
https://localhost:8443/test/second.do
我们可以把@RequestMapping放在类的上面
package com.lu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/test")
public class MyController {
@RequestMapping(value = {"/some.do","/first.do"})
public ModelAndView doSome() {
System.out.println("执行了MyController的doSome()方法");
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了some.do请求");
mv.addObject("fun","执行了doSome方法");
mv.setViewName("show");
return mv;
}
@RequestMapping(value = {"/other.do","/second.do"})
public ModelAndView doOther() {
System.out.println("执行了MyController的doOther()方法");
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了other.do请求");
mv.addObject("fun","执行了doOther方法");
mv.setViewName("other");
return mv;
}
}
属性method请求的方式,使用RequestMethod类的枚举,表示请求方式
//请求方式不一样,错误码是 405
//指定some.do使用get请求方式
@RequestMapping(value = "/some.do", method = RequestMethod.GET)
public ModelAndView doSome() {}
对应HttpServletRequest,HttpServletResponse,HttpSession 只需要在控制器方法的形参列表中定义就可以了。框架会给参数赋值,在控制器方法内部可以直接使用request,reponse,session参数。
400:http status,表示客户端异常,主要是发生在用户提交参数过程中。
接收请求中的参数:逐个接收;对象接收
逐个接收:请求中的参数名和控制器方法的形参名一样,按照名称
逐个接收请求参数
@RequestMapping(value = "receive_property.do")
public ModelAndView doPropertyParam(String name, Integer age) {
System.out.println("执行了MyController的doPropertyParam方法,name:" + name + " age:" + age);
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
接收参数的问题:
CharacterEncodingFilter使用:
<filter>
<filter-name>encodingfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
<init-param>
<param-name>forceRequestEncodingparam-name>
<param-value>trueparam-value>
init-param>
<init-param>
<param-name>forceResponseEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
/**
* 逐个接收请求参数:请求中参数名和形参名不一致
* @RequestParam:解决名称不一样的问题
* 属性:value 请求中的参数名称
* required:boolean类型的,默认是true
* true:请求中必须有此参数,没有报错
* 位置:在形参定义的前面
* */
@RequestMapping(value = "receive_param.do")
public ModelAndView doReceiveParam(@RequestParam(value = "rname",required = false) String name,
@RequestParam("rage") Integer age) {}
对象接收:在控制器方法的形参是Java对象,使用Java对象的属性接收请求中的参数值
要求:Java对象的属性名和请求中参数名一致。
例子:
public class Student {
private Integer id;
private String name;
private Integer age;
//set | get 方法
}
/**
* 使用对象接收请求中的参数
* 要求:参数名和Java对象的属性名一样
* Java类需要有一个无参数构造方法,属性有set方法
*
* 框架的处理:
* 1.调用Student的无参数构造方法,创建对象
* 2.调用对象set方法,同名的参数,调用对应的set方法
* 参数是name,调用setName(参数名)
* */
@RequestMapping("receive_object.do")
public ModelAndView doReceiveObject(Student student) {
System.out.println("MyController的方法doReceiveObject=" + student);
ModelAndView mv = new ModelAndView();
mv.addObject("myname",student.getName());
mv.addObject("myage",student.getAge());
mv.addObject("myid",student.getId());
mv.setViewName("show");
return mv;
}
控制器方法的返回值表示本次请求的处理结果,返回值有ModelAndView,String,void,Object
请求的处理结果包含:数据和视图
请求的结果有数据和视图,使用ModelAndView最方便
数据:存放request作用域
视图:执行forward转发操作
框架对应的返回值是String,执行的是forward转发操作
视图可以表示为完整视图路径,或者视图的逻辑名称
@Controller
public class MyController {
/**
* 控制器方法返回String,表示逻辑名称。需要项目中配置视图解析器
*
*/
@RequestMapping("return-string-view.do")
public String doReturnStringView1(String name, Integer age) {
System.out.println("执行了MyController的doReturnStringView1方法 name=" + name + ",age=" + age);
//返回结果,forward,转发到show.jsp
return "show";
}
}
void:没有数据和视图,可以使用HttpServletResponse对象输出数据,相应ajax请求
/**
* 控制器方法返回是void,相应ajax请求。使用HttpServletResponse输出数据
* */
@RequestMapping("/return-void-ajax.do")
public void returnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {
System.out.println("处理void返回类型,name=" + name + ",age=" + age);
//调用service得到结果对象
Student student = new Student();
student.setName(name + "同学");
student.setAge(age);
//把对象转为json
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(student);
System.out.println("服务器段对象转为的json===" + json);
//输出Json,相应ajax
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.write(json);
pw.flush();
pw.close();
}
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022/7/22
Time: 11:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
请求方式
控制器方法返回String-逻辑视图名称
返回Student表示数据,还有视图。
所以控制器方法返回对象Object,用来相应Ajax请求
返回对象Object,可以是List,Student,Map,String,Integer…这些都是数据,Ajax请求需要的就是数据。在Ajax请求中,一般需要从服务器返回的是json格式的数据,经常要处理Java 对象到json的转换。而且还需要输出数据响应Ajax请求。框架提供了处理Java对象到json转换,还有数据输出工作
HttpMessageConverter接口,作用:
public interface HttpMessageConverter<T> {
/**
作用:检查clazz这个类型的对象,能否转为mediaType所表示的数据格式
如果能转为mediaType表示的类型,返回true,返回true调用read()
*/
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
/**
作用:接收请求中的数据,把数据转为clazz表示的对象
*/
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/**
作用:检查clazz这种数据类型,能否转为mediaType表示的数据格式
*/
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
/**
作用:把t对象,按照contentType说明的格式,把对象转为Json或者xml
*/
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
MediaType:媒体类型,表示互联网中数据的格式。例如 application/json;text/html;image/gif
HttpMessageConverter接口的实现类:
1.MappingJackson2HttpMessageConverter 使用jackson工具库中的ObjectMapper把Java对象转换为json数据格式
2.StringHttpMessageConverter 把字符串类型的数据,进行格式转换和编码
怎么使用实现类:
框架根据控制器方法的返回类型,自动查找使用的实现类。
@RequestMapping("/receiver-object.do")
public Student doReceiveObject(String name, Integer age) {
System.out.println("doReceiveObject方法执行了");
Student student = new Student();
student.setName("lisi");
student.setAge(21);
student.setId(1001);
return student;
}
默认情况下:springmvc使用了HttpMessageConverter接口的4个实现类。包括StringHttpMessageConverter
需要在springmvc的配置文件中,加入注解驱动的标签 mvc:annotation-driven,加入这个标签后,springmvc项目启动后,会创建HttpMessageConverter接口的7个实现类对象,包括StringHttpMessageConverter和Mappingjackson2HttpMessageConverter.
@ResponseBody注解的作用,就是把student转换后的json通过HttpServletResponse对象输出给浏览器
//输出Json,相应ajax
response.setContentType("application/json;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.write(json);
pw.flush();
pw.close();
@ResponseBody注解的作用就是上面的代码的实现
访问地址:
当web.xml中DispathcerServlet的url-pattern是*.do
http://localhost:8080/index.jsp tomcat
http://localhost:8080/js/jquery-3.6.0.min.js tomcat
http://localhost:8080/images/book02.jpg tomcat
http://localhost:8080/html/test.html tomcat
http://localhost:8080/some.do DispathcerServlet(SpringMVC框架)
tomcat安装目录/conf/web.xml
<servlet>
<servlet-name>defaultservlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServletservlet-class>
<init-param>
<param-name>debugparam-name>
<param-value>0param-value>
init-param>
<init-param>
<param-name>listingsparam-name>
<param-value>falseparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
default叫做默认servlet,作用:
1.它提供静态资源的处理
2.它处理所有未映射到其他请求的请求处理
http://localhost:8080/index.jsp tomcat 成功访问
http://localhost:8080/js/jquery-3.6.0.min.js 404 没有对应的控制器对象
http://localhost:8080/images/book02.jpg 404 没有对应的控制器对象
http://localhost:8080/html/test.html 404 没有对应的控制器对象
http://localhost:8080/some.do 200 MyController
404是因为没有对应的控制器对象
使用"/",导致中央调度器成为了默认的default servlet,
需要处理静态资源和其他的未映射的请求,默认中央调度器没有处理静态资源的控制器对象,所以静态资源都是404,some.do这个请求有MyController对象,所以能访问。
如果项目中,中央调度器设置了"/",动态资源能访问,静态资源不能访问,需要处理静态资源的访问工作。
在springmvc的配置文件中加入:mvc:default-servlet-handler/标签 ,springmvc框架会在项目运行时,加入DefaultServletHttpRequestHandler对象,让这个对象处理静态资源访问
<mvc:default-servlet-handler/>
<mvc:annotation-driven>mvc:annotation-driven>
在springmvc配置文件中加入一个 mvc:resources 标签,框架会创建ResourceHttpRequestHandler控制器对象,使用这个对象处理静态资源的访问。不依赖tomcat
<mvc:annotation-driven>mvc:annotation-driven>
<mvc:resources mapping="/static/**" location="/static/">mvc:resources>
forward:/视图完整路径
redirect:/视图完整路径
package com.lu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
/**
* 控制器方法返回是ModelAndView实现转发forward
* 语法:mv.setViewName("forward:视图完整路径")
* */
@RequestMapping(value = "/doForward.do",method = RequestMethod.GET)
public ModelAndView doForward() {
System.out.println("执行了doForward方法");
ModelAndView mv = new ModelAndView();
mv.addObject("msg","处理了doForward请求");
mv.addObject("fun","执行了doForward方法");
//显示使用forward指定转发操作
mv.setViewName("forward:/WEB-INF/view/show.jsp");
return mv;
}
/**
* 当控制器方法返回ModelAndView实现重定向
* 语法: mv.setViewName("redirect:视图完整路径")
* redirect特点:不和视图解析器一起工作,就当作项目中没有视图解析器
*
* 框架提供的重定向的功能:
* 1.框架可以实现两次请求之间的数据传递,把第一个请求中的Model俩面简单类型的数据,转为字符串,附加到目标页面的后面,做get参数传递
* 可以在目标页面中获取参数值使用
*
* 2.在目标页面中,可以使用 ${param.参数名} 获取参数的值
* */
@RequestMapping("doRedirect.do")
public ModelAndView doRedirect(String name, Integer age) {
System.out.println("执行了doRedirect方法,name=" + name + ",age=" + age);
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("redirect:/other.jsp");
//http://localhost:8080/other.jsp?myname=%E5%BC%A0%E4%B8%89&myage=23
return mv;
}
}
框架使用的是集中的异常处理。把各个Controller中抛出的异常集中到一个地方处理。处理异常的叫做异常处理。
框架中使用两个注解完成异常的集中处理。这样每个controller不用单独处理异常了。注解是:
@ExceptionHandler:放在方法的上面,表示此方法可以处理某个类型的异常。当异常发生时,执行这个方法
@ControllerAdvice:放在类的上面,表示这个类中有异常的处理方法,相当于aop中的@Aspect
@ControllerAdvice看作是 控制器增强,就是给Controller类增加异常(切面)的处理功能
package com.lu.controller;
import com.lu.exception.AgeException;
import com.lu.exception.MyUserException;
import com.lu.exception.NameException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
@RequestMapping("some.do")
public ModelAndView doSome(String name, Integer age) throws MyUserException {
System.out.println("执行了doSome方法,name=" + name + ",age=" + age);
//抛出异常
if(!"zs".equals(name)) {
throw new NameException("姓名不正确");
}
if(age == null || age.intValue() > 80) {
throw new AgeException("年龄太大了");
}
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}
}
拦截器:是springmvc框架中的一种对象,需要实现接口HandlerInterceptor,拦截用户的请求,拦截到controller的请求
作用:拦截用户的请求,可以预先对请求做处理,根据处理结果,决定是否执行controller,也可以把多个controller中共用的功能定义到拦截器。
特点:
拦截器的定义:
package com.lu.handler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 拦截器
* */
public class MyInterceptor implements HandlerInterceptor {
/**
* preHandle:预先处理请求的方法。总的开关
* 参数:
* Object handler:被拦截的控制器对象(MyController)
* 返回值:boolean
* true:请求是正确的,可以被controller处理的
* ====MyInterceptor拦截器的preHandle====
* 执行了MyController的doSome方法
* ====MyInterceptor拦截器的postHandle====
* ====MyInterceptor拦截器的afterCompletion====
* false:请求不能被处理,控制器方法不会执行。请求到此截止。
* ====MyInterceptor拦截器的preHandle====
*
* 特点:
* 1.预处理方法他的执行时间;在控制器方法之前执行的
* 2.可以对请求做处理,可以做登录的检查,权限的判断,统计数据等等。
* 3.决定请求是否执行
* */
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("====MyInterceptor拦截器的preHandle====");
return true;
}
/**
* postHandle:后处理发方法
* 参数:
* Object handler:被拦截的控制器对象(MyController)
* ModelAndView mv:控制器方法的返回值(请求的执行结果)
*
* 特点:
* 1.在控制器方法之后执行的
* 2.能获取到控制器方法的执行结果,可以修改原来的执行结果(可以修改数据,也可以修改视图)
* 3.可以做对请求的二次处理
*
* */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("====MyInterceptor拦截器的postHandle====");
}
/**
* afterComletion:最后执行的方法
* 参数:
* Object handler:被拦截的控制器对象(MyController)
* Exception ex:异常对象
*
* 特点:
* 1.在请求处理完成后执行的,请求处理完成的标志是视图处理完成,对视图执行forward操作后
* 2.可以做程序最后要做的工作,释放内存,清理临时变量
*
* 3.方法的执行条件:
* 1)当前的拦截器preHandle()方法必须执行
* 2)preHandle()必须返回true
*
* */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("====MyInterceptor拦截器的afterCompletion====");
}
}
配置文件:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lu.handler.MyInterceptor">bean>
mvc:interceptor>
mvc:interceptors>
当你的preHndle返回true,执行结果:
====MyInterceptor拦截器的preHandle====
执行了MyController的doSome方法
====MyInterceptor拦截器的postHandle====
====MyInterceptor拦截器的afterCompletion====
请求的执行顺序:用户some.do---preHandle---doSome---postHandle---afterComletion
当preHandle返回false,执行结果:
====MyInterceptor拦截器的preHandle====
三个方法的使用:
package com.lu.handler;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
* 拦截器
* */
public class MyInterceptor implements HandlerInterceptor {
/**
* preHandle:预先处理请求的方法。总的开关
* 参数:
* Object handler:被拦截的控制器对象(MyController)
* 返回值:boolean
* true:请求是正确的,可以被controller处理的
* ====MyInterceptor拦截器的preHandle====
* 执行了MyController的doSome方法
* ====MyInterceptor拦截器的postHandle====
* ====MyInterceptor拦截器的afterCompletion====
* false:请求不能被处理,控制器方法不会执行。请求到此截止。
* ====MyInterceptor拦截器的preHandle====
*
* 特点:
* 1.预处理方法他的执行时间;在控制器方法之前执行的
* 2.可以对请求做处理,可以做登录的检查,权限的判断,统计数据等等。
* 3.决定请求是否执行
* */
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("====MyInterceptor拦截器的preHandle====");
//request.getRequestDispatcher("/tips.jsp").forward(request,response);
return true;
}
/**
* postHandle:后处理发方法
* 参数:
* Object handler:被拦截的控制器对象(MyController)
* ModelAndView mv:控制器方法的返回值(请求的执行结果)
*
* 特点:
* 1.在控制器方法之后执行的
* 2.能获取到控制器方法的执行结果,可以修改原来的执行结果(可以修改数据,也可以修改视图)
* 3.可以做对请求的二次处理
*
* */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) throws Exception {
System.out.println("====MyInterceptor拦截器的postHandle====");
//对请求做二次的处理
if(mv != null) {
mv.addObject("mydate",new Date());
mv.setViewName("other");
}
}
/**
* afterComletion:最后执行的方法
* 参数:
* Object handler:被拦截的控制器对象(MyController)
* Exception ex:异常对象
*
* 特点:
* 1.在请求处理完成后执行的,请求处理完成的标志是视图处理完成,对视图执行forward操作后
* 2.可以做程序最后要做的工作,释放内存,清理临时变量
*
* 3.方法的执行条件:
* 1)当前的拦截器preHandle()方法必须执行
* 2)preHandle()必须返回true
*
* */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("====MyInterceptor拦截器的afterCompletion====");
//获取数据
HttpSession session = request.getSession();
Object attr = session.getAttribute("attr");
System.out.println("attr == " + attr);
//删除数据
session.removeAttribute("attr");
//确定数据是否删除
attr = session.getAttribute("attr");
System.out.println("删除后再次检查数据 === " + attr);
}
}
使用两个拦截器,主要看拦截器的执行顺序,以及哪个方法控制请求的执行
====MyInterceptor拦截器的preHandle111====
====MyInterceptor拦截器的preHandle222====
执行了MyController的doSome方法
====MyInterceptor拦截器的postHandle222====
====MyInterceptor拦截器的postHandle111====
====MyInterceptor拦截器的afterCompletion222====
====MyInterceptor拦截器的afterCompletion111====
请求的执行顺序:
用户some.do—拦截器1的preHandle—拦截器2的preHandle—控制器doSome—拦截器2的postHandle—拦截器1的postHandle—拦截器2的afterComletion—拦截器1的afterComletion
2.两个拦截器,第一个拦截器preHnadle=true,第二个拦截器preHandle=false
====MyInterceptor拦截器的preHandle111====
====MyInterceptor拦截器的preHandle222====
====MyInterceptor拦截器的afterCompletion111====
3.两个拦截器,第一个拦截器preHnadle=false,第二个拦截器preHandle=true
====MyInterceptor拦截器的preHandle111====