1. 基础知识
1.作用
解决了V-C交互的问题。servlet
在传统的Java EE项目中,使用的Controller是Servlet,在绝大部分时候,用户的每个请求都需要1个Servlet进行处理,那么,在一个比较成熟的项目中,就需要创建大量的Servlet,则会引发一系列的问题:类太多不易于管理和维护;对象太多消耗内存;关于Servlet的配置代码太长也不易于管理和维护!
2.创建项目
创建简单maven并生成web.xml文件
在项目中添加tomcat运行环境
在pom.xml中添加依赖
1
2
3
4
5
6
7
8
9
10
11
12<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
3.核心组件
分类
组件 作用 DispatcherServlet 接收并分发所有请求给对应控制器(前端控制器,不处理请求) HandlerMapping 记录和制定分发方案(记录和处理请求路径与控制器的对应关系) Controller 实际处理请求生成ModeAndView ModeAndView 处理后的数据和视图名称 ViewResolver 通过接收到的视图名称确定响应的视图组件 流程图
Controller注解
注解 名称 @Component 通用注解 @Controller 控制类注解 @Service 业务类注解 @Repository 持久层类
2. MVC流程
1. DispatcherServlet\HandlerMapping
- 作用
- 项目启动时就直接初始化Spring.xml文件,不需要再使用Classpathxmlapplicationcontext进行调用.
- 配置了默认servlet默认转发类型.do.
web.xml
contextConfigLocation可以在class的父类里找到这一属性名
1
2
3
4
5
6
7
8
9
10
11
12
13
14<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--DispatcherServlet-->
<!--初始化servlet时调用Spring.xml文件-->
<init-param><!--HandlerMapping:基于注解的HandlerMapping-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup><!--启动时创建servlet,直接初始化,不能写在前面-->
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern><!--配置所有路径都被servlet处理,配置后的地址不能被访问>
</servlet-mapping>测试
启动时自动创建Component对象
1
2
3
4
5
6
public class User {
public User() {
System.out.println("User()");
}
}
2. Controller\ModelAndView
相当于servlet,返回值是ModelAndView
String.xml
controller扫描
1
<context:component-scan base-package="cn.tedu.包名"></context:component-scan>
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
*1. 权限:无所谓,但是,应该使用public
*2. 方法名:自定义
*3. 参数:暂无[可以是接收表单或AJAX数据]
*4. 返回值:返回[数据和]视图名.
null:自动查找与RequestMapping名相同的文件
String:查找与文件名相同的文件
*5.@RequestMapping:用于映射地址和控制器
return:用于映射控制器和文件
*/
public class userController{
"hello.do") (
public String showHello() {
syso("内容");
return "hello";//modelAndView
}
}
测试
当访问hello.do时控制台输出”内容”;
3.ViewResolver
决定位置
原理:
- 创建一个InternalResourceViewResolver对象(之前是自己写一个类然后创建)
- 默认根目录是webapp,引导到/前缀/return返回值.后缀(/WEB-INF/hello.jsp)
- 抽象类不能被直接使用,因此使用的是继承VIewResolver接口的子类
Spring.xml
prefix/suffix是InternalResourceViewResolver父类的属性
1
2
3
4
5
6<context:component-scan base-package="cn.tedu.spring"></context:component-scan>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />//前缀
<property name="suffix" value=".jsp" />//后缀
</bean>测试
访问hello.do,根据返回值访问网页,最后结果
3. 响应处理结果
1.重定向
1 | //访问handle_reg.do----login.do |
2.转发
- 正常情况
1 | "handle_login.do") ( |
- ModelAndView[不推荐]
1 | "handle_login.do") ( |
3.session
java
1
2
3
4
5
6
7
8
9
10"reg.do") (
public String register(HttpSession session){
Object count = session.getAttribute("count");
if(count==null){
count = 1;
}else{
count = (Integer)count+1;
}
session.setAttribute("count");
}
4. @RequestMapping[设置目录]
设置父目录
1
2
3
4
5
6
7
8
"User")//当配置进制只允许提交方式时必须用[value="User"] (
public class User{
"login.do") (
public String login(){
return "";
}
}设置只允许使用某种提交方式
使用别的提交方式会提示405错误
1
2
3
4
5
6
7
8
"User" method=RequestMethod.POST)//只允许使用POST (value=
public class User{
"login.do") (
public String login(){
return "";
}
}postMapping
在方法上用postMapping
5. @RequestParam(参数命名)
使用情况
- 客户端的名字跟程序的不一样时
- 必须添加某一个参数时
- 需要添加默认值时[非默认]
设置别名
1
2
3public String handleLogin(@RequestParam("uname") String username,String password){
//当提交的表单中的名字为uname时也可以,但是必须提交否则400错误
}
设置不必须添加参数
默认有一个隐式required=true
1
"uname",required=false) (value=
设置默认值
1
"uname",required=false,defaultValue="") (value=
4.拦截器
详细内容
拦截器是SpringMVC的组件,用于拦截或者放行
preHandle方法中定义if满足条件时返回下列
- return=true时:拦截器放行;
- return=flase时:拦截器拦截;剩余的两个方法执行:postHandlle()/afterCompletion()
仅能拦截Dispatcher所配置的文件
例子:若dispatcher仅配置了*.do文件,那么.jsp文件不经过MVC,因此不能拦截;
xml配置:拦截器(拦截器的url路径/拦截器规则所在类)
通配符
通配符 作用 案例 * 代表拦截层数 /user/* 可以拦截/user/a.jsp /user/**可以拦截/user/a.jsp和/user/a/a.jsp ? 代表拦截文件[不常用] /user/????.jsp 黑名单
多个拦截器时,生效顺序取决于拦截器的书写顺序
1
2
3
4
5
6
7
8
9
10<!-- 配置拦截器链 -->
<mvc:interceptors>
<!--拦截器-->
<mvc:interceptor>
<!-- 拦截路径 -->
<mvc:mapping path="需要拦截url地址"/>
<!-- 拦截器类-->
<bean class="java配置的所在类"></bean>
</mvc:interceptor>
</mvc:interceptors>白名单+黑名单[简易]
白名单上的路径不经过拦截器,直接进入controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14<mvc:interceptors>
<mvc:interceptor>
<!-- 1:父类下的全部为黑名单 -->
<mvc:mapping path="/user/*"/>
<!-- 2:父类下的例外/白名单 -->
<mvc:exclude-mapping path="/user/reg.do"/>
<mvc:exclude-mapping path="/user/register.do"/>
<mvc:exclude-mapping path="/user/login.do"/>
<mvc:exclude-mapping path="/user/handle_reg.do"/>
<mvc:exclude-mapping path="/user/handle_login.do"/>
<!-- 3:拦截器类 -->
<bean class="cn.tedu.spring.拦截器类名"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器类:拦截器规则[,以及是否拦截]
需要实现HandleServletInterceptor类,并重写preHandle方法
1
2
3
4
5
6
7
8public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception {
if(不满足条件){
response.sendRedirect("/web/login.html");//重定向到一个网站
return false;//不放行:不可以访问
}else{
return true;//放行:可以访问
}
}
5.解决乱码
javaEE方法失效
javaEE中是在servlet之前生效,现在是在Controller之前生效,所以会导致失败
web.xml
1
2
3
4
5
6
7
8
9
10
11
12<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>
6.访问静态资源
1.<mvc:resources />
spring3.0.4之后新功能,与test测试冲突
spring.xml
1 | <mvc:resources mapping="/**" location="/" /> |
mapping:—>location,可以使用classpath
*:当前目录
**:当前目录及子目录
2.defaultServlet[推荐]
Tomcat自带功能
web.xml
1 | <servlet-mapping> |
3.<mvc:default-servlet-handler />
最后更新: 2019年11月06日 11:36