第一部分
SpringMVC代码角度实现流程:
- 在新创建的动态web项目中,webcontent下的WEB-INF下的lib文件中导入所需要的jar包
- 需要在当前项目结构下的web.xml中进行相关的配置
- 这些配置包括中央调度器的配置,其中包括DispatcherServlet类,init-param标签用于指定MVC的配置文件的位置还有文件名,load-on-startup标签用于表示容器启动时立即启动servelt,servelt-mapping
- 用于配置调用中央调度器的请求URL格式
- .在src下创建一个类,这个类要实现controller,表示当前类是一个控制器类
- 类中的实现方法handleRequest中完后请求的处理过程代码
- 同时,控制器类的创建需要在springMVC的配置文件中进行注册
- 在webcontent下的WEB-INF中创建页面接收响应
SpringMVC的执行流程
- 通过图示,可以发现,在整个的执行流程中,包括有一个类,四个接口
类:DispatcherServlet
接口:handlermapping、handlerAdapter、Controller、ViewResolver - 所有的请求,都会经过中央调度器,由中央调度器进行整体的调度
SpringMVC中中央调度器的配置阐述
如果在指定的url中使用/,需要怎样访问静态资源
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
这种方式能够应用于所有的web方式,用于处理/处理不了的静态资源请求
第二部分:SpringMVC 配置式开发
2.1 存在有开发人员配置的过程
2.2 处理器映射器(HandleMapping)
用于匹配响应的Controller/Interceptor(拦截器),将符合要求的Controller进行封装,以执行链的形式返回给DispatcherServlet
实现类:
-
BeanNameUrlHandlerMapping:默认的使用方式,在不进行处理器映射配置时,要求Spring配置文件中的Controller请求以/开头,适用于处理器的请求仅限一个时,使用这种方式即可,在多个时,也可以使用,但不是特别好
-
SimpleUrlHandlerMapping:需要进行配置,在Spring的配置文件中,这种方式可以将url和处理器进行分离
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <!-- <property name="urlMap"> <map> <entry key="/myController1.do" value="MyController"></entry> <entry key="/myController2.do" value="MyController"></entry> <entry key="/myController3.do" value="MyController"></entry> </map> </property> --> <property name="mappings"> <props> <prop key="/myController4.do">MyController</prop> <prop key="/myController5.do">MyController</prop> <prop key="/myController6.do">MyController</prop> </props> </property> </bean>
2.3 处理器适配器(HandleAdapter)
实现类:
HttpRequestHandlerAdapter:需要当前自定义的类实现HttpRequestHandler接口,这种情况 下,处理器适配器就执行的是HttpRequestHandlerAdapter这个实现类
SimpleControllerHandlerAdapter:当自定义的类实现了Controller接口时,默认情况下处理器适配器使用的就是这种方式
2.4 处理器/控制器(Controller)
-
除了实现Controller和HttpRequestHandler之外,还可以继承一些类,这些类能够让我们的处理器拥有一些其他的功能
-
继承AbstractController类:我们可以对处理器对象进行属性注入,规定请求方式为POST,请求更安全
-
继承MultiActionController类:
- InternalPathMethodNameResolver方法解析器:这个类中有一个方法解析器methodNameResolver,默认情况下InternalPathMethodNameResolver,会将方法名解析为资源名称,因此浏览器中地址栏中的url的资源名称需为方法名称
<!-- 注册处理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/*.do">MyController</prop> </props> </property> </bean> <!-- 注册处理器 --> <bean id="MyController" class="com.dem.springmvc.MyController"></bean> <!-- 注册视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="Prefix" value="/WEB-INF/"></property> <property name="Suffix" value=".jsp"></property> </bean> <!-- 使用这种方法解析器访问格式为:http://localhost:8080/StudySpringMVC01/first.do first.do为资源名称,first与方法名称对应 -->
- PropertiesMethodNameResolver方法解析器:需要在spring的容器中进行配置,配置的方式通过为处理器对象注入MethodNameResolver这个属性进行,这个过程中,需要这个属性指向PropertiesMethodNameResolver方法解析器,因此,我们还需要进行PropertiesMethodNameResolver这个属性的注册,在这个方法解析器的注册中,完成对方法名称和url的对应关系
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/*.do">MyController</prop> </props> </property> </bean> <!-- 注册一个新的方法解析器PropertiesMethodNameResolver --> <bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver" id="myPropertiesMethodNameResolver"> <property name="mappings"> <props> <prop key="/myFirst.do">first</prop> <prop key="/mySecond.do">second</prop> <prop key="/myThird.do">third</prop> </props> </property> </bean> <!-- 注册处理器 --> <bean id="MyController" class="com.dem.springmvc.MyController"> <property name="MethodNameResolver" ref="myPropertiesMethodNameResolver"></property> </bean> <!-- 使用PropertiesMethodNameResolver这种方式进行解析时,URL的格式为:http://localhost:8080/StudySpringMVC01/myFirst.do myFirst.do指的是解析器中与方法名对应的url -->
- ParameterMethodNameResolver方法解析器:这个方法解析器同样需要在Spring的容器中进行配置,配置的方式通过为处理器对象注入MethodNameResolver这个属性进行,这个过程中,需要这个属性指向ParameterMethodNameResolver方法解析器,因此还需要进行方法解析器的注册,这个注册中可以对paramName进行属性注入,指定参数名称,这个名称是可以自定义的,也可以不进行注入,使用默认的action
<!-- 注册处理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/fwx.do">MyController</prop> </props> </property> </bean> <!-- 注册一个新的方法解析器PropertiesMethodNameResolver --> <bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver" id="myPropertiesMethodNameResolver"> <!-- property这个属性可以不进行书写,不写默认值为action 此时URL格式为:http://localhost:8080/StudySpringMVC01/fwx.do?action=second --> <property name="paramName" value="abc"></property> </bean> <!-- 注册处理器 --> <bean id="MyController" class="com.dem.springmvc.MyController"> <property name="MethodNameResolver" ref="myPropertiesMethodNameResolver"></property> </bean> <!-- 使用这种解析器时,URL格式:http://localhost:8080/StudySpringMVC01/fwx.do?abc=first fwx.do是处理器映射器中指定的url,?之后是方法解析器中指定的参数 -->
2.5 ModelAndView对象
模型与视图,包含有模型Model与视图view两部分,在代码中,我们通过addIbject()为模型添加数据,而通过SetViewName()为模型指定视图名称
-
模型:本质上是一个ModelMap,ModelMap底层是LinkedHashMap
-
视图:本身是一个视图对象,这个对象是被封装在ModelAndView中的,我们在使用SetViewName()时,传入的是一个String对象
2.6 视图解析器(ViewResolver)
- InternalResourceViewResolver:默认的视图解析器,这种解析器可以完成视图名称前缀和后缀的指定,如果未指定,按默认的方式进行解析
<!-- 注册视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="Prefix" value="/WEB-INF/"></property>
<property name="Suffix" value=".jsp"></property>
</bean>
-
BeanNameViewResolver:将视图名称封装为Spring容器中注册的Bean实例,在定义Bean实例时,需将资源分为内部资源和外部资源,定义内部资源实例要用到JstlView,如果定义的是外部资源,需要用到RedirectView
访问视图时,通过bean实例的id来进行访问
springMVC.xml:
<!-- 注册BeanNameViewResolver视图解析器 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"></bean>
<!-- 定义一个first.jsp的Bean对象 -->
<bean class="org.springframework.web.servlet.view.JstlView" id="myFirstView">
<property name="url" value="/WEB-INF/first.jsp"></property>
</bean>
MyController.java:
public ModelAndView first(HttpServletRequest request, HttpServletResponse response) {
ModelAndView view = new ModelAndView();
view.addObject("message", "欢迎来到......first.....");
view.setViewName("myFirstView");
return view;
}
外部视图RedirectView访问百度:
<bean class="org.springframework.web.servlet.view.RedirectView" id="myBaiduView">
<property name="url" value="http://www.baidu.com"></property>
</bean>
- XmlViewResolver:这种视图解析器,可以将视图资源分离出来
springMVC.xml:
<!-- 注册新的视图解析器 xmlViewResolver -->
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="location" value="classpath:myView.xml"></property>
</bean>
myView.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 定义一个first.jsp的Bean对象 -->
<bean class="org.springframework.web.servlet.view.JstlView" id="myFirstView">
<property name="url" value="/WEB-INF/first.jsp"></property>
</bean>
<bean class="org.springframework.web.servlet.view.RedirectView" id="myBaiduView">
<property name="url" value="http://www.baidu.com"></property>
</bean>
<bean class="org.springframework.web.servlet.view.JstlView" id="mySecondView">
<property name="url" value="/WEB-INF/first.jsp"></property>
</bean>
</beans>
- ResourceBundleViewResolver:这种视图解析器,也是将视图资源分离出来
springmvc:
<!-- 注册新的视图解析器-->
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basenames" value="myView"></property>
</bean>
myView.properties:
myFirstView.(class) = org.springframework.web.servlet.view.JstlView
myFirstView.url = /WEB-INF/first.jsp
myBaiduView.(class) = org.springframework.web.servlet.view.RedirectView
myBaiduView.url = http://www.baidu.com
第三部分:SpringMVC注解式开发
3.1一种基于注解的类的开发
比如说,处理器的表示无需再配置文件中进行注册,也无需事先某个接口,只需要在类中和某个方法中进行注解,便可对处理器进行表示
在这个过程中,注解替换掉了注册的部分。实际开发中,常使用注解式开发
3.2 完成注解式的程序
@Controller
用在类上,表示当前类为处理器
@Controller
//表示当前类是一个处理器
public class MyController{
@RequestMapping(value= "/first.do")
public ModelAndView firstMethod(HttpServletRequest request, HttpServletResponse response) {
ModelAndView view = new ModelAndView();
view.addObject("message", "欢迎来到SSM");
view.setViewName("/WEB-INF/first.jsp");
return view;
}
}
<!-- 组件扫描器注册 -->
<context:component-scan base-package="com.dem.springmvc"></context:component-scan>
@RequestMapping
用在类上,表示当前处理器的命名空间,用在方法上,表示请求资源名称
@Controller
//表示当前类是一个处理器
@RequestMapping(value="/f/w/x")
//命名空间
public class MyController{
@RequestMapping(value= "/first.do")
public ModelAndView firstMethod(HttpServletRequest request, HttpServletResponse response) {
ModelAndView view = new ModelAndView();
view.addObject("message", "欢迎来到SSM");
view.setViewName("/WEB-INF/first.jsp");
return view;
}
}
//url访问:localhost:8080/StudySpringMVC01/f/w/x/first.do
@RequestMapping(value= {"/first.do","second.do"})
public ModelAndView firstMethod(HttpServletRequest request, HttpServletResponse response) {
ModelAndView view = new ModelAndView();
view.addObject("message", "欢迎来到SSM");
view.setViewName("/WEB-INF/first.jsp");
return view;
}
//RequestMapping中value的值本身是一个string类型的数组
3.3 请求的资源名称相关通配符的使用
-
before/资源名称
-
third*:表示url路径中资源名称要以third开头才能访问
@RequestMapping(value= {"/third*.do"})
//url访问:http://localhost:8080/StudySpringMVC01/f/w/x/thirdsdf.do
- *third:资源名称要以third结尾才能进行访问
@RequestMapping(value= {"/*third.do"})
//url访问:http://localhost:8080/StudySpringMVC01/f/w/x/sdfthird.do
- before/*/third:表示url路径中,before与third之间需要有以及路径,而且必须要有,不能多不能少
@RequestMapping(value= {"/*/third.do"})
//url访问:http://localhost:8080/StudySpringMVC01/f/w/x/fwx/third.do
- before/**/third:表示url路径中,before与third之间可以有多级路径,也可以没有
@RequestMapping(value= {"/**/third.do"})
/*
url访问:
http://localhost:8080/StudySpringMVC01/f/w/x//third.do
http://localhost:8080/StudySpringMVC01/f/w/x/fwx/third.do
http://localhost:8080/StudySpringMVC01/f/w/x/fwx/fwx2/third.do
*/
- before /**/third *
3.4 请求提交方式
@RequestMapping(value= "/**/third.do",method=RequestMethod.POST)
3.5 请求中携带参数 params
@RequestMapping(value= {"/first.do","second.do"},params= {"name","age"})
//url访问:http://localhost:8080/StudySpringMVC01/demo/first.do?name="fwx"&age=20
以上表示请求中需要参数name,age
@RequestMapping(value= {"/first.do","second.do"},params= {"age=20"})
//url访问:http://localhost:8080/StudySpringMVC01/demo/first.do?age=20
3.6 处理器方法中参数
<form action="${pageContext.request.contextPath }/demo/first.do" method="get">
<form action="demo/first.do" method="get">
请求中携带的参数:逐个接受参数的方式,这种方式则是将数据作为处理器方法的参数逐个接收的过程
index.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<%-- <form action="${pageContext.request.contextPath }/demo/first.do" method="get"> --%>
<form action="demo/first.do" method="get">
姓名:<input type="text" name="name">
年龄:<input type="text" name="age">
<input type="submit" value="提交">
</form>
</body>
</html>
mycontroller.java:
@RequestMapping(value= {"/first.do"})
public ModelAndView firstMethod(String name,int age) {
System.out.println(name);
System.out.println(age);
ModelAndView view = new ModelAndView();
view.addObject("name", name);
view.addObject("age", age);
view.setViewName("/WEB-INF/first.jsp");
return view;
}
first.jsp:
<body>
${name}
${age}
</body>
3.7 配置过滤器(防止乱码)
<!-- 配置过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.8 参数校正
@RequestParam:用在方法类中的注解
public ModelAndView firstMethod(@RequestParam(value="sname") String name,int age)
以对象的形式接收参数
- 以对象的方式整体接收,要求实体类中的属性名称必须要与表单提交中的参数名称相同
index.jsp:
<body>
<%-- <form action="${pageContext.request.contextPath }/demo/first.do" method="get"> --%>
<form action="demo/first.do" method="get">
姓名:<input type="text" name="ename">
年龄:<input type="text" name="age">
<input type="submit" value="提交">
</form>
</body>
employee.java:
private String ename;
private int age;
//构建实体类
myController.java:
@Controller
//表示当前类是一个处理器
@RequestMapping(value="/demo")
//命名空间
public class MyController{
// 处理器方法
@RequestMapping(value= {"/first.do"})
public ModelAndView firstMethod(Employee employee) {
System.out.println(employee.toString());
ModelAndView view = new ModelAndView();
view.addObject("employee", employee);
view.setViewName("/WEB-INF/first.jsp");
return view;
}
}
对象属性提交方式:也要有相应的实体类属性名称相同的要求
index.jsp
<body>
<%-- <form action="${pageContext.request.contextPath }/demo/first.do" method="get"> --%>
<form action="demo/first.do" method="get">
姓名:<input type="text" name="ename">
年龄:<input type="text" name="age">
部门:<input type="text" name="department.dname">
<input type="submit" value="提交">
</form>
</body>
department.java
//构建实体类
private String dname;
employee.java
//构建实体类
private String ename;
private int age;
private Department department;
- employee.java、department.java之间存在一对多的关系
3.7 处理器方法的返回值
**ModelAndView:**当我们的处理器方法执行完成之后,如果我们需要跳转到其他的页面,在跳转过程中,需要传递数据
**String:**处理器方法执行结束后,进行页面跳转,其中一种方式直接返回物理视图名称,还可以使用外部视图名称
- /WEB-INF/first.jsp:物理视图名称
- first:逻辑视图名称,需要在springMVC配置文件中配置视图解析器,指定前缀和后缀
- 视图对象:在Spring配置文件中使用BeanNameViewResolver视图解析器,来将视图交给spring,在spring配置文件中定义视图对象,这种情况下,我们可以进行外部资源调整
MyController.java:
@RequestMapping(value= {"/first.do"})
public String firstMethod() {
return "first";
}
Springmvc.xml:
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="Prefix" value="/WEB-INF/"></property>
<property name="Suffix" value=".jsp"></property>
</bean>
**void:**可以使用处理器方法参数,HttpServletRequest,HttpServletResponse
mycontoller.java
@RequestMapping(value= {"/first.do"})
public void firstMethod(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
request.getRequestDispatcher("/WEB-INF/first.jsp").forward(request, response);
}
Object:
第四部分:SpringMVC中的其他技术
4.1 类型转换器
String —Date转换
MyConverter.java
package com.dem.converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Pattern;
import org.springframework.core.convert.converter.Converter;
/*
* 自定义类型转换器,此转换器用于转换日期格式
* S:要转换数据的类型
* T:要转换成的目标类型
*/
public class MyConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdf = getSimpleDateFormat(source);
try {
return sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
private SimpleDateFormat getSimpleDateFormat(String source) {
// 完成不同日期格式的匹配,进而对不同的日期格式进行转换
SimpleDateFormat sdf = new SimpleDateFormat();
if (Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) {
sdf = new SimpleDateFormat("yyyy-MM-dd");
}
if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) {
sdf = new SimpleDateFormat("yyyy/MM/dd");
}
return sdf;
}
}
SpringMVC.xml
<!-- 转换器的注册 -->
<bean class="com.dem.converter.MyConverter" id="MyConverter"></bean>
<!-- 转换器的服务对象的注册 -->
<bean class="org.springframework.context.support.ConversionServiceFactoryBean" id="myConversionServiceFactoryBean">
<property name="converters" ref="MyConverter"></property>
</bean>
<!-- 在注解驱动中配置转换服务 -->
<mvc:annotation-driven conversion-service="myConversionServiceFactoryBean"></mvc:annotation-driven>
MyController.java
@RequestMapping(value= {"/first.do"})
public ModelAndView firstMethod(String ename,int age,Date birthday) {
System.out.println(birthday);
ModelAndView view = new ModelAndView();
view.addObject("ename", ename);
view.addObject("age", age);
view.addObject("birthday", birthday);
view.setViewName("/WEB-INF/first.jsp");
return view;
}
index.jsp
<%-- <form action="${pageContext.request.contextPath }/demo/first.do" method="get"> --%>
<form action="demo/first.do" method="get">
姓名:<input type="text" name="ename">
年龄:<input type="text" name="age">
生日:<input type="text" name="birthday">
<input type="submit" value="提交">
</form>
4.2 端口被占用问题
win+R—>cmd—>netstat -ano—>找到8080
taskkill /pid/ 11532 -f