经过断断续续两个多月的学习,终于是学习完了SSM框架。今天将SpringMVC的学习总结分享给各位,希望大家共勉,互相进步。还是老样子,先上思维导图,我认为学习任何东西有一个体系是很有必要的。
创建maven项目,推荐使用骨架创建
导入相关依赖,第一个入门案例我们就只需要两个依赖就可以了
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.5.RELEASEversion>
dependency>
和传统servlet一样,我们需要在web.xml中注册servlet,只不过在springmvc中注册servlet和传统servlet有所不同,回忆一下传统servlet的执行流程
如上图所示,超链接发出的请求some会被值为/some的url-pattern所拦截(即数字1代表的箭头),紧接着该url-pattern会根据自己的servlet-name的值MyServlet2去匹配servlet标签中的值为MyServlet2的servlet-name(箭头3),若匹配到值为MyServlet2的servlet-name标签,则将该请求交由该servlet-name标签下面的servlet-class所对应的servlet类去处理。
下面来看看springmvc程序是怎么执行的,下面是前台和后台的代码
web.xml
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
springmvc.xml
<context:component-scan base-package="com.mms.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
bean>
前台jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
请求页
hello,SpringMVC
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
结果页
欢迎使用springmvc进行开发
msg数据:${msg}
function数据:${function}
后台controller
/*
控制器类:使用@Controller注解修饰,在DispacherServlet对象在读取springmvc配置文件时通过组件扫描器
进行实例化
*/
@Controller
public class MyController {
/*
@RequestMapping(value = "/Xxx"):请求映射,将一个请求与一个方法绑定起来,一个请求指定相应
方法进行处理
1、value值唯一,表示请求的路径,其中斜杠"/"代表项目根路径
2、使用ReuestMapper修饰的方法叫做处理器方法、控制器方法,相当于传统servlet中的doGet()、doPost
3、返回值ModeAndView:
Mode:数据,即处理结果
View:视图,例如jsp
*/
@RequestMapping(value = "/some.do")
public ModelAndView someDo() {
//代码到这里,说明进入了someDo方法了,创建ModelAndView对象来封装结果
ModelAndView mv = new ModelAndView();
//添加数据,类似于request.setAttribute(key,value)
mv.addObject("msg","第一个springmvc项目");
mv.addObject("function","执行了someDo方法");
//指定视图
//mv.setViewName("/WEB-INF/view/show.jsp");
//使用视图解析器
mv.setViewName("show");
return mv;
}
}
下面通过一张图来说一下springmvc执行原理
我们在上面也说过了servlet的执行原理,那么问题就来了,我们怎么让springmvc介入程序呢?也就是我们怎么指定一个请求交由springmvc来处理而不是传统servlet来处理呢?这里就要讲一下springmvc程序的入口,这个类是springmvc提供的,叫做DispacherServlet(中央调度器)。
该种方式适用于前端数据少的请求,例如登录页面,一般只需要用户名和密码以及验证码,这类数据量少的情况就适合使用逐个接收的方式,下面通过一个登录表单看一下控制器方法逐个接收参数。
前端表单页
后台controller
@Controller
public class MethodController {
@RequestMapping(value = "/login.do",method = RequestMethod.POST)
/*
1、@RequestMapping还有一个属性method,该属性用来指定请求方式,若客户同样是发出同一个请求,但是
请求方式与@RequestMapping的method属性不一致,则报错HTTP状态405-方法不允许
2、超链接、表单默认是get方式请求
3、关于post方式中文显示乱码问题的解决方式:
我们发现当请求方式是post时,客户端的中文数据在结果页展示时会出现乱码,传统的servlet是在doGet、
doPost方法的第一行执行如下代码统一请求、响应编码格式
请求:request.setCharacterEncoding("UTF-8");
响应:response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
4、但是上述的设置编码方式每次在一个方法的第一行都要设置,重复代码过多,在这里我们可以使用过滤器
对所有请求设置编码格式,一步到位,springMVC内部给我们提供了这样的一个过滤器类CharacterEncodingFilter
*/
public ModelAndView login(String username, String userpwd) {
ModelAndView mv = new ModelAndView();
mv.addObject("username",username);
mv.addObject("userpwd",userpwd);
mv.setViewName("show");
return mv;
}
}
关于中文乱码问题,在传统servlet中,我们接收前台数据之前要设置request字符集,即request.setCharacterEncoding(“UTF-8”),同样的后台通过response对象以输出流的方式向浏览器输出信息时也要设置响应字符集;这在springmvc中也是一样的,不过springmvc通过过滤器实现了这一功能,我们只需要在web.xml中加入以下过滤器配置就可以解决中文乱码问题;
<filter>
<filter-name>characterEncodingFilterfilter-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>characterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
关于前台数据name值与控制器方法形参名不一致情况解决方案:在开发中,我们一般建议前台数据的name值与控制器方法的形参名一致,若不一致,则可以使用下面的方式解决,还是以一个表单注册为例:
前台表单
<form action="different.do" method="post">
用户名:<input type="text" name="username"/><br/>
密码<input type="password" name="userpwd"/><br/>
<input type="submit" value="注册"/>
form>
controller
@Controller
public class ParamDifferentController {
/*
解决形参名和用户传入参数名不一致情况(了解即可,很少使用,有点多此一举的意思)
1、控制器方法的参数名有一个属性@RequestParam,该属性可以解决控制器方法形参名与用户传入实际参数
名不一致情况。
2、@RequestParam有两个属性
value:用户传入实际参数名
required:布尔值,默认为true,即用户必须传递该实际参数;false则可以不传递该参数
*/
@RequestMapping(value = "/different.do",method = RequestMethod.POST)
public ModelAndView different(
@RequestParam(value = "username",required = true)String name,
@RequestParam(value = "userpwd",required = true)String password) {
ModelAndView mv = new ModelAndView();
mv.addObject("name",name);
mv.addObject("password",password);
mv.setViewName("showDifferent");
return mv;
}
}
创建一个类Person
//接收数据的普通类
public class Person {
private String name;
private int age;
public Person() {
System.out.println("无参构造...");
}
public void setName(String name) {
System.out.println("setName...");
this.name = name;
}
public void setAge(int age) {
System.out.println("setAge...");
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
前台表单这次的数据和Person类的属性相同,框架若发现控制器方法的形参为对象并且前端传递过来的数据名与该对象的属性名一致,会自动将这些数据组装为对象,类似于javabean;
<form action="obj.do" method="post">
用户名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
<input type="submit" value="注册"/>
form>
后台controller:注意看形参类型(对象)
//使用java对象接收用户数据
@Controller
public class ReceiveParamByObjController {
@RequestMapping(value = "/obj.do")
public ModelAndView byObject(Person person) {
ModelAndView mv = new ModelAndView();
mv.addObject("name",person.getName());
mv.addObject("age",person.getAge());
mv.setViewName("byObj");
return mv;
}
}
处理器方法返回值为String并且该处理器方法定义处上面没有@ResponseBody注解的话,表示该处理方法的作用仅是进行页面的跳转而不向前台传递任何数据。下面是一个返回值为String的controller类
@RequestMapping(value = "/some.do")
public String returnString() {
return "show";
}
注意处理器方法返回值为String返回视图时要配合视图解析器使用。
控制器方法返回值为void表示即不向前端传递数据,也不进行页面的跳转,所以返回值为void通过用于异步刷新(ajax)。了解即可,因为在实际开发中,我们一般使用返回值为Object的控制器方法响应ajax。
控制器方法返回值为Object用于响应ajax请求,先回忆一下传统的servlet响应ajax响应。
前端请求,通过一个按钮绑定单击事件实现ajax请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
请求页
返回值为void,响应ajax
后台servlet
@RequestMapping(value = "/returnVoid.do", method = RequestMethod.POST)
public void returnVoid(HttpServletResponse response, String name, int age) throws IOException {
System.out.println("name="+name+"age="+age);
// 处理ajax,使用json传递结果
Person person = new Person();
person.setName(name);
person.setAge(age);
// 定义容器保存json字符串
String jsonStr = "";
// 将结果转为json格式数据,使用传统方式
if (person != null) {
ObjectMapper om = new ObjectMapper();
jsonStr = om.writeValueAsString(person);
System.out.println(jsonStr);
}
// 将结果响应至客户端
// 设置响应格式
response.setContentType("application/json;charset=utf-8");
// 得到输出流
PrintWriter out = response.getWriter();
out.println(jsonStr);
// 清管道
out.flush();
// 关闭流
out.close();
}
传统的servlet处理ajax请求还是比较麻烦的,尤其是通过request、response对象向数据域进行数据设置时;那么通过框架是怎么响应ajax的呢?
首先引入依赖
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
dependencies>
在springmvc配置文件中加入注解驱动标签告诉springmvc’框架使用框架功能处理json对象,具体是框架发现注解@ResponseBody,会将该注解对应的控制器方法特殊对待
<mvc:annotation-driven/>
下面是controller类
@RequestMapping(value = "/returnAnnotation.do", method = RequestMethod.POST)
// 加入注解
@ResponseBody
public Object returnObj(String name, int age) {
/**
* 使用springmvc框架向前端传递json数据的步骤
* 1、加入处理json的工具类依赖,springmvc默认使用jackkjson
* 2、在springmvc配置文件中加入注解驱动
* 在创建springmvc容器时,注解驱动会执行一下两行代码
* ObjectMapper om = new ObjectMapper();
* jsonStr = om.writeValueAsString(person);
* 即注解驱动干的事就是将java对象转换为json格式的数据
* 3、在控制器方法上加入@ResponseBody注解,相当于执行了一下代码
* response.setContentType("application/json;charset=utf-8");
* PrintWriter out = response.getWriter();
* out.println(jsonStr);
* 即将json格式数据发送给服务器
*/
// 包装service处理后的数据
Person person = new Person();
person.setName("李四");
person.setAge(24);
return person;// 框架自动将其转换为json格式发给前台浏览器
}
ModeAndView即可以使用ModeAndView.addObject(key,value)向服务器作用域(request域)添加数据,又可以使用ModeAndView.setViewName(value)实现页面的跳转(内部是请求转发方式进行的跳转),代码就如入门案例所示,这里就不给出了,ModeAndView是我们用的最多的。
在上篇我的Spring博客中详细说明Spring+Mybatis整合,在这里的思路是一样的,我们还是将Mybatis的SqlSessionFactory对象交由spring容器创建。与上次不同的是,这次spring容器不光要托管SqlSessionFactory对象,还要将service、dao对象的创建;Mybatis负责dao层;springmvc完成controller和web开发相关的对象创建。即前端发出请求->controller拦截->调用service处理业务->调用dao查询数据库。查询完将结果一层一层返回给前端用户。
创建maven项目,导入依赖,由于是整合,涉及的依赖较多,下面是依赖
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.2.1-b03version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.5.RELEASEversion>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>1.3.1version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.9version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.12version>
dependency>
创建mybatis核心配置文件
<configuration>
<typeAliases>
<package name="com.mms.entity"/>
typeAliases>
<mappers>
<package name="com.mms.mapper"/>
mappers>
configuration>
创建spring配置文件applicationContext.xml
<context:component-scan base-package="com.mms.service"/>
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.mms.mapper"/>
bean>
创建springmvc配置文件springmvc.xml
<context:component-scan base-package="com.mms.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
bean>
<mvc:annotation-driven/>
<mvc:resources mapping="/js/**" location="/js/"/>
web.xml配置文件与之前的相同
创建数据库配置文件db.properties
url = jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=true&serverTimezone=UTC
username = xxx
password = xxx
项目流程
用户通过前台页面超链接发出增加学生或是查询全部的请求,该请求会被中央调度器拦截并分发给相应的controller处理,controller有一个service成员变量,controller调用service的业务方法从而service层接着调用dao层完成对数据库的操作,典型的mvc设计模式。
controller
@Controller
@RequestMapping(value = "/student")
public class StudentController {
// 自动注入
@Autowired
private StudentServiceImpl studentService;
// 控制器方法:查询全部
@RequestMapping(value = "/findAll")
@ResponseBody // 响应ajax
public List<Student> findAll() {
return studentService.findAll();
}
// 控制器方法:增加学生
@RequestMapping(value = "/addStudent")
public ModelAndView addStudent(Student student) {
ModelAndView mv = new ModelAndView();
int count = studentService.addStudent(student);
if (count > 0) {
mv.addObject("msg","注册成功");
mv.addObject("name",student.getStuName());
mv.setViewName("success");
} else {
mv.addObject("msg","注册失败");
mv.setViewName("fail");
}
return mv;
}
}
service
@Service(value = "studentService")
public class StudentServiceImpl implements IStudentService {
// 自动注入
@Autowired
private StudentMapper studentMapper;
@Override
public List<Student> findAll() {
return studentMapper.findAll();
}
@Override
public int addStudent(Student student) {
return studentMapper.addStudent(student);
}
}
mapper接口和映射文件
// mapper接口
public interface StudentMapper {
/**
* 查询全部
* @return
*/
List<Student> findAll();
/**
* 增加学生
* @param student
* @return
*/
int addStudent(Student student);
}
<mapper namespace="com.mms.mapper.StudentMapper">
<select id="findAll" resultType="Student">
select stuno, stuname
from student
select>
<insert id="addStudent" parameterType="Student">
insert into student (stuno,stuname)
values (#{stuNo},#{stuName})
insert>
mapper>
前台jsp,请求页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
注册页
前台jsp,注册页
前台jsp,展示页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
学生信息页
学生信息
学号
姓名
相信各位在初学javaweb时,访问项目时常会出现404资源不存在,当初我学习时也是同样的情况,一直搞不懂斜杠"/"到底是什么意思,xml中的斜杠和普通jsp页面中的斜杠是一样的吗诸如此类问题,直到我在学习完springmvc后,自己通过测试才弄懂绝对路径、相对路径以及斜杠的意思。下面就听我一一道来。
绝对路径:带斜杠"/"的地址
直接说结论:
a、在web(eclipse中是webContent)下的所有请求若以斜杠开头(绝对地址),此时的斜杠就代表服务器的根目录,即localhost:port/,此类的请求发出必是404,因为少了请求url中少了项目名。
解决方法:显示的在请求的斜杠前使用上下文对象(request.getContextPath)加上项目的名称
b、在servlet中的请求若以斜杆开头,此时的斜杠就代表项目的根目录,即localhost:port/项目名/, 不需要开发人员指定上下文对象
相对路径:不带斜杠"/"的地址,相对于当前资源所在的目录;例如现在有一个index.jsp,它的完整url如下
localhost:8080/项目名/index.jsp,那么它的相对地址就是相对于当前资源所在的路径,即 localhost:8080/项目名/,相对地址就是相对于当前资源所在的路径;./代表当前路径,…/代表当前路径的父级目录。
关于xml、jsp中斜杠的意义
a、xml中的斜杠代表项目根目录,即localhost:8080/项目名
b、jsp中超链接、表单action请求中的斜杠均代表的是绝对路径
c、所有的后台代码(controller)中的斜杠的斜杠代表项目根
为什么要引入这个问题,因为我们现在的所有项目的程序入口DispacherServlet的url-pattern都是*.do这类扩展名方式,若是我们将中央调度器的url-pattern改为/会出现静态资源(图片、css、js等)会报404,为什么会出现这样的问题呢?原因如下:
我们现在的中央调度器的url-pattern都是为"*.do"这样的,当发出的请求匹配url-pattern时会调用相应的
servlet来处理;那些不匹配的请求会交由tomcat内置的默认servlet这个类来处理(例如静态资源css、jsp等)
但是当中央调度器的url-pattern为"/"时(表示拦截一切),此时的servlet的默认servlet就被替代了,
中央调度器默认是没有处理静态资源的能力,所以会出现静态资源找不到的问题。
解决方案:
方案1、在springmvc配置文件中加入标签mvc:default-servlet-handler
原理:再加入这个标签时,在创建springmvc容器时,会创建一个DefaultServletHttpRequestHandler对象,该对象会将所有的静态资源的访问交由tomcat内置的defaultservlet来处理(内部是请求转发形式)
注意:该方式会将所有的请求交由tomcat默认servlet去处理,会覆盖@RequestMapping的请求,需要加入 注解驱动标签
方案2:在springmvc配置文件中加入标签
批量处理静态资源
1、在以前的程序中,我们都是使用try、catch进行异常的处理,但是这样有一个弊端,那就是当我们的程序涉及
到多个异常时,程序会出现很多的try、catch语句块,造成程序的冗余
2、在springmvc中,我们可以使用一个类来专门处理controller类中抛出的异常类,从而减少重复代码,这也是
aop的体现。
3、这个专门处理controller类抛出异常的类的结构:
1)我们在类的声明语句上面要加入注解@ControllerAdvice,这个注解会告诉springmvc框架这个类是全局
异常处理类。在全局异常处理类中定义处理各个异常的方法,这些方法的上面要加入@ExceptionHandler(value=“异常类.class”)。
告诉框架这个方法是处理异常类的方法
4、执行原理:
1)、首先当controller类中抛出异常时,框架发现在springmvc配置文件中的组件扫描器中的一个包下有一个
类的声明处有@ControllerAdvice注解,就会知道这个类是全局异常处理类
2)、当controller类中抛出异常时,会拿着该抛出异常类的类型与全局异常处理类的方法的
@ExceptionHandler(value=“异常类.class”) 的value值异常类类型进行比对,若两者相同则
进入方法执行相应代码;若不同则接着与剩下的方法的@ExceptionHandler(value=“异常类.class”)
进行比对;直至最后进入默认的异常处理方法
5、开发步骤:
1)新建maven项目
2)引入依赖
3)创建一个自定义异常类,再定义它的n个子类,由于表示不同的异常类
4)创建全局异常处理类
5)创建Springmvc配置文件,加入注解扫描器,值为controller、全局异常处理类所在的包;声明注解驱动
三个异常类代码:
// 自定义异常类父类
public class MyException extends Exception{
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
// 年龄异常类
public class AgeException extends MyException{
public AgeException() {
super();
}
public AgeException(String message) {
super(message);
}
}
// 姓名异常类
public class NameException extends MyException {
public NameException() {
super();
}
public NameException(String message) {
super(message);
}
}
控制器
@Controller
public class StudentController {
@RequestMapping(value = "/some.do")
public ModelAndView someDo(String name, Integer age) throws MyException {
ModelAndView mv = new ModelAndView();
// 进行年龄、姓名的判断
if (!("zs".equals(name))) {
// 姓名不是zs,抛出NameException
throw new NameException("姓名不正确");
}
if (!(age > 20 && age < 30)) {
// 年龄不合法,抛出AgeException异常
throw new AgeException("年龄不合法");
}
// 说明姓名、年龄合法,跳转到登陆成功页面
mv.addObject("msg","登陆成功,欢迎您");
mv.addObject("name",name);
mv.setViewName("success");
return mv;
}
}
全局异常处理类
// 全局异常处理类
@ControllerAdvice
public class ExceptionsController {
// 姓名异常类处理方法
@ExceptionHandler(value = NameException.class)
public ModelAndView nameException(Exception exception) {
// 形参exception就代表controller类中抛出的异常对象
ModelAndView mv = new ModelAndView();
// 进行异常类的数据、视图的处理
mv.addObject("msg","姓名不合法,必须为zs");
// 将异常信息发送至前端进行处理,提升用户感知
mv.addObject("exception",exception);
mv.setViewName("nameError");
return mv;
}
// 年龄异常类处理方法
@ExceptionHandler(value = AgeException.class)
public ModelAndView ageException(Exception exception) {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","年龄不合法,必须在20至30之间");
mv.addObject("exception",exception);
mv.setViewName("ageError");
return mv;
}
// 默认异常处理方法
@ExceptionHandler
public ModelAndView defaultException(Exception exception) {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","程序发生了一个不可预知的问题");
mv.addObject("exception",exception);
mv.setViewName("defaultError");
return mv;
}
}
在javaweb阶段我们就知道,要想让一个普通的类具有某种特定功能,要嘛通过继承、要嘛通过实现接口,亦或是通过注解这三种方式可以使一个普通类变得不普通,拦截器也是这样,springmvc框架说了要实现拦截器必须实现HandlerInterceptor接口,我们可以看一下这个接口的定义:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
关于这个接口三个方法:
用户通过前台通过表单提交个人信息,拦截器校验用户信息,若用户名为zs则放行,否则截断请求。
前台jsp,请求
拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandler...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandler...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
controller
@Controller
public class StudentController {
@RequestMapping(value = "/student.do")
public ModelAndView someDo(String name, Integer age) {
System.out.println("someDo...");
ModelAndView mv = new ModelAndView();
mv.addObject("name",name);
mv.addObject("age",age);
mv.setViewName("success");
return mv;
}
}
前台jsp,结果页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登陆
登陆成功,欢迎您:
${name}
至此,SSM框架阶段告一段落了,小编也可以快乐的玩耍了,为了让各位的阅读博文的体验更加好,我也听取了前辈的建议,将之前的Mybatis、Spring以及本篇SpringMVC的代码和笔记上传到了github和gitee仓库,供大家参考,下面是仓库的链接,希望大家一起进步。
github仓库地址
gitee仓库地址