SpringMVC集合

目录

  • SpringMVC
      • SpringMVC简介
        • 1、什么是MVC
        • 2、什么是SpringMVC
        • 3、SpringMVC的特点
      • SpringMVC入门
        • (1)引入依赖
        • (2)配置web.xml
        • (3)创建请求控制器
        • (4)创建SpringMVC的配置文件
        • (5)创建index.html
        • (6)编辑control层
        • (7)测试
        • (8)补充:将配置文件设置到resources下
          • classpath是什么:
        • (9)总结
      • @RequestMapping注解
        • 1、@RequestMapping注解的功能
        • 2、@RequestMapping注解的位置
        • 3、@RequestMapping注解的value属性
        • 4、@RequestMapping注解的method属性
        • 5、@RequestMapping注解的params属性
        • 6、@RequestMapping注解的headers属性
        • 7、SpringMVC支持ant风格的路径
          • ***但上面所有的ant符号都不能写问号"?"***
        • 8、SpringMVC支持路径中的占位符(重点)
      • SpringMVC获取请求参数
        • 1、通过servletAPI获取
        • 2、通过控制器方法的形参获取
        • 3、通过pojo实体类类型的形参获取
        • 4、解决获取请求参数的中文乱码问题
      • 域对象共享数据
        • 1、使用servletAPI向request域对象共享数据
        • 2、使用ModelAndView向request域对象共享数据
        • 3、使用Model、ModelMap、Map向request域对象共享数据
        • 4、向session域对象共享数据
        • 4、向application域对象共享数据
      • springMVC视图
        • 1、ThymeleafView
        • 2、InternalResouceView(转发视图)
        • 3、RedirectView(重定向视图)
        • 4、视图控制器view-controller
      • RESTful
        • 1、RESTful简介
        • 2、RESTful的实现
        • 3、查询功能实现
        • 4、使用HiddenHttpMethodFilter实现put、delete的改删功能
        • 5、处理静态资源无法找到(CSS..)
        • 6、RESTful实例(员工增删改查)
      • springMVC处理ajax请求
        • 1、@RequestBody
        • 2、@ResponseBody
        • 3、@RestController注解
      • 文件上传和下载
        • 1、下载
        • 2、上传
      • 拦截器
        • 多个拦截器执行顺序
      • 异常处理
        • xml配置处理异常
        • 注解配置处理异常
      • 注解配置SpringMVC

SpringMVC

SpringMVC简介

1、什么是MVC

MVC是一种软件架构的思想,将软件按照模型、视图、控制器划分

M:Model,模型层,指工程中的JavaBean,作用是处理数据

Javabean分为两类:

  • 实体类bean:专门储存业务数据的,如uesr
  • 业务处理bean:指service或dao对象,专门用于处理业务逻辑和数据访问

V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据

C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器

MVC工作流程:

用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器

2、什么是SpringMVC

SpringMVC是Spring的一个后续产品,是spring的一个子项目

SpringMVC是spring为表述层开发(servlet)提供的一个框架,SpringMVC就是封装了servlet

三层架构分为表述层(表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet

3、SpringMVC的特点

(1)Spring家族原生产品,与IoC容器对接

(2)基于原生的servlet,通过封装的servlet管理控制器DispatcherServlet,对请求和响应进行统一处理

(3)表述层各个细分领域需要解决的问题全方位覆盖,提供全面解决方案

(4)提高开发效率

(5)内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应的组件即可

SpringMVC入门

建议用tomcat10版本以下去测试

(1)引入依赖


<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-webmvcartifactId>
    <version>5.3.1version>
dependency>


<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>javax.servlet-apiartifactId>
    <version>3.1.0version>
    <scope>providedscope>
dependency>
  
  
<dependency>
    <groupId>ch.qos.logbackgroupId>
    <artifactId>logback-classicartifactId>
    <version>1.4.5version>
    <scope>testscope>
dependency>


<dependency>
    <groupId>org.thymeleafgroupId>
    <artifactId>thymeleaf-spring5artifactId>
    <version>3.0.15.RELEASEversion>
dependency>

(2)配置web.xml

注意:

SpringMVC的配置文件默认的位置和名称:
位置:WEB-INF下
名称:-servlet.xml,以下配置的文件名称为SpringMVC-servlet.xml

url-pattern中/和/*的区别:

  • /:匹配浏览器向服务器发送的所有请求(不包括.jsp)
  • /*:匹配浏览器向服务器发送的所有请求(包括.jsp)

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
  
  <servlet>
  	<servlet-name>SpringMVCservlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
  servlet>
  <servlet-mapping>
  	<servlet-name>SpringMVCservlet-name>
  	<url-pattern>/url-pattern>
  servlet-mapping>
web-app>

(3)创建请求控制器

由于前端控制器对浏览器发送的请求进行了统一的处理,但是具体的请求有不同的处理过程,因此需要创建处理具体请求的类,即请求控制器

请求控制器中每一个请求处理的方法成为控制器方法

因为springMVC的控制器由一个pojo(普通的Java类)担任,因此需要提通过@Controller注解将其标识为一个控制层组件

@Controller
public class HelloController {

}

(4)创建SpringMVC的配置文件

当前文件名为:SpringMVC-servlet.xml

 
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	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-4.1.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/util
     http://www.springframework.org/schema/util/spring-util-4.1.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">

	 <context:component-scan base-package="controller">context:component-scan>
	 
	 
	<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
    	<property name="order" value="1"/>
    	<property name="characterEncoding" value="UTF-8"/>
    	<property name="templateEngine">
        	<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
            	<property name="templateResolver">
                	<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">   
                    	
                    	<property name="prefix" value="/WEB-INF/templates/"/>    
                    	
                    	<property name="suffix" value=".html"/>
                    	<property name="templateMode" value="HTML5"/>
                    	<property name="characterEncoding" value="UTF-8" />
                	bean>
            	property>
        	bean>
    	property>
	bean>	

beans>

(5)创建index.html

在/WEB-INF/templates/下创建index.html

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
<h2>Hello World!h2>
<a th:href="@{/hello }">测试SpringMVCa>
<a href="/hello">测试绝对路径a>
body>
html>

以及success.html

DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
<h1>successh1>
body>
html>

(6)编辑control层

@Controller
public class HelloController {
	@RequestMapping("/")
	public String protal() {
		//将index.html
		return "index";
	}
	
	@RequestMapping("/hello")
	public String hello() {
		return "success";
	}
}

(7)测试

开启tomcat9测试SpringMVC集合_第1张图片

(8)补充:将配置文件设置到resources下

在web.xml中修改servlet配置

  <servlet>
  	<servlet-name>SpringMVCservlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
      
  	<init-param>
  		<param-name>contextConfigLocationparam-name>
  		<param-value>classpath:springmvc.xmlparam-value>
  	init-param>
      
      <load-on-startup>1load-on-startup>
  servlet>
  <servlet-mapping>
  	<servlet-name>SpringMVCservlet-name>
  	<url-pattern>/url-pattern>
  servlet-mapping>
web-app>
classpath是什么:

classpath直译过来是类路径,是Java环境配置中要设置的一个环境变量,就是.class文件的路径,表示JVM从哪里去寻找要运行的class文件,classpath = D:\java表示执行java命令时去D:\java目录中去找需要被执行的class文件并运行。

一般一个web工程中java、resources下的路径都是类路径。src/main/下面的javaresources文件夹都被(编译)打包到了生产包的WEB-INF/classes/目录下;而原来WEB-INF下面的views和web.xml则仍然还是在WEB-INF下面。同时由maven引入的依赖都被放入到了WEB-INF/lib/下面。最后,编译后的class文件和资源文件都放在了classes目录下。

(9)总结

浏览器发送请求,若请求地址符合前端控制器的url—pattern,该请求就会被前端控制器DispatcherServlet处理。前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中@RequestMapping注解的value属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法。处理请求的方法需要返回一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径,通过Thymeleaf对视图进行渲染,最终转发到视图所对应页面

@RequestMapping注解

1、@RequestMapping注解的功能

从注解名称上可以看到,@RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。

springMVC接收到指定的请求,就会去找到在映射关系中对应的控制器方法来处理这个请求。

2、@RequestMapping注解的位置

@RequestMapping注解标识一个类:设置映射请求的请求路径的初始信息

@RequestMapping注解标识一个方法:设置映射请求路径的具体信息

@Controller
@RequestMapping("/test")
public class HelloController {
	//此时的hello方法的url路径为../test/hello,而不是../hello
	@RequestMapping("/hello")
	public String hello() {
		return "success";
	}
}

3、@RequestMapping注解的value属性

作用:通过请求的请求路径匹配请求

value属性是数组类型,即当前浏览器所发送请求的请求路径匹配value属性中的任何一个值,则当前请求就会被注解所标识的方法进行处理

@AliasFor("path")
	String[] value() default {};
@RequestMapping({"/hello","/abc"})
	public String hello() {
		return "success";
	}

SpringMVC集合_第2张图片

4、@RequestMapping注解的method属性

作用:通过请求的请求方式匹配请求

method属性是@RequestMethod 类型的数组,即当前浏览器所发送请求的请求方式匹配method属性中的任何一个值,则当前请求就会被注解所标识的方法进行处理

若浏览器所发送的请求的请求路径和@RequestMapping注解的value属性所匹配,但与method属性不匹配,则此时页面会报错:

405 - Request method ‘GET’ not supported

RequestMethod[] method() default {};
public enum RequestMethod {

	GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

}
@RequestMapping(value = {"/hello","/abc"},method = RequestMethod.POST)
	public String hello() {
		return "success";
	}
@RequestMapping(value = {"/hello","/abc"},method = {RequestMethod.POST,RequestMethod.GET})

在@RequestMapping注解的基础上,结合请求方式的一些派生注解:

@GetMapping,@PostMapping,@DeleteMapping,@PutMapping

5、@RequestMapping注解的params属性

作用:通过请求的请求参数匹配请求,即浏览器发送的请求的请求参数必须满足pamas属性

params 可以使用四种表达式:

“param”:表示当前所匹配请求的请求参数中必须携带param参数

“!param”:表示当前所匹配请求的请求参数中一定不能携带param参数

“param=value”:表示当前所匹配请求的请求参数中必须携带param参数且值必须是value

“param!=value”:表示当前所匹配请求的请求参数中可以不携带param参数,若携带值一定不能是value

String[] params() default {};
@RequestMapping(value = {"/hello","/abc"},
				    method = {RequestMethod.POST,RequestMethod.GET},
				//	params = {"username"}
               	//	params = {"username","!password"}
               		params = {"username","!password","age=10","admin!=18"})
	public String hello() {
		return "success";
	}

若浏览器所发送的请求的请求路径和@RequestMapping注解value属性匹配,但是请求参数不匹配,则报错:

400 - Parameter conditions “username” not met for actual request parameters:

400 - Parameter conditions “username, !password” not met for actual request parameters: username={12}, password={}

SpringMVC集合_第3张图片
SpringMVC集合_第4张图片
SpringMVC集合_第5张图片

6、@RequestMapping注解的headers属性

作用:@RequestMapping注解的headers属性通过请求的请求头信息匹配请求映射

@RequestMapping注解的headers属性是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系

“header”:表示当前所匹配请求的请求头中必须携带header参数

“!header”:表示当前所匹配请求的请求头中一定不能携带header参数

“header=value”:表示当前所匹配请求的请求头中必须携带header参数且值必须是value

“header!=value”:表示当前所匹配请求的请求头中可以不携带header参数,若携带值一定不能是value

String[] headers() default {};

跟上面的params是差不多一样的

7、SpringMVC支持ant风格的路径

?:表示任意的单个字符

*:表示任意的0个或多个字符

**:表示任意层数的任意目录

注意:在使用 ** 时,只能使用 /** /XXX 的方式, ** 只能写在双斜线中,前后不能有任何的其它字符

@RequestMapping("/a?a/ant")
	public String testAnt() {
		return "success";
	}

SpringMVC集合_第6张图片

但上面所有的ant符号都不能写问号"?"

SpringMVC集合_第7张图片

@RequestMapping("/**/ant")
	public String testAnt() {
		return "success";
	}

SpringMVC集合_第8张图片

8、SpringMVC支持路径中的占位符(重点)

原始方式:/XXX?id=1

rest方式:/XXX/1

SpringMVC路径中的占位符常用RESTful(后面有讲到)风格中,当请求路径中将某些数据通过路径的方式传输到服务器中,就可以在相应的@RequestMapping注解的value属性中占位符{XXX}表示传输的数据,在通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参

<a th:href="@{/test/rest/1/admin}">SpringMVC支持路径中的占位符a>
@RequestMapping("/test/rest/{id}/{username}")
	public String testRest(@PathVariable("id") Integer id,@PathVariable("username") String uesrname) {
		System.out.println("id:"+id+";username:"+uesrname);
		return "success";
	}

SpringMVC获取请求参数

1、通过servletAPI获取

将HttpServletRequest作为控制器方法的形参,此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象

@RequestMapping("/param/servletAPI")
	public String getAPI(HttpServletRequest request) {
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		System.out.println(username + password);
		return "success";
	}

2、通过控制器方法的形参获取

@RequestParam:将请求参数和控制器方法的形参绑定

value/name:设置和形参绑定的请求参数的名字

required:设置是否必须传输value所对应的请求参数

默认值为true,表示value所对应的请求参数必须传输,否则页面报错

@RequestHeader:将请求头信息和控制器方法的形参绑定

@CookieValue:将cookie数据和控制器方法的形参绑定

@RequestMapping("/param")
	public String getcontrolAPI(@RequestParam(name = "userName",required = false,defaultValue = "hai") String username,
							String password,
                            @RequestHeader("referer") String referer,
                            @CookieValue("JSSESSIONID") String jssessioid) {
		System.out.println(username + password);
		return "success";
	}

3、通过pojo实体类类型的形参获取

需要在控制器方法的形参位置设置实体类类型的形参,要保证实体类中的属性名和请求参数的名字一致

可以通过实体类类型的形参获取请求参数

4、解决获取请求参数的中文乱码问题

spring自带过滤器,通过再web.xml下设置过滤器就可以完成


  <filter>
  	<filter-name>CharacterEncodingFilterfilter-name>
  	<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
  	
  	<init-param>
  		<param-name>encodingparam-name>
  		<param-value>UTF-8param-value>
  	init-param>
  	
  	<init-param>
  		<param-name>forceEncodingparam-name>
  		<param-value>trueparam-value>
  	init-param>
  filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilterfilter-name>
  	<url-pattern>/*url-pattern>
  filter-mapping>

注意:

springmvc的自带过滤器一定要配置在其它过滤器前,否则无效

域对象共享数据

1、使用servletAPI向request域对象共享数据

@RequestMapping("/test/api")
	public String api(HttpServletRequest request) {
		request.setAttribute("test", "hello,api");
		return "success";
	}
<p th:text="${test}">

2、使用ModelAndView向request域对象共享数据

@RequestMapping("/test/view")
	public ModelAndView view() {
		/**
		 * ModelAndView包含model和view的功能
		 * model:向请求域中共享数据
		 * view:设置逻辑视图实现页面跳转
		 */
		ModelAndView modelAndView = new ModelAndView();
		//向请求域中共享数据
		modelAndView.addObject("test", "hello,modelandview");
		modelAndView.setViewName("success");
		return modelAndView;
	}

3、使用Model、ModelMap、Map向request域对象共享数据

@RequestMapping("/test/model")
	public String model(Model model) {
		model.addAttribute("test", "hello,model");
		return "success";
	}
	@RequestMapping("/test/modelMap")
	public String modelMap(ModelMap modelMap) {
		modelMap.addAttribute("test", "hello,modelMap");
		return "success";
	}
	@RequestMapping("/test/map")
	public String map(Map<String,Object> map) {
		map.put("test", "hello,model");
		return "success";
	}

这三个方法都是一个类下所继承或接口

4、向session域对象共享数据

@RequestMapping("/test/session")
	public String session(HttpSession session) {
		session.setAttribute("test", "hello,sesssion");
		return "success";
	}
<p th:text="${session.test}">

4、向application域对象共享数据

@RequestMapping("/test/application")
	public String application(HttpSession session) {
		session.getServletContext().setAttribute("test", "hello,application");
		return "success";
	}
<p th:text="${application.test}">

注意:session和浏览器有关,在一次会话中只要浏览器不关闭就存在session;application是在整个应用域上,和服务器有关。

springMVC视图

springmvc中的视图是view接口,视图的作用是渲染数据,将模型model中的数据展示给用户

springmvc视图的种类很多,默认有转发视图和重定向视图

当工程引入jstl的依赖,转发视图会自动转换为jistlView

若使用的视图技术为Thymeleaf,在springmvc的配置文件中配置了Thymeleaf的视图解析器

1、ThymeleafView

当控制器方法中所设置的视图名没有任何前缀时,此时的视图名称会被springmvc配置文件中所配置的视图解析器解析

@RequestMapping("/**/ant")
	public String testAnt() {
		return "success";
	}

2、InternalResouceView(转发视图)

@RequestMapping("/**/anti")
	public String testAnt() {
		return "forward:/test/view";
	}

Thymeleaf和转发InternalResouce都可以实现转发,但如果用InternalResouce无法使Thymeleaf渲染页面,无法解析th语法,只是一个简单的a转发

3、RedirectView(重定向视图)

@RequestMapping("/**/anto")
	public String testAnt() {
		return "redirect:/test/view";
	}

4、视图控制器view-controller

当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示

    
	<mvc:annotation-driven>mvc:annotation-driven>	
	
	<mvc:view-controller path="/" view-name="index">mvc:view-controller>

相当于:

	@RequestMapping("/")
	public String protal() {
		//将index.html
		return "index";
	}

注意:

视图控制器:为当前的请求直接设置视图名称实现页面跳转,
若设置视图控制器,则只有视图控制器所设置的请求会被处理,其它的请求将全部404

要在配置文件中设置

RESTful

1、RESTful简介

REST:表现层资源状态转移。

相当于传表单一样,用rest方法来传输客户端的数据给后端

2、RESTful的实现

在http协议中,有四个表示操作方式的动词:GET、POSY、PUT、DELETE.

GET用来获取资源、POST用来新建资源、PUT用来更新资源、DELETE用来删除资源

http方法 资源操作 幂等 安全
GET SELECT(查)
POST INSERT(增)
PUT UPDATE(改)
DELETE DELETE(删)

幂等性:对同一REST接口的多次访问,得到的资源状态是相同的。

安全性:对该REST接口访问,不会使服务器端资源的状态发生改变。

3、查询功能实现

@RequestMapping(value = "/user/{id}" ,method=RequestMethod.GET)
	public String getUserId(@PathVariable("id") Integer id) {
		
		return "success";
	}

同上@RequestMapping注解中的SpringMVC支持路径中的占位符(重点)讲到的一样

4、使用HiddenHttpMethodFilter实现put、delete的改删功能

因为客户端的请求方法只有GET、POST,不能直接用PUT、DELETE,所以需要一个过滤器来实现

<filter>
  	<filter-name>HiddenHttpMethodFilterfilter-name>
  	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
  	<filter-name>HiddenHttpMethodFilterfilter-name>
  	<url-pattern>/*url-pattern>
filter-mapping>
<form th:action="@{/user}" method="post">
	<input type="hidden" name="_method" value="put">
	<input type="submit" value="修改用户信息">
form>
@RequestMapping(value = "/user" ,method=RequestMethod.PUT)
	public String updateUserId() {		
		return "success";
	}

delete方法和上面的put方法一样,用hidden来实现。

请求http方法:get --> /uesr/1 post --> /user put --> /user delete --> /user/1

5、处理静态资源无法找到(CSS…)

<link rel="stylesheet" href="/xxx/xxx.css">

在前端报错找不到xxx/xxx.css,原因是

	当前工程的web.xml配置的前端控制器DispacherServlet的url-pattern是/
	 此时,tomcat下的web.xml会先按照工程中web.xml下的配置进行,所以tomcat下的web.xml中的DefaultServlet不会去处理servlet  。浏览器发送到请求会优先被DispacherServlet进行处理,但是DispacherServlet无法处理静态资源。

解决方法是:在web.xml下配置

​ 若配置了,此时浏览器发送的请求都会被DefaultServlet处理
​ 若配置了
​ 浏览器发送到请求会先被DispacherServlet处理,无法处理的交给DefaultServlet处理

	
	<mvc:default-servlet-handler/>
	
	<mvc:annotation-driven>mvc:annotation-driven>	

6、RESTful实例(员工增删改查)

pojo

package pojo;

public class Employee {
	private Integer id;
	private String name;
	private String sex;
	public Employee(Integer id, String name, String sex) {
		super();
		this.id = id;
		this.name = name;
		this.sex = sex;
	}
	public Employee() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", sex=" + sex + "]";
	}
	
}

dao

package dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Repository;

import pojo.Employee;
@Repository
public class EmployeesImpl implements Employees {
	private static Map<Integer, Employee> employees;
	static {
		employees = new HashMap<Integer, Employee>();
		employees.put(1001, new Employee(1001,"小海","男"));
		employees.put(1002, new Employee(1002,"小王","男"));
		employees.put(1003, new Employee(1003,"小陈","女"));
	}
	private static int initid = 1004;
	@Override
	public int save(Employee employee) {
		// TODO Auto-generated method stub
		if (employee.getId() == null) {
			employee.setId(initid++);
		}
		employees.put(employee.getId(), employee);
		return 1;
	}

	@Override
	public Employee getbyid(Integer id) {
		// TODO Auto-generated method stub
		return employees.get(id);
	}

	@Override
	public int deletebyid(Integer id) {
		// TODO Auto-generated method stub
		employees.remove(id);
		return -1;
	}

	@Override
	public Collection<Employee> allEmployee() {
		// TODO Auto-generated method stub
		return employees.values();
	}
	

}

springmvc.xml(配置文件)

 
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/util
     http://www.springframework.org/schema/util/spring-util-4.1.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/mvc 
     http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

	 <context:component-scan base-package="controller,dao,pojo">context:component-scan>
	 
	 
	<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
    	<property name="order" value="1"/>
    	<property name="characterEncoding" value="UTF-8"/>
    	<property name="templateEngine">
        	<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
            	<property name="templateResolver">
                	<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">   
                    	
                    	<property name="prefix" value="/WEB-INF/templates/"/>    
                    	
                    	<property name="suffix" value=".html"/>
                    	<property name="templateMode" value="HTML5"/>
                    	<property name="characterEncoding" value="UTF-8" />
                	bean>
            	property>
        	bean>
    	property>
	bean>
	
	
	<mvc:default-servlet-handler/>
	
	<mvc:annotation-driven>mvc:annotation-driven>	
	
	<mvc:view-controller path="/" view-name="index">mvc:view-controller>
	<mvc:view-controller path="/to/add" view-name="add">mvc:view-controller>
beans>

web.xml


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
  
   
  <filter>
  	<filter-name>CharacterEncodingFilterfilter-name>
  	<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
  	
  	<init-param>
  		<param-name>encodingparam-name>
  		<param-value>UTF-8param-value>
  	init-param>
  	
  	<init-param>
  		<param-name>forceEncodingparam-name>
  		<param-value>trueparam-value>
  	init-param>
  filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilterfilter-name>
  	<url-pattern>/*url-pattern>
  filter-mapping>
  
  <filter>
  	<filter-name>HiddenHttpMethodFilterfilter-name>
  	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
  filter>
  <filter-mapping>
  	<filter-name>HiddenHttpMethodFilterfilter-name>
  	<url-pattern>/*url-pattern>
  filter-mapping>
    
  <servlet>
  	<servlet-name>SpringMVCservlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
  	<init-param>
  		<param-name>contextConfigLocationparam-name>
  		<param-value>classpath:springmvc.xmlparam-value>
  	init-param>
  	 
  	<load-on-startup>1load-on-startup>
  servlet>
  <servlet-mapping>
  	<servlet-name>SpringMVCservlet-name>
  	<url-pattern>/url-pattern>
  servlet-mapping>
web-app>

controller

@Autowired
	private EmployeesImpl employeesImpl;
//显示所有员工
	@GetMapping("/employee")
	public ModelAndView getallemployee(ModelAndView modelAndView) {
		Collection<Employee> allEmployee = employeesImpl.allEmployee();
		modelAndView.addObject("allEmployee",allEmployee);
		modelAndView.setViewName("all");
		return modelAndView;
	}
//更新
	@GetMapping("/employee/{id}")
	public String getupdate(@PathVariable("id") Integer id,Model model) {
		Employee employee = employeesImpl.getbyid(id);
		model.addAttribute("employee", employee);
		return "update";
	}
	@PutMapping("/employee")
	public String update(Employee employee) {
		employeesImpl.save(employee);
		return "redirect:/employee";
	}
//增加	
	@PostMapping("/employee")
	public String add(Employee employee) {
		employeesImpl.save(employee);
		return "redirect:/employee";
	}
//删除
	@DeleteMapping("/employee/{id}")
	public String getdelete(@PathVariable("id") Integer id) {
		employeesImpl.deletebyid(id);
		return "redirect:/employee";
	}

index.html

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
<a th:href="@{/employee}">查询所有员工信息a>
body>
html>

all.html

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
<div id="app">
		<table>
			<tr>
				<th>idth>
				<th>nameth>
				<th>sexth>
				<th>options(<a th:href="@{/to/add}">adda>)th>
			tr>
			<tr th:each="employee : ${allEmployee}">
				<td><p th:text=${employee.id}>td>
				<td><p th:text=${employee.name}>td>
				<td><p th:text=${employee.sex}>td>
				<td>
				<a th:href="@{'/employee/'+${employee.id}}">updatea>
				<a @click="getfrom()" th:href="@{'/employee/'+${employee.id}}">deletea>
				
				td>
			tr>
			
		table>
			<form method="post">
			<input type="hidden" name="_method" value="delete">
		form>
div>
body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
<script type="text/javascript">
    
/* function getfrom(){
	var form = document.getElementsByTagName("form")[0];
    form.action = event.target.href;
    form.submit();
    event.preventDefault();
} */


	var vue = new Vue({
		el:"#app",
		methods:{
			getfrom(){
				var form = document.getElementsByTagName("form")[0];
			    form.action = event.target.href;
			    form.submit();
			    event.preventDefault();
			}
		}
	})
script>
html>

注意:< form method=“post”>没有action会自动提交,通过js来实现改变删除方法的请求方法

add.html

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
	<form th:action="@{/employee}" method="post">
		<input type="hidden" name="id">
		性名:<input type="text" name="name"><br>
		性别:<input type="radio" name="sex" value="" ><br>
		<input type="radio" name="sex" value="" ><br>
		<input type="submit" value="提交">
	form>
body>
html>

update.html

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
	<form th:action="@{/employee}" method="post">
		<input type="hidden" name="_method" value="put">
		<input type="hidden" name="id" th:value="${employee.id}">
		性名:<input type="text" name="name" th:value="${employee.name}"><br>
		性别:<input type="radio" name="sex" value="" ><br>
		<input type="radio" name="sex" value="" ><br>
		<input type="submit" value="提交">
	form>
body>
html>

springMVC处理ajax请求

1、@RequestBody

将请求体中的内容和控制器方法的形参进行绑定

使用@RequestBody注解json格式的请求参数转换为Java对象

使用条件:

  • 导入Jackson的依赖

    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.9.0version>
    dependency>
    
  • 在springmvc的配置文件中设置

  • 在处理请求的控制器方法的形参位置,直接设置json格式的请求参数要转换的Java类型的形参,使用@RequestBody标识即可

<div id="app">
	<a @click="testbody()" href="#">@RequestBody处理json请求参数a>
div>
body>
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
<script type="text/javascript">
	var vue = new Vue({
		el:"#app",
		methods:{
			testbody(){
				axios.post(
					"/springMVC/test/ajax/RequestBody",
					{id:1000,name:"小丁",sex:"男"}
				).then(response=>{
					console.log(response.data);
				});
			}	
		}
	});
	
script>
@RequestMapping("/test/ajax/RequestBody")
	public void testajax(@RequestBody Employee employee,HttpServletResponse response) throws IOException {
		System.out.println(employee);
		response.getWriter().write("hello,ajax");
	}

2、@ResponseBody

使用@ResponseBody注解响应浏览器json格式的数据

使用@ResponseBody注解java对象、map、list集合的请求参数转换为json格式

使用条件:

  • 导入Jackson的依赖

    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.9.0version>
    dependency>
    
  • 在springmvc的配置文件中设置

  • 将需要转换的json字符串的Java对象直接作为控制器方法的返回值,使用@ResponseBody注解标识控制器方法就可以将Java对象直接转换为json字符串,并响应到浏览器

注意:

常用的Java对象转换为json的结果:

实体类 --> json对象

map --> json对象

list --> json集合

testresponsebody(){
				axios.post(
						"/springMVC/test/ajax/responsebody"
					).then(response=>{
						console.log(response.data);
					});
			}
@RequestMapping("/test/ajax/responsebody")
	@ResponseBody
	public Employee testajax(){
		Employee employee = new Employee(1006,"小王","男");
		return employee;
	}

3、@RestController注解

@RestController注解是springmvc提供的一个复合注解,表示在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解

文件上传和下载

1、下载

@RequestMapping("/test/down")
	public ResponseEntity<byte[]> downfile(HttpSession session) throws IOException {
		ServletContext context = session.getServletContext();
		//文件名
		String filename = "1.jpg";
		File file = new File(filename);
		//真实文件路径
		String realPath = context.getRealPath("img") + file.separator +filename;
		FileInputStream iStream = new FileInputStream(realPath);
		//iStream.available()获取输入流所对应的文件字节数
		byte[] bytes = new byte[iStream.available()];
		//将流读到字节数组中
		iStream.read(bytes);
		MultiValueMap<String, String> headers = new HttpHeaders();
		headers.add("Content-disposition","attachment;filename="+filename);
		//状态码
		HttpStatus status = HttpStatus.OK;
		ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,headers,status);
		iStream.close();
		return responseEntity;
	}

注意:ResponseEntity的使用和理解

Spring ResponseEntity 详解:从原理到实践 - 知乎 (zhihu.com)

2、上传

使用spring封装的文件上传对象,通过此对象可以获取文件相关信息

文件上传要求from表单的请求方式必须是POST,并且添加属性enctype=“multipart/form-data”

<form th:action="@{/test/up}" method="post" enctype="multipart/form-data">
文件:<input type="file" name="photo"><br>
<input type="submit" value="提交">
form>

使用springmvc上传文件步骤:

  • 添加依赖

    
    <dependency>
        <groupId>commons-fileuploadgroupId>
        <artifactId>commons-fileuploadartifactId>
        <version>1.5version>
    dependency>
    
  • 在springmvc的配置文件中配置

     
    	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">bean>
    
  • 控制器方法

    @RequestMapping("/test/up")
    	public String upfile(MultipartFile photo,HttpSession session) throws IllegalStateException, IOException {
            //获取上下文
    		ServletContext context = session.getServletContext();
            //获取文件的文件名
    		String filename = photo.getOriginalFilename();
            /**
            *解决文件名重复的问题
            *filename.lastIndexOf(".")标识文件名的最后一个.的位置
            *filename.substring(filename.lastIndexOf("."))表示取到文件名的后缀名
            *如文件名:1.png ,则hzname = .png
            **/
    		String hzname = filename.substring(filename.lastIndexOf("."));
            //使用uuid
    		String uuid = UUID.randomUUID().toString();
            //用时间戳来重命名文件
    		filename = uuid + hzname;
    		String path = context.getRealPath("photo");
    		File file = new File(path);
    		if (!file.exists()) {
                //如果文件路径不存在,则创建文件
    			file.mkdir();
    		}
    		String realpath = path + file.separator + filename;
            //利用MultipartFile获取文件的字节数据
    		photo.transferTo(new File(realpath));
    		return "success";
    	}
    

拦截器

SpringMVC中的拦截器用于拦截控制器方法的执行(在DispatcherServlet部署前配置)

SpringMVC中的拦截器需要实现HandlerInterceptor

拦截器需要在springmvc配置文件中配置:

	<mvc:interceptors>
		
		
		
		<mvc:interceptor>
            
			<mvc:mapping path="/**"/>
			<ref bean="firstInterceptor"/>
		mvc:interceptor>
	mvc:interceptors>

注意:

配置ref 时需要FirstInterceptor类上加入@Component注解并扫描,让springmvcIOC去管理

类名的小驼峰命名是bean默认的id名

创建拦截类:

package interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class FirstInterceptor implements HandlerInterceptor{
    //preHandle控制器方法执行前执行
	//preHandle默认传参为true,如果为false则postHandle、afterCompletion不执行
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle");
		return HandlerInterceptor.super.preHandle(request, response, handler);
	}
	//postHandle控制器方法执行后执行
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle");
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}
	//afterCompletion渲染完视图后执行
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion");
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}
	
}

多个拦截器执行顺序

多个拦截器执行顺序跟springmvc配置文件下的配置顺序有关

<mvc:interceptors>
		<ref bean="firstInterceptor">ref>
		<ref bean="secondInterceptor">ref>
	mvc:interceptors>

SpringMVC集合_第9张图片

输出顺序:

先执行firstInterceptor的preHandle,在执行secondInterceptor的preHandle,之后的postHandle、afterCompletion两个方法顺序相反。

异常处理

xml配置处理异常

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
        	
            <prop key="java.lang.ArithmeticException">errorprop>
        props>
    property>
    
    <property name="exceptionAttribute" value="ex">property>
bean>

注解配置处理异常

@ControllerAdvice
public class ExceptionController {
	//异常处理,设置要处理的异常信息
    //ArithmeticException.class 数学运算异常
	@ExceptionHandler(ArithmeticException.class)
    //Throwable ex 异常的形参
	public String exption(Throwable ex,Model model) {
		model.addAttribute("ex", ex);
		return "error";
	}
}

注解配置SpringMVC

在servlet3.0环境下,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置servlet容器(tomcat)。

spring提供了这个接口的实现,名为SpringServletContainerInitializer

1、配置weInit

public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer{
	//代替spring配置文件
	@Override
	protected Class<?>[] getRootConfigClasses() {
		// TODO Auto-generated method stub
		return new Class[] {SpringConfig.class};
	}
	//代替springMVC配置文件
	@Override
	protected Class<?>[] getServletConfigClasses() {
		// TODO Auto-generated method stub
		return new Class[] {WebConfig.class};
	}
	//设置springMVC的前端控制器的DispatcherServlet的url-pattern
	@Override
	protected String[] getServletMappings() {
		// TODO Auto-generated method stub
		return new String[]{"/"};
	}
	@Override
	protected Filter[] getServletFilters() {
		//创建编码过滤器
		CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
		characterEncodingFilter.setEncoding("UTF-8");
		characterEncodingFilter.setForceEncoding(true);
		//创建处理请求方式过滤器
		HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
		return new Filter[] {characterEncodingFilter,hiddenHttpMethodFilter};
	}
	
}

2、配置springmvc的配置文件

//将类标识为配置类
@Configuration
//扫描组件
@ComponentScan("controller")
//开启mvc注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
	//配置Thymeleaf视图解析器
    //配置生成模板解析器
    @Bean
    public ServletContextTemplateResolver templateResolver() {
    	WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());
        resolver.setPrefix("/WEB-INF/templates/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }
    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        return engine;
    }   
    //生成视图解析器并为解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setCharacterEncoding("UTF-8");
        resolver.setTemplateEngine(templateEngine());
        return resolver;
    }
	//处理静态资源
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
		WebMvcConfigurer.super.configureDefaultServletHandling(configurer);
	}
	//配置视图控制器
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/").setViewName("index");
		WebMvcConfigurer.super.addViewControllers(registry);
	}
	//文件上传解析器
	@Bean
	//@Bean注解可以将标识的方法的返回值作为bean来管理
	public CommonsMultipartResolver multipartResolver() {
		return new CommonsMultipartResolver();
	}
	//配置过滤器
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		FirstInterceptor firstInterceptor = new FirstInterceptor();
		registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
		WebMvcConfigurer.super.addInterceptors(registry);
	}
	@Override
	public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
		// TODO Auto-generated method stub
		WebMvcConfigurer.super.configureHandlerExceptionResolvers(resolvers);
	}
	配置异常处理解析器
	@Override
	public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
		SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
		Properties properties = new Properties();
		properties.setProperty("java.lang.ArithmeticException", "error");
		simpleMappingExceptionResolver.setExceptionMappings(properties);
		simpleMappingExceptionResolver.setExceptionAttribute("ex");
		resolvers.add(simpleMappingExceptionResolver);
		WebMvcConfigurer.super.extendHandlerExceptionResolvers(resolvers);
	}
		
}

你可能感兴趣的:(spring,java,mvc)