SpringMVC集合

news2024/11/16 4:49:44

目录

  • 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)引入依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.1</version>
</dependency>
<!-- servletAPI -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
  <!-- slf4j日志门面的一个具体实现 -->
  <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.5</version>
    <scope>test</scope>
</dependency>
<!-- spring5和hymeleaf整合包 -->
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf-spring5 -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.15.RELEASE</version>
</dependency>

(2)配置web.xml

注意:

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

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

  • /:匹配浏览器向服务器发送的所有请求(不包括.jsp)
  • /*:匹配浏览器向服务器发送的所有请求(包括.jsp)
<?xml version="1.0" encoding="UTF-8"?>
<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 Application</display-name>
  <!-- 配置SpringMVC的前端控制器DispatcherServlet -->
  <servlet>
  	<servlet-name>SpringMVC</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>SpringMVC</servlet-name>
  	<url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

(3)创建请求控制器

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

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

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

@Controller
public class HelloController {

}

(4)创建SpringMVC的配置文件

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

<?xml version="1.0" encoding="UTF-8"?> 
<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>
	 
	 <!-- 配置Thymeleaf视图解析器 -->
	<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">
<!-- xmlns:th="http://www.thymeleaf.org": 引入thymeleaf -->
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>Hello World!</h2>
<a th:href="@{/hello }">测试SpringMVC</a>
<a href="/hello">测试绝对路径</a>
</body>
</html>

以及success.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>success</h1>
</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测试在这里插入图片描述

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

在web.xml中修改servlet配置

  <servlet>
  	<servlet-name>SpringMVC</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <!-- 初始化配置
 		   classpath:将springmvc配置文件转到resources下
	   -->
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:springmvc.xml</param-value>
  	</init-param>
      <!-- 
		不在浏览器开启第一时间去访问DispatcherServlet:将DispatcherServlet的初始化时间提前到服务器启动时
	   -->
      <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>SpringMVC</servlet-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";
	}

在这里插入图片描述

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={}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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";
	}

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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下设置过滤器就可以完成

<!-- 配置spring的编码问题 -->
  <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>forceEncoding</param-name>
  		<param-value>true</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilter</filter-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的注释驱动 -->
	<mvc:annotation-driven></mvc:annotation-driven>	
	<!-- 
		 path:设置处理的请求地址
 	     view-controller:设置请求地址所对应的视图名称
	 -->
	<mvc:view-controller path="/" view-name="index"></mvc:view-controller>

相当于:

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

注意:

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

要在配置文件中设置<mvc:annotation-driven />

RESTful

1、RESTful简介

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

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

2、RESTful的实现

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

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

http方法资源操作幂等安全
GETSELECT(查)
POSTINSERT(增)
PUTUPDATE(改)
DELETEDELETE(删)

幂等性:对同一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>HiddenHttpMethodFilter</filter-name>
  	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
  	<filter-name>HiddenHttpMethodFilter</filter-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下配置<mvc:default-servlet-handler />和<mvc:annotation-driven />

​ 若配置了<mvc:default-servlet-handler />,此时浏览器发送的请求都会被DefaultServlet处理
​ 若配置了<mvc:default-servlet-handler />和<mvc:annotation-driven />
​ 浏览器发送到请求会先被DispacherServlet处理,无法处理的交给DefaultServlet处理

	<!-- 配置默认的servlet处理静态资源-->
	<mvc:default-servlet-handler/>
	<!-- 开启mvc的注释驱动 -->
	<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(配置文件)

<?xml version="1.0" encoding="UTF-8"?> 
<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>
	 
	 <!-- 配置Thymeleaf视图解析器 -->
	<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>
	
	<!-- 配置默认的servlet处理静态资源
		 当前工程的web.xml配置的前端控制器DispacherServlet的url-pattern是/
		 此时,浏览器发送到请求会优先被DispacherServlet进行处理,但是DispacherServlet无法处理静态资源
		 若配置了<mvc:default-servlet-handler />,此时浏览器发送的请求都会被DefaultServlet处理
		 若配置了<mvc:default-servlet-handler />和<mvc:annotation-driven />
		 浏览器发送到请求会先被DispacherServlet处理,无法处理的交给DefaultServlet处理
	 -->
	<mvc:default-servlet-handler/>
	<!-- 开启mvc的注释驱动 -->
	<mvc:annotation-driven></mvc:annotation-driven>	
	<!-- 视图控制器:为当前的请求直接设置视图名称实现页面跳转
		 若设置视图控制器,则只有视图控制器所设置的请求会被处理,其它的请求将全部404
	 -->
	<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

<?xml version="1.0" encoding="UTF-8"?>
<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 Application</display-name>
  <!-- 配置SpringMVC的前端控制器DispatcherServlet
  	   注意:
  	   SpringMVC的配置文件默认的位置和名称:
  	   位置:WEB-INF下
  	   名称:<servlet-name>-servlet.xml,以下配置的文件名称为SpringMVC-servlet.xml
	   url-pattern中/和/*的区别:
       /:匹配浏览器向服务器发送的所有请求(不包括.jsp)
       /*:匹配浏览器向服务器发送的所有请求(包括.jsp)
   -->
   <!-- 配置spring的编码问题 -->
  <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>forceEncoding</param-name>
  		<param-value>true</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter>
  	<filter-name>HiddenHttpMethodFilter</filter-name>
  	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>HiddenHttpMethodFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
    
  <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:springmvc.xml</param-value>
  	</init-param>
  	 <!-- 
		不在浏览器开启第一时间去访问DispatcherServlet:将DispatcherServlet的初始化时间提前到服务器启动时
	   -->
  	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>SpringMVC</servlet-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 here</title>
</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 here</title>
</head>
<body>
<div id="app">
		<table>
			<tr>
				<th>id</th>
				<th>name</th>
				<th>sex</th>
				<th>options(<a th:href="@{/to/add}">add</a>)</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}}">update</a>
				<a @click="getfrom()" th:href="@{'/employee/'+${employee.id}}">delete</a>
				<!-- <a οnclick="getfrom()" th:href="@{'/employee/'+${employee.id}}">delete</a> -->
				</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 here</title>
</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 here</title>
</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.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    
  • 在springmvc的配置文件中设置<mvc:annotation-driven />

  • 在处理请求的控制器方法的形参位置,直接设置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.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    
  • 在springmvc的配置文件中设置<mvc:annotation-driven />

  • 将需要转换的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<byte[]>的使用和理解

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上传文件步骤:

  • 添加依赖

    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.5</version>
    </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>
		<!-- 两种配置方式都是对DispatcherServlet所处理的所有请求进行拦截 -->
		<!-- <bean class="interceptor.FirstInterceptor"></bean> -->
		<!-- <ref bean="firstInterceptor"></ref> -->
		<mvc:interceptor>
            <!-- /**表示项目下的路径都执行,/*只执行/下的路径,如/1/test不执行 -->
			<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>

在这里插入图片描述

输出顺序:

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

异常处理

xml配置处理异常

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
        	<!--
        		properties的键表示处理器方法执行过程中出现的异常
        		properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
        	-->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!--
    	exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享
    -->
    <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);
	}
		
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Docker] Docker学习和基本配置部署(一)

前言&#xff1a; Docker的作用是通过容器化技术实现快速、可移植和可扩展的应用程序部署与管理。 文章目录 引言容器化的基本概念Docker的背景产生Docker 配置和命令详解1. 安装 Docker2. Docker 配置3. Docker 命令 Docker的核心组件Docker在软件开发和云计算中的重要性Docke…

rancher

rancher&#xff08;牧场主&#xff09;简介&#xff1a; Rancher是一个开源的容器管理平台&#xff0c;它提供了一套完整的解决方案来管理和部署容器集群。它的目标是简化容器化应用的部署、管理和运维工作。 Rancher使用了开放标准的容器技术&#xff0c;如Docker和Kubernete…

C/C++实现高并发http服务器

http高并发服务器实现 基础知识 html&#xff0c;全称为html markup language&#xff0c;超文本标记语言。 http&#xff0c;全称hyper text transfer protocol&#xff0c;超文本传输协议。用于从万维网&#xff08;WWW&#xff1a;World Wide Web&#xff09;服务器传输超…

绝了!贸易企业增值税高,税负重怎么办?这些处理技巧请收藏!

绝了&#xff01;贸易企业增值税高&#xff0c;税负重怎么办&#xff1f;这些处理技巧请收藏&#xff01; 《税筹顾问》专注于园区招商、企业税务筹划&#xff0c;合理合规助力企业节税&#xff01; 贸易企业始终都逃脱不了税负重的问题&#xff0c;这是因为贸易企业自身的行业…

ChatGPT潮落 资金逃离AI概念股

ChatGPT访问量首次出现负增长&#xff0c;寒气传导到证券市场。 上半年经历暴涨的一众AI概念股偃旗息鼓&#xff0c;蓝色光标、三六零、昆仑万维等知名个股均较高点跌超30%。微软、英伟达也未能幸免&#xff0c;同样有不同程度回调。 回顾这波过山车般的市场表现&#xff0c;…

【JavaEE】你真的了解Cookie和Session吗?

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 目录 文章目录 一、什么是Cookie 二、什么是Session 三、Cookie和Session有什么不同 四、关于Sessionid 五、关于浏览器禁止Cookie 六、如何考虑分布式Session问题&#xff1f; 七、Serv…

springboot请求重定向失败问题解决方案

今天晚上在写登录页面时&#xff0c;发现自己的首页无法正常访问&#xff0c;用户名和密码正常的情况下还是无法访问首页。于是开始进行debug&#xff0c; 程序执行至此处时无任何异常&#xff0c;但是就是在进行重定向页面时出现了404&#xff0c;在检查导航栏后发现地址栏也发…

做好POC测试 需要重点关心的5点

在日常POC测试过程中&#xff0c;往往遇到&#xff1a;测试计划时间结束才达到测试目标&#xff0c;导致结果未记录&#xff1b;不了解测试达标要求&#xff0c;未达到测试要求&#xff0c;后期大量的工作进行补救&#xff1b;测试遇到的问题&#xff0c;没有充分地相互沟通等问…

Dell Inspiron 15-3567电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。&#xff08;下载请直接百度黑果魏叔&#xff09; 硬件型号驱动情况 主板Dell Inspiron 15-3567 处理器Intel Core i5 Kabylake, 7200U, 2.70 GHz已驱动 内存16GB LPDDR4X 3200MHz已驱动 硬盘三星 MZVLW1T0HMLH-000L2 (…

pycharm找不到conda可执行文件怎么办?

问题&#xff1a;pycharm配置conda环境找不到conda可执行文件 解决办法&#xff1a; 1. 找到 anaconda 安装目录&#xff08;D:\Users\wl\anaconda3&#xff09; 2. 打开pycharm &#xff08;看图吧<手动狗头>&#xff09; 找到anaconda3\condabin\conda.bat 选择你要…

【从删库到跑路】MySQL数据库的 存储引擎

&#x1f38a;专栏【MySQL】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f33a;存储引擎简介&#x1f384;查询当前数据库支持的存储引擎&#x1f384;…

C++笔记之是否知道了一个数组首元素的地址就可以获取该整个数组?-面试问题

C笔记之数组名和指针GPT问答记录 事前提要&#xff1a;前段时间去面一个公司&#xff0c;面试官说知道了一个数组首元素的地址&#xff0c;就可以获取该整个数组&#xff0c;我当时就困惑&#xff0c;不知道大小和长度&#xff0c;只知道地址怎么就能获取。但也没反驳面试官&a…

ChatGPT炒股:批量下载北交所上市公司的招股说明书

打开北京证券交易所官网&#xff0c;点击发行上市&#xff0c;然后点击公开发行信息披露&#xff0c;然后在查询框里面输入关键词&#xff1a;在北京证券交易所上市招股说明书&#xff0c;然后选择时间&#xff0c;点击查询&#xff0c;就可以看到所有北交所上市公司的招股说明…

数据集【NO.13】复杂场景下的鸟类检测数据集

写在前面&#xff1a;数据集对应应用场景&#xff0c;不同的应用场景有不同的检测难点以及对应改进方法&#xff0c;本系列整理汇总领域内的数据集&#xff0c;方便大家下载数据集&#xff0c;若无法下载可关注后私信领取。关注免费领取整理好的数据集资料&#xff01;今天分享…

一款可定时发圈和标签群发的微信管理软件是什么样的?

什么是时间管理&#xff1f;它是一种科学的解释&#xff0c;意味着时间的流逝是不可阻挡的&#xff0c;但是可以通过掌握时间来获取更多的改变。那如何在有限的生命里而做更多有意义的事情呢&#xff1f;学习一下时间管理&#xff0c;你一定会从中得到启发和答案的。 1.先确定…

MYSQL建库及查询

目的&#xff1a; 1.创建数据库&#xff0c;删除数据库&#xff0c;查询创建数据的语句&#xff0c;使用数据库&#xff0c;查询当前默认的数据库以及使用的编码方式校验规则 2.数字&#xff0c;文本&#xff0c;日期 在一章表中定义多个字段&#xff0c;要使用提到的所有的数…

vue 多环境打包指令配置及编译

1.创建多环境: 在根目录创建.env.xxx文件,如下为例(我创建了两个) 文件内容主要包括&#xff1a; # 页面标题 VUE_APP_TITLE "标题"# 生产环境配置 ENV production# DNA检测仓储管理系统/生产环境 VUE_APP_BASE_API https://xxxxxx 2.设置: 修改根目录下的package…

Parasoft Jtest 2023.1版本-全新的Jtest让你的Java测试更加容易

测试用例的创建和执行以及测量代码覆盖率是现代开发过程的重要组成部分。新发布的Parasoft Jtest 2023.1增加了重要的新功能&#xff0c;使Java开发和QA团队在测试实践中更具有生产力和效率。 通过使用最新版本的Jtest&#xff0c;您可以在Visual Studio code IDE中提高Java代…

设计模式之二:观察者模式

假定我们需要为Weather-O-Rama公司建立一个气象站系统&#xff0c;除已有的WeatherData有数据源类&#xff0c;还需要更新三个布告板的显示&#xff1a;目前状况&#xff08;温度、湿度、气压&#xff09;、气象统计和天气预报。 1 以下是一个可能的实现 class WeatherData { …

雅思口语备考模仿练习有没有用?

如何对于雅思口语进行模仿练习&#xff1f;这是很多同学需要了解的事情&#xff0c;那么接下来就和一起来了解一下雅思口语备考模仿练习有没有用&#xff1f; 模仿练习 1. 方法 众所周知&#xff0c;模仿最基本的方法便是跟读。跟读的途径可以是两种&#xff1a;一种是听录音…