yahoo提交网站入口,织梦论坛源码,搭建一个论坛网站,站长素材网站官网文章目录 一、SpringMVC简介1、什么是MVC2、MVC架构模式与三层模型的区别3、什么是SpringMVC 二、HelloWorld程序1、pom文件2、springmvc.xml3、配置web.xml文件4、html文件5、执行Controller 三、RequestMapping注解1、value属性1.1、基础使用1.2、Ant风格#xff08;模糊匹配… 文章目录 一、SpringMVC简介1、什么是MVC2、MVC架构模式与三层模型的区别3、什么是SpringMVC 二、HelloWorld程序1、pom文件2、springmvc.xml3、配置web.xml文件4、html文件5、执行Controller 三、RequestMapping注解1、value属性1.1、基础使用1.2、Ant风格模糊匹配路径1.3、路径占位符PathVariable 2、method属性2.1、基础使用2.2、衍生xxxMapping注解2.3、web的请求方式 3、params属性4、headers属性 四、获取请求参数1、原生Servlet API2、RequestParam注解2.1、value属性2.2、required属性2.2、defaultValue属性 3、根据形参名获取4、根据实体类接收5、RequestHeader注解6、CookieValue注解7、请求的中文乱码问题7.1、get请求乱码7.2、post请求乱码 五、Servlet的三个域对象1、request域对象2、session域对象3、application域对象 六、HttpMessageConverter消息转换器1、Form表单转换器和默认转换器2、ResponseBody2.1、Servlet原生API方式2.2、ResponseBody注解方式2.3、MappingJackson2HttpMessageConverter(JSON转换器) 3、RestController4、RequestBody4.1、拼接参数4.2、JSON格式参数 5、RequestEntity6、ResponseEntity 七、异常处理器1、默认异常处理器2、自定义异常处理器2.1、跳转错误页面2.2、返回错误响应对象 八、拦截器1、拦截器概述2、拦截器和过滤器的区别3、拦截器的创建与基本配置4、多个拦截器执行顺序 一、SpringMVC简介
1、什么是MVC
MVC是一种软件架构模式是一种软件架构设计思想不止Java开发中用到其它语言也需要用到它将应用分为三块 MModel模型负责业务处理及数据的收集VView视图负责数据的展示CController控制器负责调度。它是一个调度中心它来决定什么时候调用Model来处理业务什么时候调用View视图来展示数据 MVC架构模式的描述前端浏览器发送请求给web服务器web服务器中的Controller接收到用户的请求Controller负责将前端提交的数据进行封装然后Controller调用Model来处理业务当Model处理完业务后会返回处理之后的数据给ControllerController再调用View来完成数据的展示最终将结果响应给浏览器浏览器进行渲染展示页面。
2、MVC架构模式与三层模型的区别 什么是三层模型 三层模型就是由Controller控制器和View视图组成的表现层将Model数据模型拆封为业务层和与数据库交互的持久层 MVC架构模式与三层模型的区别 MVC和三层模型都采用了分层结构来设计应用程序都是降低耦合度提高扩展力提高组件复用性区别在于他们的关注点不同 三层模型更加关注业务逻辑组件的划分MVC架构模式关注的是整个应用程序的层次关系和分离思想 现代的开发方式大部分都是MVC架构模式结合三层模型一起用
3、什么是SpringMVC
SpringMVC是一个实现了MVC架构模式的Web框架底层基于Servlet实现SpringMVC已经将MVC架构模式实现了因此只要我们是基于SpringMVC框架写代码Spring框架中有一个子项目叫做Spring WebSpring Web子项目当中包含很多模块 Spring MVCSpring WebFluxSpring Web ServicesSpring Web FlowSpring WebSocketSpring Web Services Client Spring架构图如下其中Web中的servlet指的就是Spring MVC 二、HelloWorld程序
1、pom文件
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.xc/groupIdartifactIdspringmvc-xml/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingdependencies!--springmvc--dependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.3.1/version/dependency!--servletAPI--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependency!--spring5和thymeleaf整合--dependencygroupIdorg.thymeleaf/groupIdartifactIdthymeleaf-spring5/artifactIdversion3.0.11.RELEASE/version/dependency/dependenciespropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/properties/project2、springmvc.xml
组件扫描。spring扫描这个包中的类将这个包中的类实例化并纳入IoC容器的管理视图解析器。视图解析器View Resolver的作用主要是将Controller方法返回的逻辑视图名称解析成实际的视图对象。视图解析器将解析出的视图对象返回给DispatcherServlet并最终由DispatcherServlet将该视图对象转化为响应结果呈现给用户
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd!--组件扫描--context:component-scan base-packagecom.xc.controller/!--视图解析器--bean idthymeleafViewResolver classorg.thymeleaf.spring5.view.ThymeleafViewResolver!--作用于视图渲染的过程中可以设置视图渲染后输出时采用的编码字符集--property namecharacterEncoding valueUTF-8/!--如果配置多个视图解析器它来决定优先使用哪个视图解析器它的值越小优先级越高--property nameorder value1/!--当 ThymeleafViewResolver 渲染模板时会使用该模板引擎来解析、编译和渲染模板--property nametemplateEnginebean classorg.thymeleaf.spring5.SpringTemplateEngine!--用于指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器负责根据模板位置、模板资源名称、文件编码等信息加载模板并对其进行解析--property nametemplateResolverbean classorg.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver!--设置模板文件的位置前缀--property nameprefix value/WEB-INF/templates//!--设置模板文件后缀后缀Thymeleaf文件扩展名不一定是html也可以是其他例如txt大部分都是html--property namesuffix value.html/!--设置模板类型例如HTML,TEXT,JAVASCRIPT,CSS等--property nametemplateMode valueHTML/!--用于模板文件在读取和解析过程中采用的编码字符集--property namecharacterEncoding valueUTF-8//bean/property/bean/property/bean
/beans3、配置web.xml文件
Spring MVC是一个web框架在javaweb中谁来负责接收请求处理请求以及响应呢当然是Servlet在SpringMVC框架中已经为我们写好了一个Servlet它的名字叫做DispatcherServlet我们称其为前端控制器既然是Servlet那么它就需要在web.xml文件中进行配置
?xml version1.0 encodingUTF-8?
web-app xmlnshttps://jakarta.ee/xml/ns/jakartaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttps://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsdversion5.0!--配置前端控制器--servletservlet-namespringmvc/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class!--手动设置springmvc配置文件的路径及名字--init-paramparam-namecontextConfigLocation/param-nameparam-valueclasspath:springmvc.xml/param-value/init-param!--为了提高用户的第一次访问效率建议在web服务器启动时初始化前端控制器--load-on-startup1/load-on-startup/servletservlet-mappingservlet-namespringmvc/servlet-name!-- /* 表示任何一个请求都交给DispatcherServlet来处理 --!-- / 表示当请求不是xx.jsp的时候DispatcherServlet来负责处理本次请求--!-- jsp本质就是Servlet因此如果请求是jsp的话应该走它自己的Servlet而不应该走DispatcherServlet --!-- 因此我们的 url-pattern 使用 / --url-pattern//url-pattern/servlet-mapping/web-appDispatcherServlet是SpringMVC框架为我们提供的最核心的类它是整个SpringMVC框架的前端控制器负责接收HTTP请求、将请求路由到处理程序、处理响应信息最终将响应返回给客户端。
接收客户端的HTTP请求DispatcherServlet监听来自Web浏览器的HTTP请求Tomcat已经将请求数据解析为Request对象处理请求的URLDispatcherServlet将请求的URL与处理程序进行匹配确定要调用哪个控制器(Controller)来处理此请求调用相应的控制器DispatcherServlet将请求发送给找到的控制器处理控制器将执行业务逻辑然后返回一个模型对象(Model)渲染视图DispatcherServlet将调用视图引擎将模型对象呈现为用户可以查看的HTML页面返回响应给客户端DispatcherServlet将为用户生成的响应发送回浏览器响应可以包括表单、JSON、XML、HTML以及其它类型的数据
4、html文件
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
hello world
/body
/html5、执行Controller
Controller
public class HelloController {RequestMapping(/test)public String test(){return success;}
}配置Tomcat 启动tomcat调用test 三、RequestMapping注解 RequestMapping 注解是 Spring MVC 框架中的一个控制器映射注解用于将请求映射到相应的处理方法上。具体来说它可以将指定 URL 的请求绑定到一个特定的方法或类上从而实现对请求的处理和响应。 RequestMapping的出现位置 通过源码可以看到RequestMapping注解只能出现在类上或者方法上当然类上和方法上也可以同时出现类上是公共的方法上是独有的 1、value属性
1.1、基础使用
value属性是该注解最核心的属性value属性填写的是请求路径也就是说通过该请求路径与对应的控制器的方法绑定在一起value属性是一个字符串数组表示可以提供多个路径也就是说多个不同的请求路径可以映射同一个控制器的同一个方法value属性和path属性互为别名两个属性一样 举例 如下两个请求路径都可以正常访问到控制器的方法上 http://localhost:8080/springmvc/hello/test1http://localhost:8080/springmvc/hello/test2
Controller
RequestMapping(/hello)
public class RequestMappingController {RequestMapping(value {/test1,test2})public String test(){return success;}
}1.2、Ant风格模糊匹配路径
value是可以用来匹配路径的路径支持模糊匹配我们把这种模糊匹配称之为Ant风格 ?表示任意的单个字符*表示任意的0个或多个字符**表示任意的一层或多层目录只能使用xxx/**的方式 匹配?例子 RequestMapping(/x?z/testValueAnt)
public String testValueAnt(){return success;
}匹配成功可以正常访问到以上控制器的方法上 匹配失败抛错404 匹配*例子 RequestMapping(/x*z/testValueAnt)
public String testValueAnt(){return success;
}匹配成功可以正常访问到以上控制器的方法上 匹配失败抛错404 匹配**例子 spring6中**通配符只能出现在路径的末尾否则抛错spring5可以不用在末尾
RequestMapping(/testValueAnt/**)
public String testValueAnt(){return success;
}匹配成功可以正常访问到以上控制器的方法上 1.3、路径占位符PathVariable 普通的请求路径http://localhost:8080/springmvc/login?usernameadminpassword123age20
restful风格的请求路径http://localhost:8080/springmvc/login/admin/123/20 如果使用restful风格的请求路径在控制器中应该如何获取请求中的数据呢 不加PathVariable路径变量注解会抛500异常
RequestMapping(value /testRestful/{id}/{username}/{age})
public String testRestful(PathVariable(id) int id,PathVariable(username) String username,PathVariable(age) int age) {System.out.println(id , username , age);return success;
}2、method属性
2.1、基础使用
如果前端发送请求的方式和后端的处理方式不一致时会出现405错误HTTP状态码405这种机制的作用是限制客户端的请求方式以保证服务器中数据的安全SpringMVC使用RequestMapping注解的method属性来实现限制请求方式 通过RequestMapping源码可以看到method属性也是一个数组数组中的每个元素是RequestMethod而RequestMethod是一个枚举类型的数据 举例 只允许get和post请求方式否则报错405
RequestMapping(value/login, method {RequestMethod.GET,RequestMethod.POST})
public String testMethod(){return success;
}2.2、衍生xxxMapping注解
SpringMVC提供了另外一些注解使用更加的方便 GetMapping要求前端必须发送get请求PutMapping要求前端必须发送put请求DeleteMapping要求前端必须发送delete请求PatchMapping要求前端必须发送patch请求 举例 两种方式效果一样对比衍生注解更加简洁
//RequestMapping(value/login, method RequestMethod.POST)
PostMapping(/login)
public String testMethod(){return success;
}2.3、web的请求方式 前端向服务器发送请求的方式包括哪些共9种 GET获取资源只允许读取数据不影响数据的状态和功能 使用URL中传递参数或者在HTTP请求的头部使用参数服务器返回请求的资源 POST向服务器提交资源可能还会改变数据的状态和功能 通过表单等方式提交请求体服务器接收请求体后进行数据处理 PUT更新资源用于更新指定的资源上所有可编辑内容 通过请求体发送需要被更新的全部内容服务器接收数据后将被更新的资源进行替换或修改 DELETE删除资源用于删除指定的资源 将要被删除的资源标识符放在URL中或请求体中 HEAD请求服务器返回资源的头部 与 GET 命令类似但是所有返回的信息都是头部信息不能包含数据体主要用于资源检测和缓存控制 OPTIONS请求获得服务器支持的请求方法类型以及支持的请求头标志 OPTIONS则返回支持全部方法类型的服务器标志主要用于跨域检查 PATCH部分更改请求 当被请求的资源是可被更改的资源时请求服务器对该资源进行部分更新即每次更新一部分 TRACE服务器响应输出客户端的 HTTP 请求主要用于调试和测试CONNECT建立网络连接通常用于加密 SSL/TLS 连接 ⚠️注意 使用超链接以及原生的form表单只能提交get和post请求put、delete、head请求可以使用发送ajax请求的方式来实现 GET和POST的区别 get请求比较适合从服务器端获取数据post请求比较适合向服务器端传送数据get请求支持缓存。 也就是说当第二次发送get请求时会走浏览器上次的缓存结果不再真正的请求服务器post请求不支持缓存。每一次发送post请求都会真正的走服务器
3、params属性
对于RequestMapping注解来说 value属性是一个数组只要满足数组中的任意一个路径就能映射成功method属性也是一个数组只要满足数组中任意一个请求方式就能映射成功params属性也是一个数组不过要求请求参数必须和params数组中要求的所有参数完全一致后才能映射成功 params属性的4种用法 RequestMapping(value/login, params{username, password}) 请求参数中必须包含username 和 password才能与当前标注的方法进行映射 RequestMapping(value/login, params{!username, password}) 请求参数中不能包含username参数但必须包含password参数才能与当前标注的方法进行映射 RequestMapping(value/login, params{usernameadmin, password}) 请求参数中必须包含username参数并且参数的值必须是admin另外也必须包含password参数才能与当前标注的方法进行映射 RequestMapping(value/login, params{username!admin, password}) 请求参数中必须包含username参数但参数的值不能是admin另外也必须包含password参数才能与当前标注的方法进行映射
4、headers属性
headers和params原理相同用法也相同当前端提交的请求头信息和后端要求的请求头信息一致时才能映射成功 headers属性的4种用法 RequestMapping(value/login, headers{Referer, Host}) 请求头信息中必须包含Referer和Host才能与当前标注的方法进行映射 RequestMapping(value/login, headers{!Referer, Host}) 请求头信息中不能包含Referer参数但必须包含Host参数才能与当前标注的方法进行映射 RequestMapping(value/login, headers{Refererxxx, Host}) 请求头信息中必须包含Referer参数并且参数的值必须是xxx另外也必须包含Host参数才能与当前标注的方法进行映射 RequestMapping(value/login, headers{Referer!xxx, Host}) 请求头信息中必须包含Referer参数但参数的值不能是xxx另外也必须包含Host参数才能与当前标注的方法进行映射
四、获取请求参数
1、原生Servlet API
前端表单提交数据 F12查询提交数据方式 后端控制器获取数据
PostMapping(value/register)
public String register(HttpServletRequest request){// 通过当前请求对象获取提交的数据String username request.getParameter(username);String password request.getParameter(password);String sex request.getParameter(sex);String[] hobbies request.getParameterValues(hobby);String intro request.getParameter(intro);System.out.println(username , password , sex , Arrays.toString(hobbies) , intro);return success;
}这样通过Servlet原生的API获取到提交的数据。但是这种方式不建议使用因为方法的参数HttpServletRequest依赖Servlet原生APIController的测试将不能单独测试必须依赖web服务器才能测试。
2、RequestParam注解
2.1、value属性
RequestParam注解作用将请求参数与方法上的形参映射
PostMapping(value /register)
public String register(RequestParam(value username) String a,RequestParam(value password) String b,RequestParam(value sex) String c,RequestParam(value hobby) String[] d,RequestParam(name intro) String e
) {System.out.println(a);System.out.println(b);System.out.println(c);System.out.println(Arrays.toString(d));System.out.println(e);return success;
}RequestParam注解的两个属性value和name互为别名作用相同 发送请求时提交的数据是name1value1name2value2则这个注解应该这样写RequestParam(valuename1)、RequestParam(valuename2)
2.2、required属性
required属性用来设置该方法参数是否为必须的默认情况下这个参数为 true表示方法参数是必需的。如果请求中缺少对应的参数则会抛出异常可以将其设置为falsefalse表示不是必须的如果请求中缺少对应的参数则方法的参数为null 举例 添加了一个 age 形参没有指定 required 属性时默认是true表示必需的 但前端表单中没有年龄age报错如下 2.2、defaultValue属性
defaultValue属性用来设置形参的默认值当没有提供对应的请求参数或者请求参数的值是空字符串的时候方法的形参会采用默认值 举例 age属性设置为非必须当前端不传值时候默认年龄为18岁 3、根据形参名获取
如果方法形参的名字和提交数据时的name相同则RequestParam可以省略
PostMapping(value/register)
public String register(String username, String password, String sex, String[] hobby, String intro){System.out.println(username , password , sex , Arrays.toString(hobby) , intro);return success;
}4、根据实体类接收
在SpringMVC中也可以使用POJO类/JavaBean实体类来接收请求参数不过有一个非常重要的要求实体类的属性名必须和请求参数的参数名保持一致
PostMapping(/register)
public String register(User user){System.out.println(user);return success;
}底层的实现原理反射机制 先获取User对象实例没有则反射实例化然后获取请求参数的名字通过请求参数名字拼接出set属性名的方法名最后User实例和set属性方法反射给属性赋值 请求参数是否可以赋值到JavaBean对应的属性上不是取决于属性名而是setter方法名
5、RequestHeader注解
该注解的作用是将请求头信息映射到方法的形参上对于RequestHeader注解来说也有三个属性value、required、defaultValue和RequestParam一样
PostMapping(/register)
public String register(User user, RequestHeader(valueReferer, required false, defaultValue ) String referer){System.out.println(user);System.out.println(referer);return success;
}6、CookieValue注解
该注解的作用是将请求提交的Cookie数据映射到方法的形参上对于CookieValue注解来说也有三个属性value、required、defaultValue和RequestParam一样
GetMapping(/register)
public String register(User user,CookieValue(valueid, required false, defaultValue 110) String id){System.out.println(user);System.out.println(id);return success;
}7、请求的中文乱码问题
7.1、get请求乱码
get请求数据在URI后面提交这个乱码问题怎么解决呢解决办法是找到 CATALINA_HOME/config/server.xml文件找到其中配置端口号的标签Connector在该标签中添加URIEncodingUTF-8 但是对于高版本的Tomcat服务器来说是不需要设置的例如Tomcat10Tomcat9有如下的默认配置在默认情况下URIEncoding使用的就是UTF-8的编码方式 但对于低版本的Tomcat服务器例如Tomcat8URIEncoding的默认配置是ISO-8859-1 7.2、post请求乱码
post请求是解决请求体的中文乱码问题
request.setCharacterEncoding(UTF-8);同样对于高版本的Tomcat10服务器来说针对请求体中的字符编码也是配置好的默认也是采用了UTF-8web.xml配置如下 一定要注意Tomcat9以及之前的版本以上的配置是没有的解决方法web.xml中配置mvc自带的乱码过滤器
!--配置SpringMVC自带的乱码过滤器--
filterfilter-nameencoding/filter-namefilter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueutf-8/param-value/init-param!-- 设置forceEncoding为true就是强制设置编码的意思forceEncoding为true就会设置forceRequestEncoding和forceResponseEncoding为true这样如下源码的两个if条件成立就会设置utf-8编码了--init-paramparam-nameforceEncoding/param-nameparam-valuetrue/param-value/init-param
/filter
filter-mappingfilter-nameencoding/filter-nameurl-pattern/*/url-pattern
/filter-mapping源码解析 五、Servlet的三个域对象
请求域request、会话域session、应用域application三个域都有以下三个方法
// 向域中存储数据
void setAttribute(String name, Object obj);// 从域中读取数据
Object getAttribute(String name);// 删除域中的数据
void removeAttribute(String name);主要是通过setAttribute getAttribute方法来完成在域中数据的传递和共享
1、request域对象
request对象代表了一次请求一次请求一个request使用请求域的业务场景 在A资源中通过转发的方式跳转到B资源因为是转发所以从A到B是一次请求如果想让A资源和B资源共享同一个数据可以将数据存储到request域中 在request域中共享数据有以下几种方式 使用原生Servlet API方式使用Model接口使用Map接口使用ModelMap类使用ModelAndView类 使用原生Servlet API方式 RequestMapping(/testServletAPI)
public String testServletAPI(HttpServletRequest request){// 向request域中存储数据request.setAttribute(testRequestScope, 在SpringMVC中使用原生Servlet API实现request域数据共享);return view;
}使用Model接口 RequestMapping(/testModel)
public String testModel(Model model){// 向request域中存储数据model.addAttribute(testRequestScope, 在SpringMVC中使用Model接口实现request域数据共享);return view;
}使用Map接口 RequestMapping(/testMap)
public String testMap(MapString, Object map){// 向request域中存储数据map.put(testRequestScope, 在SpringMVC中使用Map接口实现request域数据共享);return view;
}使用ModelMap类 RequestMapping(/testModelMap)
public String testModelMap(ModelMap modelMap){// 向request域中存储数据modelMap.addAttribute(testRequestScope, 在SpringMVC中使用ModelMap实现request域数据共享);return view;
}Model、Map、ModelMap的关系
输出打印Model、Map、ModelMap的Class底层实例化的对象都是BindingAwareModelMapBindingAwareModelMap的继承结构 BindingAwareModelMap继承ModelMap实现Model而ModelMap又实现了Map接口 使用ModelAndView类 为了更好的体现MVC架构模式提供了一个类ModelAndView。这个类的实例封装了Model和View也就是说这个类既封装业务处理之后的数据也体现了跳转到哪个视图使用它也可以完成request域数据共享
RequestMapping(/testModelAndView)
public ModelAndView testModelAndView(){// 创建“模型与视图对象”ModelAndView modelAndView new ModelAndView();// 绑定数据modelAndView.addObject(testRequestScope, 在SpringMVC中使用ModelAndView实现request域数据共享);// 绑定视图modelAndView.setViewName(view);// 返回return modelAndView;
}注意
方法的返回值类型不是String而是ModelAndView对象ModelAndView不是出现在方法的参数位置而是在方法体中new的需要调用addObject向域中存储数据需要调用setViewName设置视图的名字 以上我们通过了五种方式完成了request域数据共享这几种方式在底层DispatcherServlet调用我们的Controller之后返回的对象都是ModelAndView。 2、session域对象
session对象代表了一次会话 从打开浏览器开始访问到最终浏览器关闭这是一次完整的会话每个会话session对象都对应一个JSESSIONID而JSESSIONID生成后以cookie的方式存储在浏览器客户端浏览器关闭JSESSIONID失效会话结束 使用会话域的业务场景 登录成功后保存用户的登录状态 使用原生Servlet API方式 RequestMapping(/testSessionScope1)
public String testServletAPI(HttpSession session) {// 向会话域中存储数据session.setAttribute(testSessionScope1, 使用原生Servlet API实现session域共享数据);return view;
}3、application域对象
application对象代表了整个web应用 服务器启动时创建服务器关闭时销毁对于一个web应用来说application对象只有一个 使用应用域的业务场景 记录网站的在线人数 使用原生Servlet API方式 RequestMapping(/testApplicationScope)
public String testApplicationScope(HttpServletRequest request){// 获取ServletContext对象ServletContext application request.getServletContext();// 向应用域中存储数据application.setAttribute(applicationScope, 我是应用域当中的一条数据);return view;
}六、HttpMessageConverter消息转换器
HttpMessageConverter是Spring MVC中非常重要的一个接口翻译为HTTP消息转换器。该接口下提供了很多实现类不同的实现类有不同的转换方式 转换器是HTTP协议与Java程序中的对象之间的互相转换 1、Form表单转换器和默认转换器 Form表单转换器 请求体中的数据是如何转换成user对象的底层实际上使用了HttpMessageConverter接口的其中一个实现类FormHttpMessageConverter。 通过上图可以看出FormHttpMessageConverter是负责将请求协议转换为Java对象的。 默认转换器 Controller返回值看做逻辑视图名称视图解析器将其转换成物理视图名称生成视图对象StringHttpMessageConverter负责将视图对象中的HTML字符串写入到HTTP协议的响应体中。最终完成响应。 通过上图可以看出StringHttpMessageConverter是负责将Java对象转换为响应协议的。
2、ResponseBody
首页面AJAX请求获取数据非跳转页面Controller
2.1、Servlet原生API方式
// 有返回值
RequestMapping(value /hello1)
public String hello1(HttpServletResponse response) throws IOException {response.getWriter().print(hello);return null;
}// 无返回值
RequestMapping(value /hello2)
public void hello2(HttpServletResponse response) throws IOException {response.getWriter().print(hello);
}页面展示 注意如果采用这种方式响应则和 springmvc.xml 文件中配置的视图解析器没有关系不走视图解析器了
2.2、ResponseBody注解方式
这里的hello不是逻辑视图名了而是作为响应体的内容进行响应。直接输出到浏览器客户端程序中使用的消息转换器是StringHttpMessageConverter为什么会启用这个消息转换器呢 因为你添加ResponseBody这个注解
Controller
public class HelloController {RequestMapping(value /hello)ResponseBodypublic String hello(){// 由于你使用了 ResponseBody 注解// 以下的return语句返回的字符串则不再是“逻辑视图名”了// 而是作为响应协议的响应体进行响应。return hello;}
}通常AJAX请求需要服务器给返回一段JSON格式的字符串可以返回JSON格式的字符串吗当然可以代码如下
Controller
public class HelloController {RequestMapping(value /hello)ResponseBodypublic String hello(){return {\username\:\zhangsan\,\password\:\1234\};}
}页面展示 此时底层使用的消息转换器还是StringHttpMessageConverter那如果在程序中是一个POJO对象怎么将POJO对象以JSON格式的字符串响应给浏览器呢 方式一自己写代码将POJO对象转换成JSON格式的字符串用上面的方式直接return即可方式二启用MappingJackson2HttpMessageConverter消息转换器
2.3、MappingJackson2HttpMessageConverter(JSON转换器) 启动JSON消息转换器需要两个步骤 第一步引入jackson依赖可以将java对象转换为json格式字符串
dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.17.0/version
/dependency第二步开启注解驱动会自动装配一个消息转换器MappingJackson2HttpMessageConverter
mvc:annotation-driven/ResponseBody最经典用法如下
RequestMapping(value /hello)
ResponseBody
public User hello(){User user new User(zhangsan, 18);return user;
}将POJO对象转换成JSON格式的字符串响应给前端 3、RestController
为了方便Spring MVC中提供了一个注解RestController。这一个注解代表了Controller ResponseBodyRestController标注在类上即可。被它标注的Controller中所有的方法上都会自动标注ResponseBody
RestController
public class HelloController {RequestMapping(value /hello)public User hello(){User user new User(zhangsan, 18);return user;}
}4、RequestBody
作用是直接将请求体传递给Java程序
4.1、拼接参数 在没有使用这个注解的时候 RequestMapping(/save)
public String save(User user){// 执行保存的业务逻辑userDao.save(user);// 保存成功跳转到成功页面return success;
}当请求体提交的数据是
usernamezhangsanpassword1234emailzhangsanpowernode.com那么Spring MVC会自动使用 FormHttpMessageConverter消息转换器将请求体转换成user对象 当使用这个注解的时候这个注解只能出现在方法的参数上 RequestMapping(/save)
public String save(RequestBody String requestBodyStr){System.out.println(请求体 requestBodyStr);return success;
}Spring MVC仍然会使用 FormHttpMessageConverter消息转换器将请求体直接以字符串形式传递给requestBodyStr变量
4.2、JSON格式参数
如果请求体是JSON格式字符串可以将其转化为POJO对象此时必须使用RequestBody注解来完成底层使用的消息转换器是MappingJackson2HttpMessageConverter启动步骤与ResponseBody一样引入jackson依赖、开启注解驱动
RequestMapping(/send)
ResponseBody
public String send(RequestBody User user){System.out.println(user);System.out.println(user.getUsername());System.out.println(user.getPassword());return success;
}5、RequestEntity
这个类的实例封装了整个请求协议包括请求行、请求头、请求体所有信息
RequestMapping(/send)
ResponseBody
public String send(RequestEntityUser requestEntity){System.out.println(请求方式 requestEntity.getMethod());System.out.println(请求URL requestEntity.getUrl());HttpHeaders headers requestEntity.getHeaders();System.out.println(请求的内容类型 headers.getContentType());System.out.println(请求头 headers);User user requestEntity.getBody();System.out.println(user);System.out.println(user.getUsername());System.out.println(user.getPassword());return success;
}执行结果 6、ResponseEntity
用该类的实例可以封装响应协议包括状态行、响应头、响应体如果你想定制属于自己的响应协议可以使用该类
Controller
public class UserController {GetMapping(/users/{id})public ResponseEntityUser getUserById(PathVariable Long id) {User user userService.getUserById(id);if (user null) {return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);} else {return ResponseEntity.ok(user);}}
}七、异常处理器
1、默认异常处理器
方法执行过程中出现了异常跳转到对应的视图在视图上展示友好信息
默认处理器DefaultHandlerExceptionResolver核心方法 当请求方式和处理方式不同时DefaultHandlerExceptionResolver的默认处理态度是 2、自定义异常处理器
2.1、跳转错误页面
ControllerAdvice
public class ExceptionController {ExceptionHandlerpublic String exceptionHandler(Exception e, Model model){model.addAttribute(e, e);return error;}
}!DOCTYPE html
html langen xmlns:thhttp://www.thymeleaf.org
headmeta charsetUTF-8title出错了/title
/head
body
h1出错了请联系管理员/h1
div th:text${e}/div
/body
/html2.2、返回错误响应对象
ControllerAdvice
public class ExceptionController {ExceptionHandler(value {Exception.class})ResponseBodypublic ResponseEntityString exceptionHandler(Exception e, Model model) {// 这里先判断拦截到的Exceptiion是不是我们自定义的异常类型if (e instanceof MyException) {MyException myException (MyException) e;return ResponseEntity.status(500).body(myException.getMeg());} else {// 如果拦截的异常不是我们自定义的异常(例如:数据库主键冲突)return ResponseEntity.status(500).body(服务器端异常);}}
}八、拦截器
1、拦截器概述
拦截器作用是在请求到达控制器之前或之后进行拦截可以对请求和响应进行一些特定的处理拦截器可以用于很多场景下 登录验证对于需要登录才能访问的网址使用拦截器可以判断用户是否已登录如果未登录则跳转到登录页面权限校验根据用户权限对部分网址进行访问控制拒绝未经授权的用户访问请求日志记录请求信息例如请求地址、请求参数、请求时间等用于排查问题和性能优化更改响应可以对响应的内容进行修改例如添加头信息、调整响应内容格式等
2、拦截器和过滤器的区别
过滤器更注重在请求和响应的流程中进行处理可以修改请求和响应的内容例如设置编码和字符集、请求头、状态码等拦截器则更加侧重于对控制器进行前置或后置处理在请求到达控制器之前或之后进行特定的操作例如打印日志、权限验证等
Filter、Servlet、Interceptor、Controller的执行顺序 3、拦截器的创建与基本配置 定义拦截器 实现org.springframework.web.servlet.HandlerInterceptor 接口共有三个方法可以进行选择性的实现 preHandle处理器方法调用之前执行(返回true放行false拦截)postHandle处理器方法调用之后执行afterCompletion渲染完成后执行
Component
public class MyInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(处理器方法前调用);return true;}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println(处理器方法后调用);}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println(渲染完成后调用);}
}基本配置 springmvc.xml配置如下
mvc:interceptorsbean classcom.xc.interceptors.MyInterceptor/
/mvc:interceptors
!-- 或者 --
mvc:interceptorsref beanmyInterceptor/
/mvc:interceptors添加组件扫描 注意对于这种基本配置来说拦截器是拦截所有请求的
4、多个拦截器执行顺序 如果所有拦截器preHandle都返回true 按照springmvc.xml文件中配置的顺序自上而下调用 preHandle
mvc:interceptorsref beaninterceptor1/ref beaninterceptor2/
/mvc:interceptors执行顺序 如果其中一个拦截器preHandle返回false mvc:interceptorsref beaninterceptor1/ref beaninterceptor2/
/mvc:interceptors如果interceptor2的preHandle返回false执行顺序 规则只要有一个拦截器preHandle返回false所有postHandle都不执行。但返回false的拦截器的前面的拦截器按照逆序执行afterCompletion。