欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

框架学习二SpringMVC

程序员文章站 2022-06-02 21:21:30
...

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请求过程

框架学习二SpringMVC

2.SpringMVC组件

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其他组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式

HandlerAdapter:通过扩展处理器适配器,支持更多类型的处理器,调用处理器传递参数等工作

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel

3.MVC执行过程

先是浏览器发送请求给,DispatcherServlet去HandlerMapping找对应的请求处理器Controller(Servlet),调用Service具体请求处理方法,返回ModelAndView给DispatcherServlet,然后Dispatcher找与返回处理数据匹配的视图映射ViewResolver,将模型数据Model传给View显示

框架学习二SpringMVC

3.1Dispatcher介绍

DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责:

  1. 文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件解析
  2. 通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器,多个HandlerInterceptor拦截器)
  3. 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器)
  4. 通过ViewResolver解析逻辑视图名到具体试图实现
  5. 本地化解析
  6. 渲染具体的视图
  7. 如果执行过程中遇到异常将交给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

解决日期问题方式:

  1. 先用String接收日期,再转换:SimpleDataFormate
  2. 使用工具类处理日期

工具类引包

<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">
  1. HttpServletRequest
  2. ModelMap map,默认作用域request
  3. ModelAndView对象需要new,同时作为返回值类型
  4. 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乱码处理

  1. 设置jsp页面的编码方式
  2. 设置一个过滤器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

分别代表四种基本操作:

  1. GET用来获取资源
  2. POST用来创建新资源
  3. PUT用来更新资源
  4. 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):

  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
    ">
    
  2. 添加处理标签

    <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的配置文件中定义的先后顺序有关

框架学习二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;
    }