框架学习二SpringMVC
SpringMVC
Spring框架提供了构建Web应用程序的全功能MVC模块。使用Spring可插入的MVC架构,可以选择是内置的Spring Web框架还可以是Struts这样的Web框架。通过策略接口,Spring框架是高度可配置的,而且包含多种视图技术,例如JavaServer Pages(JSP)技术、Velocity、Tiles、iText和POI。Spring MVC框架并不知道使用的视图,所以不会强制使用者使用JSP技术。Spring MVC分离了控制器、模型对象、分派器以及处理程序对象的角色。
1.Web请求过程
2.SpringMVC组件
DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其他组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。
HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式
HandlerAdapter:通过扩展处理器适配器,支持更多类型的处理器,调用处理器传递参数等工作
ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel
3.MVC执行过程
先是浏览器发送请求给,DispatcherServlet去HandlerMapping找对应的请求处理器Controller(Servlet),调用Service具体请求处理方法,返回ModelAndView给DispatcherServlet,然后Dispatcher找与返回处理数据匹配的视图映射ViewResolver,将模型数据Model传给View显示
3.1Dispatcher介绍
DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责:
- 文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件解析
- 通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器,多个HandlerInterceptor拦截器)
- 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器)
- 通过ViewResolver解析逻辑视图名到具体试图实现
- 本地化解析
- 渲染具体的视图
- 如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
3.2DispatcherServlet辅助类
spring中的DispatcherServlet使用一些特殊的bean来处理request请求和渲染合适的视图
bean类型 | 说明 |
---|---|
Controller | 处理器/页面控制器,做的是MVC中C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理 |
HandlerMapping | 请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerIntercepor拦截器对象);如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器 |
HandlerAdapter | HandlerAdapter将会把处理器包装为设配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行设配,并且调处理器的handlerRequest方法进行功能处理 |
HandlerExceptionResolver处理器异常解析器 | 处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息) |
ViewResolver视图解析器 | ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图 |
LocaleResolver&LocaleContextResolver地区解析器和地区Context解析器 | 解析客户端中使用的地区和时区,用来提供不同的国际化的view视图 |
ThemeResolver | 主题解析器,解析web应用中能够使用的主题,比如提供个性化的网页布局 |
MultipartResolver | 多部件解析器,主要处理multi-part(多部件)request请求,例如:在HTML表格中处理文件上传 |
FlashMapManager | FlashMap管理器储存并检索在”input“和”output“的FlashMap中可以在request请求间(通常是通过重定向)传递属性的FlashMap |
springMVC搭建
(1)添加jar包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
(2)修改web.xml
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
1.url-pattern有5种配置模式
(1)/xxx:完全匹配/xxx
(2)/xxx/*:匹配以/xxx开头的路径,请求中必须包含xxx
(3)/*:匹配/下的所有路径,请求可以进入到action或controller,但是转发结果jsp时会再次被拦截,不能访问jsp界面
(4).xx:匹配以xx结尾的路径,所有请求必须以.xx结尾,但不会影响访问静态文件。
(5)/:默认模式,未被匹配的路径都将映射到servlet,对jpg,js,css等静态文件也将被拦截,不能访问
(3)修改spring配置文件
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"
>
<!-- 扫描controller-->
<context:component-scan base-package="com.yhp.controller"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- jsp所在的位置-->
<property name="prefix" value="/" />
<!-- jsp文件的后缀名-->
<property name="suffix" value=".jsp" />
</bean>
</beans>
(4)创建控制类
aaa@qq.com
aaa@qq.com(”请求地址“)
//加在类上:给模块添加根路径
//加在方法上:方法具体的路径
- 设置@RequestMapping method属性
@RequestMapping(method=RequestMethod.GET,value=”请求名“)
4.请求接收参数
接收参数的方式:
(1)HttpServletRequest
(2)页面传值时的key=处理请求的方法的参数名
(3)使用控件名和对象的属性名一致的方式进行接收
方法的参数名和传参的name值不同
//可以设置RequestParam绑定对应值
public String login(@RequestParam(value = "name") String username, String password){}
//可以设置默认值
public String list(@RequestParam(defaultValue = "1") Integer currentPage){}
日期处理
因为springmvc框架默认支持转换得日期格式:yyyy/MM/dd
解决日期问题方式:
- 先用String接收日期,再转换:SimpleDataFormate
- 使用工具类处理日期
工具类引包
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
//修改配置文件,导入mvc命名空间,添加驱动
<mvc:annotation-driven/>
//添加@DataTimeFormat注解
public String test1(@DateTimeFormat(pattern = "yyyy-MM-dd")Date birthday){}
注意:参数类型使用引用数据类型,基本数据类型使用包装类
5.返参
修改web.xml文件,用来支持jsp操作EL表达式
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
- HttpServletRequest
- ModelMap map,默认作用域request
- ModelAndView对象需要new,同时作为返回值类型
- Model类保存数据
注意:跳转的方式默认使用的是转发,而不是重定向
6.session存值
(1)使用HttpSession:request.getSession()
(2)使用@sessionAttributes(”key值“)//写的是ModelMap中定义的key值
注意:该注解和ModelMap结合使用,当使用ModelMap存值时,会在session中同时存储一份数据
@SessionAttributes()的小括号如果是一个值,不要加{}
例如:
@SessionAttributes(”key“)
@SessionAttributes({”key1“,”key2“})
清除注解session:SessionStatus类
status.setComplete()
7.弹窗响应
响应流(返回值必须是void)
public void delete(HttpServletResponse response) throws IOException{
response.setContextType("text/html;charset=UTF-8");
PrintWriter pw = response.getWriter();
pw.print("<script>alert('删除成功');location.href="logout.jsp"</script>")
}
注意:如果get请求乱码,tomcat8默认配置utf-8
post乱码处理
- 设置jsp页面的编码方式
- 设置一个过滤器filter,设置编码方式
<filter>
<filter-name>myfilter</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>myfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
8.转发和重定向
默认转发跳转:
@RequestMapping(test)
public String test(){
return "success";
}
重定向:
return "redirect:success.jsp" 或者:redirect:findall
注意:重定向时地址栏会发生拼接ModelMap中值的问题
9.异常处理
方法1:在web.xml响应状态码配置一个对应页面
<error-page>
<error>404</error>
<location>/404.html</location>
</error-page>
方法2:
@RequestMapping("test")
public String test(){
String a = null;
System.out.println(a.charAt(0));
return "success";
}
//配置异常结果界面
@ExceptionHandler(NullPointerException.class)
public String execptionResult(){
return "exception";
}
全局异常:@ControllerAdvice注解
使一个Controller成为全局的异常处理类,类中用@ExceptionHandler注解的方法处理所有Controller发生的异常
10.Cookie操作
@CookieValue注解可以获取请求中的cookie
public String testCookie(@CookieValue("JSESSIONID") String cookie){
System.out.println("cookie:"+cookie);
return "result";
}
11.获取请求头信息
@RequestHeader
@RequestHeader注解可以获取请求头中的数据!!
public String testHeader(@RequestHeader("User-Agent")String header)
12.RestFul风格
REST:即Representational State Transfer,(资源)表现层状态转化,是一种互联网软件架构
具体说,就是HTTP协议的四个表示操作方式的词
GET、POST、PUT、DELETE
分别代表四种基本操作:
- GET用来获取资源
- POST用来创建新资源
- PUT用来更新资源
- Delete用来删除资源
通过修改http的状态值来标记请求
注意:浏览器的form表单只支持GET和POST,不支持DELETE和PUT请求
Spring需要添加一个过滤器,可以将这些请求转换为标准的http方法,支持GET、POST、PUT、DELETE
(1)web.xml添加HiddenHttpMethodFilter配置
<filter>
<filter-name>methodtest</filter-name>
<filter-class>
org.springframework.web.filter.HiddenHttpMethodFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>methodtest</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(2)由于doFilterInternal方法只对method为post的表单进行过滤,所以先设置为post请求,设置隐藏域为真正的方法,HiddenHttpMethodFilter将把本次请求转化为标准的put请求方式,name一定要为”_method“
<form action="/testrest" method="get">
<input type="submit" value="get">
</form>
<form action="/testrest" method="post">
<input type="submit" value="post">
</form>
<form action="/testrest" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="put">
</form>
<form action="/testrest" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="delete">
</form>
(3)controller
@PathVariable获取路径参数
@RequestMapping(value = "/testrest/{var}", method = RequestMethod.GET)
public String myGet(@PathVariable(value = "var") String name){
System.out.println("get请求,name="+name);
return "getsuccess";
}
@RequestMapping(value = "/order",method = RequestMethod.POST)
@RequestMapping(value = "/order/{id}",method = RequestMethod.DELETE)
@RequestMapping(value = "/order/{id}",method = RequestMethod.PUT)
注意:如果访问put和delete请求的时候,报405:method not allowed。处理方式是将过滤器的请求地址改成/,而不是/*
13.静态资源访问
DispatcherServlet拦截资源设置成/,避免了死循环,虽然/不拦截jsp资源,但是它会拦截其他静态资源,例如html,js,css,image等等,那在使用jsp内部添加静态资源就无法成功,所以要单独处理静态资源
处理方法(1):
-
修改Spring MVC对应配置文件,添加mvc命名空间和约束
<?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:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
-
添加处理标签
<mvc:annotation-driven /> <!--注解驱动--> <mvc:resources mapping="/img/**" location="/images/" ></mvc:resources> //或者 <mvc:default-servlet-handler></mvc:default-servlet-handler>
14.Json处理
(1)添加jar包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
注意:maven引入jackson-databind会连带引入core和annotations
非maven项目需要引入这三个包
(2)实现代码:@ResponseBody注解
注意:需要在配置文件添加mvc:annotation-driven
15.SpringMVC拦截器
(1)创建拦截器类:实现HandlerInterceptor接口
preHandler()拦截器开始
postHandler()拦截器结束
afterCompletion()最后执行
(2)配置拦截器
拦截所有请求:
<mvc:interceptors>
<bean id="my" class="util.MyInterceptor"/>
</mvc:interceptors
拦截指定请求:
<mvc:interceptors>
<mvc:interceptor >
<mvc:mapping path="/请求名" />
<mvc:mapping path="/请求名" />
<bean id="my" class="util.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
springMVC拦截器使用场景
1、日志记录:记录请求信息的日志
2、权限检测,如登录检查
3、性能检测:检测方法的执行时间
springMVC拦截器和过滤器的区别和联系
(1)过滤器
依赖于servlet容器,在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次,使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
(2)拦截器
依赖于web框架,在SpringMVC中就是依赖springMVC框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理
多个过滤器与拦截器的执行顺序:
(1)过滤器的运行是依赖于Servlet容器的,跟springmvc等框架无关,并且多个过滤器的执行顺序跟xml文件中定义的先后顺序有关
(2)对于多个拦截器它们之间的执行顺序跟在springmvc的配置文件中定义的先后顺序有关
16.文件上传下载
Spring MVC为文件上传提供了直接支持,这种支持是通过即插即用的MultipartResolver实现
Spring使用Jakarta Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver
在SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下不能处理文件上传。
文件上传的步骤
(1)添加jar包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
(2)配置MultipartResolver:
<mvc:annotation-driven/>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:defaultEncoding="UTF-8"
p:maxUploadSize="5242880"
/>
(3)页面表单,提交方式必须是post
<form action="upload" method="post" enctype="multipart/form-data">
文件上传:<input type="file" name="myfile">
<input type="submit" value="上传">
</form>
(4)配置java代码(注意要创建文件夹保存上传之后的文件)
@RequestMapping("upload")
public String upload(MultipartFile myfile, HttpServletRequest request){
//处理文件上传内容
//1.将上传的文件夹转换成服务器路径
String realPath = request.getRealPath("/uploadimg");
System.out.println(realPath);
//2.得到上传的文件名
String filename = myfile.getOriginalFilename();
request.setAttribute("filename",filename);
//3.上传
try {
myfile.transferTo(new File(realPath+"/"+filename));
} catch (IOException e) {
e.printStackTrace();
}
return "uploadsuccess";
}
方法名称 | 方法解释 |
---|---|
byte[] getBytes() | 获取文件数据 |
String getContentType() | 获取文件MIMETYPE类型,如image/jpeg,text/plain等 |
InputStream getInputStream() | 获取文件输出流 |
String getName() | 获取表单中文件组件的名称name值 |
String getOriginalFilename() | 获取文件上传的原名 |
long getSize() | 获取文件的字节大小,单位为byte |
boolean isEmpty() | 是否有长传的文件 |
void transferTo(File dest) | 可以将上传的文件保存到指定的文件中 |
文件下载步骤
(1)添加jar包
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
(2)配置处理请求方法
@RequestMapping("download")
public ResponseEntity<byte[]> down(String filename, HttpServletRequest request) throws Exception{
//1.转换服务器地址
String realPath = request.getRealPath("/uploadimg");
//2.得到要下载的文件路径
String filePath = realPath+"/"+filename;
//3.设置响应的头信息
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//4.给用户弹窗的方式进行下载
//attachment用来表示以附件的形式响应给客户端
httpHeaders.setContentDispositionFormData("attachment", URLEncoder.encode(filename,"UTF-8"));
//5.创建文件
File file = new File(filePath);
//6.将文件进行返回
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),httpHeaders, HttpStatus.CREATED);
return responseEntity;
}
上一篇: springMVC框架学习-2