sprig MVC学习总结"/>
sprig MVC学习总结
Spring MVC
提示:本文学习总结可能存在多处错误,浏览过程发现错误请在评论区描述
文章目录
- Spring MVC
- 作用
- 一、请求的处理流程
- 二、配置文件
- 1.配置中央调度器
- 2、字符集过滤器
- 3、视图解析器
- 三、注解开发
- 常见注解
- 请求方式
- GET
- POST
- 处理器方法的参数
- HttpServletRequest,HttpServletResponse,HttpSession
- 请求中所携带的请求参数
- 逐个接收参数
- @RequestParam注解
- 对象接收方案
- 返回类型
- ModelAndView
- String
- 只是页面的跳转
- String表示数据
- void
- 静态资源访问
- 相对路径和绝对路径
- 转发和重定向
- 拦截器
- 总结
作用
是一个表现层框架,从请求中接收传入的参数,将处理后的结果返回给页面
一、请求的处理流程
1)------发起请求
2)------先发给tomcat服务器
3)------tomcat读取web.xml配置文件
4)------根据将请求给对应的中央调度器DispatcherServlet
5)------中央调度器拿到请求后,读取springmvc的配置文件,读取组件扫描器
6)------根据组件扫描器和请求扩展名知道给哪个控制器的哪个方法处理
1、用户发憷请求,请求被Spring MVC的前端控制器DispatcherServlet截获
2、DispatcherServlet对请求的URL进行解析,得到URI(请求资源标识符),然后根据URI,调用HandlerMapping获得该Handler配置的所有相关对象,包括Handler对象和Handler对象的拦截器,
3、DispatcherServlet根据获取的Handler,选择一个合适的HandlerAdapter。HandlerAdapter的设计符合对象中的单一实际处理请求结果
4、提取请求中的模型数据,开始执行Handler(Controller),在填充Handler的参数过程中,根据配置,spring将帮助做一些额外的工作
5、Handler执行完成后,会向DispatcherServlet返回一个ModelAndView对象,对于那些返回是String,Map,或者ModelMap的方法,Spring MVC也会在内部把它包装成一个ModelAndView对象。ModelAndView包含视图名或者视图模型。
6、DispatcherServlet根据返回的ModelAndView对象,选择一个合适的视图解析器(ViewResolver)
7、ViewResolver结合Model和View来渲染视图
8、DispatcherServlet将视图渲染结果返回给客户端
二、配置文件
1.配置中央调度器
<servlet><servlet-name>myweb</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:conf/dispatcherServlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>myweb</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping>
中央调度器被创建之后,会调用Servlet的init()方法,在方法中创建springmvc容器对象,加载配置文件。自定义springMVC读取配置文件的位置<param-value>classpath:conf/dispatcherServlet.xml</param-value>
,以及确定DispatcherServlet的创建时间<load-on-startup>1</load-on-startup>
。
创建springmvc容器对象的时候,默认读取的是/WEB-INF/-servlet.xml。
请求能使用的扩展名<url-pattern>
方式有两种:以设定的扩展名结尾的请求都交给<servlet-name>
对应的中央调度器。
1、*.xxx,xxx是自定义的扩展名,常用的有".do",“.action”等
2、使用斜杠“/”,在静态资源访问处记录
2、字符集过滤器
<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><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>*</url-pattern></filter-mapping>
CharacterEncodingFilter的有三个参数需要设置:
encoding:表示指定的字符集编码
forceRequestEncoding:表示是否同时设置Request的编码(true表示设置)
forceResponseEncoding:表示是否同时设置Response的编码(true表示设置)
<filter-mapping>
设置哪些请求需要使用指定字符集编码过滤。
3、视图解析器
<!-- springmvc的配置文件,声明controller和其他web相关的对象--><context:component-scan base-package="com.SSM.controller"/><!-- 视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean>
三、注解开发
先看看文件结构和内容
@Controller
@RequestMapping("/student")
public class StudentController {@RequestMapping("/show.do")public ModelAndView addshow(String name,String age){ModelAndView mv = new ModelAndView();mv.addObject("name",name);mv.addObject("age",age);mv.setViewName("show");return mv;}
}
常见注解
@Controller:表示在tomcat启动的时候,把这个类作为一个控制器加载到Spring的Bean工厂。
@RequestMapping:表示请求的
1、当@RequestMapping在类上边:表示请求的公共部分
2、当@RequestMapping在方法上边:表示请求的名称
请求方式
GET
默认请求是get的请求方式,当是get请求组方式,在控制器的方法上不需要做特殊的处理,或者也可以加上属性method=RequestMethod.GET
@RequestMapping("/some.do",method=RequestMethod.GET)
public ModelAndView doSome(){
.......
}
POST
当前端弄得请求指定了请求方式为POST请求,在控制器的处理方法上也需要配置属性。
post方式请求,中文会有乱码,需要使用过滤器处理乱码的问题
@RequestMapping("/some.do",method=RequestMethod.POST)
public ModelAndView doSome(){
.......
}
处理器方法的参数
处理器方法的采纳数可以有以下四种类型:
HttpServletRequest:请求
HttpServletResponse:应答
HttpSession:对话
请求中所携带的请求参数
- 前三个参数框架会自动给他们赋值
HttpServletRequest,HttpServletResponse,HttpSession
这三个参数框架会自动赋值,不需要开发手动赋值
// 前端发起请求:http://localhost:8080/ch01_HttpServletRequest/some.do?name=zhangsan
@RequestMapping("/some.do")
public ModelAndView doSome(HttpServletRequest request){ModelAndView mv = new ModelAndView();mv.addObject("name=",request.getParameter("name"));mv.setViewName("show");return mv;
}
// 在show页面,能够显示name=zhangsan
请求中所携带的请求参数
逐个接收参数
要求:处理器方法的形参名和请求中的参数名称必须一致,同名的请求桉树赋值给同名的形参
前端请求
<form action="show.do">zhanghao:<input type="text" name="name">mima:<input type="text" name="age"><input type="submit" value="提交参数"></form>
后端控制器类接收参数
@RequestMapping("/show.do")public ModelAndView dointerceptor(String name,Integer age) {ModelAndView mv = new ModelAndView();mv.addObject("name",name);mv.addObject("age",age);mv.setViewName("show");return mv;}
在show.jsp页面能够获取name和age的值
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h2>接收的name参数值:${name}</h2>
<h2>接收的age参数值:${age}</h2></body>
</html>
原理:框架接收请求的参数
1、使用request对象接收参数
------String name = request.getParameter(“name”);
------String age = request.getParameter(“age”)
2、springmvc框架通过中央调度器调用控制器的dodointerceptor()方法,按名称对应,把接收的参数赋值给形参,框架会提供类型转换的功能
@RequestParam注解
当请求中的参数和处理器方法的形参不一致的时候,可以使用这个注解来解决名称不一致的问题
@RequestParam("请求中的参数名称”)
前端:
<form action="show.do">zhanghao:<input type="text" name="myname">mima:<input type="text" name="myage"><input type="submit" value="提交参数"></form>
后端控制器
@RequestMapping("/show.do")public ModelAndView dointerceptor(@RequestParam("myname")String name,@RequestParam("myage")Integer age) {ModelAndView mv = new ModelAndView();mv.addObject("name",name);mv.addObject("age",age);mv.setViewName("show");return mv;}
对象接收方案
需要一个保存请求参数的普通类,并且这个类的属性名和请求的参数名要一样
在这种方式中,@RequestParam注解没有作用
前端代码:
<form action="show.do">zhanghao:<input type="text" name="myname">mima:<input type="text" name="myage"><input type="submit" value="提交参数"></form>
后端代码:
// 创建一个保存请求参数的普通类
public class Student{private String myname;private Integer myage;// 添加set和get方法// 无参构造方法
}//控制器类的方法@RequestMapping("/show.do")public ModelAndView dointerceptor(Student mystudent) {ModelAndView mv = new ModelAndView();mv.addObject("name",mystudent.getMyname());mv.addObject("age",mystudent.getMyage());mv.setViewName("show");return mv;}
返回类型
返回的数据类型可以有一下几种:
1、ModelAndView
2、String
3、void
4、Object对象
ModelAndView
有数据和视图,对视图进行forward操作
String
只是页面的跳转
处理器方法返回String表示视图名称。当return视图的完整视图路径,则不能配置视图解析器
前端请求
<form action="show.do">zhanghao:<input type="text" name="name">mima:<input type="text" name="age"><input type="submit" value="提交参数"></form>
后端处理器方法
//控制器类的方法@RequestMapping("/show.do")public String dointerceptor(HttpServletRequest request,String name,Integer age) {// 可以自己手工添加数据到request作用域// request.setAttribute("name",name);// request.setAttribute("age",age);return "show";}
return返回逻辑视图名称,框架对视图执行forward转发操作
String表示数据
区分 String是比哦啊还是视图还是数据,看方法上是否有注解@ResponseBody,有这个注解String表示数据,反之,String表示视图
- @ResponseBody
作用:把处理器方法返回对象转为json后,通过HttpServletResponse输出给浏览器
位置:方法定义的上边
@RequestMapping(value = "/returnStringData.do",produces = "text/plain;charset=utf-8")@ResponseBodypublic String doStringData(String name,Integer age){return "Hello SpringMVC 返回对象,表示数据";}
问题:
String表示数据,数据包含中文传到前端会出现乱码,前端默认的编码格式是text/plain;charset=ISO-8859-1
解决办法:在@RequestMapping注解中设置属性produces = “text/plain;charset=utf-8”
void
不能表示视图,也不能表示数据,一般用在ajax应答操作上。
$.ajax({url:"dosome.do",data:{name:"zhangsan",age:20},type:"post",dataType:"json"success:function(resp){alert(resp);}
})
@RequestMapping(value = "/returnVoid-ajax.do")public void doReturnVoidAjax(HttpServletResponse response, String name, Integer age) throws IOException {System.out.println("===doReturnVoidAjax====, name="+name+" age="+age);//处理ajax, 使用json做数据的格式//service调用完成了, 使用Student表示处理结果Student student = new Student();student.setName("张飞同学");student.setAge(28);String json = "";//把结果的对象转为json格式的数据if( student != null){ObjectMapper om = new ObjectMapper();json = om.writeValueAsString(student);System.out.println("student转换的json===="+json);}//输出数据,响应ajax的请求response.setContentType("application/json;charset=utf-8");PrintWriter pw = response.getWriter();pw.println(json);pw.flush();pw.close();}
静态资源访问
<servlet-mapping><servlet-name>myweb</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
当配置“/”,导致所有的请求包括静态资源都交给DispathcherServlet处理,默认情况下DispathcherServlet没有处理静态资源的能力,没有控制器能处理静态资源访问请求,所以静态资源(html,图片,js)都是404。
为了解决DispathcherServlet能够处理静态资源的访问,解决办法有两种
1、在springmvc配置文件中使用<mvc:default-servlet-handler/>
tomcat的web.xml文件有一个servlet 名称是 default , 在服务器启动时创建的。
表示访问静态资源和未映射的请求都是有default处理
注意:由于<default-servlet-handler/>
和@RequestMapping注解有冲突,需要加入<mvc:annotation-driven/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xmlns:mvc=""xsi:schemaLocation=" .xsd .xsd .xsd"><!-- 加入注解驱动--><mvc:annotation-driven/><!-- 静态资源访问===================================================================--><mvc:default-servlet-handler/><!-- 静态资源访问===================================================================--></beans>
原理是加入这个标签后,框架会创建控制器对象DefaultServletHttpServletHandler,当接收到静态请求后,DefaultServletHttpServletHandler会吧请求转发给tomcat的default这个servlet。
2、在springmvc配置文件中使用<mvc:resources mapping="" location=""/>
标签。
加入这个标签,框架会创建ResourceHttpRequestHandler这个处理器对象,让这个对象处理静态资源访问请求,不依赖tomcat服务器。
mapping:访问静态资源的url地址,使用通配符 **
location:静态资源你在项目中的位置
<mvc:resources mapping="/image/**" location="/static/image/"/><mvc:resources mapping="/html/**" location="/static/image/"/><mvc:resources mapping="/js/**" location="/static/image/"/>
相对路径和绝对路径
在页面(jsp,HTML)中使用的地址,都是前端页面的地址,都是相对地址
地址分类
1、绝对地址:带有协议名称的都是绝对地址,例如:
2、相对地址:没有协议开头的,例如 user/some.do,/user/some.do。相对地址不能单独使用,必须有一个参考地址,通过参考地址+相对地址本省才能制定资源
3、参考地址:
访问地址不加“/”
<!--index.jsp-->
<p><a href="user/some.do">发起请求</a></p>
访问地址:http://localhost:8080/ch01_path/index.jsp
路径:http://localhost:8080/ch01_path/
资源:index.jsp
在index.jsp页面发起user/some.do,浏览器的访问地址就会变成http://localhost:8080/ch01_path/user/some.do
所以:没有斜杠的请求,点击链接,访问地址变成当前页面的路径 + 链接的地址
访问地址加"/"
<!--index.jsp-->
<p><a href="/user/some.do">发起请求</a></p>
访问地址:http://localhost:8080/ch01_path/index.jsp
路径:http://localhost:8080/ch01_path/
资源:index.jsp
在index.jsp页面发起user/some.do,浏览器页面访问地址会变成http://localhost:8080/user/some.do
,少了项目名称部分。参考地址则变成http://localhost:8080/
这样页面访问是空白,失败的,要想访问成功,可以使用EL表达式(${pageContext.request.contextPath}
)那么,访问的链接地址变成href="${pageContext.request.contextPath}/user/some.do"
,这样就可以正常访问。
前提:在后端控制器设置在index.jsp页面some.do请求后访问的页面还是index.jsp。index.jsp 访问 user/some.do , 返回后现在的地址: http://localhost:8080/ch06_path/user/some.dohttp://localhost:8080/ch06_path/user/some.do路径: http://localhost:8080/ch06_path/user/资源: some.do在index.jsp在 user/some.do ,就变为 http://localhost:8080/ch06_path/user/user/some.do解决方案:1.加入${pageContext.request.contextPath}2.加入一个base标签, 是html语言中的标签。 表示当前页面中访问地址的基地址。你的页面中所有 没有“/”开头的地址,都是以base标签中的地址为参考地址使用base中的地址 + user/some.do 组成访问地址
base标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>
<html>
<head><title>功能rukou // /SSM_war_exploded</title><base href="<%=basePath%>"/>
</head>
转发和重定向
foeward转发:向资源1发起请求,由于资源1处理没有达到理想结果,在服务器内部,将请求转发给资源2,由资源2来处理请求,再将结果返回。
redirect重定向:向资源1发起请求,由于资源1处理没有达到理想结果,返回浏览器放问资源2能处理请求,浏览器会自动发起第二次请求访问资源2,然后返回结果。区别于转发,重定向进行了两次访问。
面试解答
1、重定向是浏览器发送请求并得到响应,以后向一个新地址发起请求,转发是服务器收到请求后,为完成请求处理而转到另外一个资源进行处理。浏览器只发起一次请求。
2、重定向请求两次,不产生共享数据,转发请求一次,共享数据
3、重定向后地址会发生变化,转发不会发生变化
4、重定向的新地址可以是任意地址,转发必须是同一个应用下的某个资源文件。
拦截器
需要在springmvc配置文件中添加配置
<!-- 声明拦截器--><mvc:interceptors>
<!-- 定义第一个拦截器--><mvc:interceptor>
<!-- 指定拦截的请求url地址任何以user开头的请求,都要拦截
--><mvc:mapping path="/student/interceptor.do"/>
<!-- <mvc:mapping path="/**"/>任意请求都要被拦截-->
<!-- 声明拦截器对象--><bean class="com.SSM.interceptor.MyInterceptor"/></mvc:interceptor></mvc:interceptors>
MyInterceptor是程序中自定义的一个拦截器对象,这个拦截器对象要实现HandlerInterceptor接口
在这个接口中实现类中,需要实现三个方法,
1、preHandle预处理方法
返回值:true:通过验证,后续执行拦截器MyInterceptor的preHandle()方法controller方法开始执行拦截器MyInterceptor的postHandle()方法拦截器MyInterceptor的afterCompletion()方法false:验证失败,请求到达拦截器就截止了只执行拦截器MyInterceptor的preHandle()方法验证通过,执行控制器方法验证失败,阶段请求,请求不能被处理
2、postHandle后处理方法:
处理器方法执行之后执行,可以对处理器方法的执行结果做二次修改
3、afterCompletion:
最后执行的方法,请求处理完成后执行的,经常做资源回收,删除对象和清理内存
/*** 拦截器类,拦截用户的请求*/
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("拦截器MyInterceptor的preHandle()方法");// 验证失败,给浏览器一个反馈//request.getRequestDispatcher("/terceptortip.jsp").forward(request,response);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("拦截器MyInterceptor的postHandle()方法");if (modelAndView != null){modelAndView.addObject("date",new Date());modelAndView.setViewName("other");}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("拦截器MyInterceptor的afterCompletion()方法");}
}
当程序中包含多个拦截器的时候,在配置文件中就需要声明多个拦截器
当对同一个请求有多个拦截器处理的时候,哪个拦截器先声明,就限制性哪个拦截器的preHandle()方法。
假如111111拦截器先声明,那么
执行流程如下
111111-拦截器的MyInterceptor的preHandle()
22222-拦截器的MyInterceptor的preHandle()
=-=执行MyController中的doSome方法=====
22222-拦截器的MyInterceptor的postHandle()
111111-拦截器的MyInterceptor的postHandle()
22222-拦截器的MyInterceptor的afterCompletion()
111111-拦截器的MyInterceptor的afterCompletion()
当第一个拦截器的preHandle()是true,第二个拦截器的preHandle()是false,
执行流程 111111-拦截器的MyInterceptor的preHandle()
22222-拦截器的MyInterceptor的preHandle()
111111-拦截器的MyInterceptor的afterCompletion()
两个都是false
111111-拦截器的MyInterceptor的preHandle()
总结
不能有总结,还没学完呢,下一篇是mybatis的学习总结,有问题请评论出来,我再改。
更多推荐
sprig MVC学习总结
发布评论