当前位置: 首页 > news >正文

建设公司设计公司网站wordpress 小工具 功能

建设公司设计公司网站,wordpress 小工具 功能,昆明seo和网络推广,英文网站设计五、Web服务 基于浏览器的B/S结构应用十分流行。SpringBoot非常适合Web应用开发#xff0c;可以使用嵌入式Tomcat、Jetty、Undertow或Netty创建一个自包含的HTTP服务器。一个SpringBoot的Web应用能够自己独立运行#xff0c;不依赖需要安装的Tomcat、Jetty等。SpringBoot可以…五、Web服务 基于浏览器的B/S结构应用十分流行。SpringBoot非常适合Web应用开发可以使用嵌入式Tomcat、Jetty、Undertow或Netty创建一个自包含的HTTP服务器。一个SpringBoot的Web应用能够自己独立运行不依赖需要安装的Tomcat、Jetty等。SpringBoot可以创建两种类型的Web应用 基于Servlet体系的Spring Web MVC应用使用spring-boot-starter-webflux模块来构建响应式非阻塞的Web应用程序 Spring WebFlux是单独一个体系的内容。Spring Web MVC又被称为SpringMVC专注web应用开发。我们快速的创建控制器Controller接受来自浏览器或其他客户端的请求并将业务代码的结果返回给请求方。 5.1高效构建Web应用 创建Web应用依赖选择spring-web包含了Spring MVC、Tomcat、Thymeleaf视图技术代替jsp、Lombok。项目结构 5.1.1html页面视图 1.Maven依赖 dependencies!--Thymeleaf视图的依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId/dependency!--SpringWeb依赖包含了SpringMVC、Tomcat服务器--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency /dependencies2.创建Controller Controller /*** Controller:创建控制器对象控制器能够浏览器接收请求并响应结果给浏览器控制器也叫处理器*/ public class QuickController {RequestMapping(/exam/quick)public String quick(Model model) {model.addAttribute(title, Web开发);model.addAttribute(time, LocalDateTime.now());return quick;} }3.创建视图 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body div stylemargin-left: 200pxh3视图技术/h3div th:text${title}/divdiv th:text${time}/div /div /body /html4.代码编写完成启动运行类在浏览器访问exam/quick地址 编写SpringMVC的应用分成三步 编写请求页面在浏览器直接模拟的请求编写Controller编写视图技术 5.1.2JSON视图 上面的例子以Html文件作为视图可以编写复杂的交互的页面CSS美化数据。除了带有页面的数据还有一种只需要数据的视图比如手机应用appapp的数据来自服务器应用处理结果。主流的方式是服务器返回json格式数据给手机app应用。我们可以通过原始的HttpServletResponse响应数据给请求方。借助SpringMVC能够无感知的处理json。 1.创建Controller Data public class User {private String username;private Integer age; }Controller public class JSONViewController {//显示JSON视图包含json数据RequestMapping(/exam/json)public void responseJson(HttpServletResponse response) throws IOException {String json {\name\:\lisi\,\age\:20};//响应response.setContentType(application/json;charsetutf-8);PrintWriter out response.getWriter();out.println(json);out.flush();out.close();}//SpringMVC支持控制器方法返回对象由框架将对象使用jackson转为json并输出//User--Jackson工具库的ObjectMapper对象---user转为json格式字符串--HttpServletResponse输出/*** 接收请求的注解** GetMapping:接收get请求简化的RequestMapping(methodRequestMethod.GET)* PostMapping:接收post请求* PutMapping接收put请求* DeleteMapping接收delete请求*/ResponseBody//RequestMapping(/exam/json2)GetMapping(/exam/json2)public User getUserJson() {User user new User();user.setUsername(张三);user.setAge(22);return user;} }注意从Spring6SpringBoot3开始javax包名称修改为jakarta。 2.浏览器测试两个地址 构建前后端分离项目经常采用这种方式。 5.1.3给项目加favicon 什么是favicon.ico? favicon.ico是网站的缩略标志可先显示浏览器标签、地址栏左边和收藏夹是展示网站个性的logo标志。 我们自己的网站定制 logo。首先找一个在线工具创建 favicon.ico。比如 https://quanxin.org/favicon 用文字、图片生成我们需要的内容。生成的 logo 文件名称是 favicon.ico。 1.将生成的favicon.ico拷贝到项目的resources/或resources/static/目录。 2.在你的视图文件加入对favicon.ico的引用 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/titlelink relicon href../favicon.ico typeimage/x-icon/ /head body div stylemargin-left: 200pxh3视图技术/h3div th:text${title}/divdiv th:text${time}/div /div /body /html注意如果项目有过滤器拦截器要放行对favicon.ico的访问。 5.2SpringMVC SpringMVC是非常著名的Web应用框架现在的大多数Web项目都采用SpringMVC。它与Spring有着紧密的联系是Spring框架中的模块专注于Web应用能够使用Spring提供的强大功能IoC、Aop等等。SpringMVC框架底层是基于Servlet技术遵循Servlet规范Web组件Servlet、Filter、Listener在SpringMVC中都能使用。同时SpringMVC也是基于MVC架构的职责分离每个组件只负责自己的功能组件解耦。SpringBoot的自动配置、按约定编程极大简化、提供了Web应用的开发效率 5.2.1控制器Controller 控制器用来处理请求接收浏览器发送过来的参数将数据和视图应答给浏览器或者客户端app等。控制器是一个普通的Bean使用Controller或者RestController注解。 RestController包含了Controller的功能同时加入了ResponseBody的注解表示当前控制器类中的所有方法都会默认加上ResponseBody的功能。Controller注解有Component的功能控制器类对象是Spring容器管理的。 如何创建控制器对象 创建普通Java类其中定义public方法类上注解Controller 或者RestController。 5.2.1.1匹配请求路径到控制器方法 Spring支持多种策略匹配请求路径到控制器方法。SpringBoot3推荐使用PathPatternParser策略比之前AntPathMatcher提高6-8倍吞吐量。吞吐量吞吐量是指单位时间内系统能够完成的工作量它衡量的是软件系统服务器的处理能力就是在一秒中 统计所完成的工作量。 一个系统的吞度量(承压能力)与请求对CPU的消耗、外部接口、IO等等紧密关联。 通配符 ?一个字符*0或多个字符**匹配0个或多个路径 示例 GetMapping(/file/t?st.html) //匹配只有一个字符 //GET http://localhost:8080/file/test.html(对) //GET http://localhost:8080/file/teest.html(错)GetMapping(/file/t?st.html) public String path1(HttpServletRequest request){return path 请求request.getRequestURI(); }GetMapping (/images/*.gif) *匹配一个路径段中的 0 或多个字符 (对) GET http://localhost:8080/images/user.gif (对) GET http://localhost:8080/images/cat.gif (对) GET http://localhost:8080/images/.gif (错) GET http://localhost:8080/images/gif/header.gif (错) GET http://localhost:8080/images/dog.jpgGetMapping (/images/*.gif) public String path2(HttpServletRequest request){return * 请求request.getRequestURI(); }GetMapping (/pic/**) ** 匹配 0 或多段路径 匹配/pic 开始的所有请求 (对) GET http://localhost:8080/pic/p1.gif (对) GET http://localhost:8080/pic/20222/p1.gif (对) GET http://localhost:8080/pic/user (对) GET http://localhost:8080/pic/GetMapping (/pic/**) public String path3(HttpServletRequest request){return /pic/**请求request.getRequestURI(); }RESTFul GetMapping(/order/{*id}) {*id} 匹配 /order 开始的所有请求 id 表示 order 后面直到路径末尾的所有内容。 id 自定义路径变量名称。与PathVariable 一样使用 (对) GET http://localhost:8080/order/1001 (对) GET http://localhost:8080/order/1001/2023-02-16GetMapping(/order/{*id}) public String path4(PathVariable(id) String orderId, HttpServletRequest request){return /order/{*id}请求request.getRequestURI() idorderId; } 注意GetMapping(/order/{*id}/{*date})无效的 {*..}后面不能在有匹配规则了GetMapping(/pages/{fname:\\w}.log) :\\w 正则匹配 xxx.log (对) GET http://localhost:8080/pages/req.log (对) GET http://localhost:8080/pages/111.log (错) GET http://localhost:8080/pages/req.txt (错) GET http://localhost:8080/pages/###.log (错) GET http://localhost:8080/pages/.logGetMapping(/pages/{fname:\\w}.log) public String path5(PathVariable(fname) String filename, HttpServletRequest request){return /pages/{fname:\\w}.log 请求request.getRequestURI() filenamefilename; }5.2.1.2RequestMapping RequestMapping用于将web请求映射到控制器类的方法上。此方法处理请求可用在类上或方法上。重要的属性 value别名path表示请求的uri在类和方法同时使用value方法上的继承类上的value。method请求方式支持GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE。值为RequestMethod[] method() RequestMethod 是 enum 类型。 快捷注解 GetMapping: 表示 get 请求方式的RequestMappingPostMapping:表示 post 请求方式的RequestMappingPutMapping表示 put 请求方式的RequestMappingDeleteMapping: 表示 delete 请求方式的RequestMapping 5.2.1.3控制器方法参数类型与可用返回值类型 参数类型 返回值 5.2.1.4接收请求参数 用户在浏览器中点击按钮时会发送一个请求给服务器其中包含让服务器程序需要做什么的参数。这些参数发送给控制器方法控制器方法的形参列表接收请求参数。 接收参数方式 请求参数与形参一一对应适合简单类型。形参可以有合适的数据类型比如String、Integer、int等。 RestController public class ParameterController {//一一对应适合接收简单类型数据String、int、long、double、float适合接收参数数量少//http://localhost:8080/param/p1?namelisiage20sexmGetMapping(/param/p1)public String p1(String name, Integer age, String sex) {return 接收参数 name , age , sex;} }对象类型控制器方法形参是对象请求的多个参数名与属性名相对应。 Data public class Person {private String name;private Integer age;private String sex; } //使用对象接收参数要求对象的属性名称和请求中参数名不一样属性有set方法类有无参数构造方法 //http://localhost:8080/param/p2?name张三age22typeasd GetMapping(/param/p2) public String p2(Person person, String type) {return 接收参数使用对象 person.toString() ,type type; }HttpServletRequest 使用request对象接收参数 //http://localhost:8080/param/p3?name张三age22sex男 GetMapping(/param/p3) public String p3(HttpServletRequest request) {String name request.getParameter(name);String age request.getParameter(age);String sex request.getParameter(sex);return name name ,age age ,sex sex; }RequestParam注解将查询参数、form表单数据解析到方法参数 //http://localhost:8080/param/p4?name张三age22 GetMapping(/param/p4) public String p4(RequestParam(value name, required true) String name,RequestParam(value age, required false, defaultValue 26) Integer age) {return p4,name name ,age age; }RequestHeader从请求header中获取某项值 //http://localhost:8080/param/p5?name张三age22 //Accept: application/json GetMapping(/param/p5) public String p5(RequestParam(value name, required true) String name,RequestParam(value age, required false, defaultValue 26) Integer age,RequestHeader(Accept) String accept) {return p5,name name ,age age ,Accept: accept; }5.2.1.4.1接收json RequestBody接收前端传递的json格式参数 Data public class User {private String username;private Integer age; }PostMapping(/param/json) public String p6(RequestBody User user) {return p6,json: user.toString(); }IDEA Http Client测试POST http://localhost:8080/param/json Content-Type: application/json{username: lisi,age: 22 }5.2.1.4.2Reader-InputStream Reader或InputStream读取请求体的数据适合post请求体的各种数据。具有广泛性。 PostMapping(/param/json2) public String p6(Reader reader) {StringBuffer content new StringBuffer();try (BufferedReader bin new BufferedReader(reader)) {var line ;while ((line bin.readLine()) ! null) {content.append(line);}} catch (Exception e) {throw new RuntimeException(e);}return p7,reader content.toString(); } IDEA Http Client 测试POST http://localhost:8080/param/json2hello world !!!5.2.1.4.3数组参数接收多个值 数组作为形参接收多个参数值。 GetMapping(/param/vals) public String getMultiVal(Integer [] id){ListInteger idList Arrays.stream(id).toList();return idList.toString(); }测试请求 GET http://localhost:8080/param/vals?id11id12id13 GET http://localhost:8080/param/vals?id11,12,13,14,15 都是成功的方式5.2.1.5验证参数 服务器端程序Controller在方法接受了参数这些参数都是由用户提供的使用之前必须校验参数是我们需要的吗值是否在允许的范围内是否符合业务的要求。比如年龄不能是负数姓名不能是空字符串email必须有符号phone国内的11位才可以。验证参数方案 编写代码手工验证主要是if语句、switch等等。Java Bean ValidationJSR-303是JAVA EE 6中的一项子规范叫做Bean Validation是一个运行时的数据验证规范为JavaBean验证定义了相应的元数据模型和API。 5.2.1.5.1 Java Bean Validation Spring Boot使用Java Bean Validation验证域模型属性值是否符合预期如果验证失败立即返回错误信息。Java Bean Validation将验证规则从controller、service集中到Bean对象一个地方控制所有的验证。Bean的属性上加入JSR-303的注解实现验证规则的定义。 5.2.1.5.2JSR-303注解 Hibernate提供的部分注解 5.2.1.5.3快速上手 验证Blog中的文章信息用户提交文章给Controller控制器使用Java Object接收参数给Bean添加约束注解验证文章数据。 1.添加Bean Validator Starter dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId /dependency2.创建文章数据类添加约束注解 Data public class ArticleVo {private Integer id;NotNull(message 必须有作者)private Integer userId;NotBlank(message 文章必须有标题)//Size 认为 null是有效值。Size(min 3,max 30,message 标题在3个字符以上)private String title;NotBlank(message 必须有副标题)Size(min 5,max 60,message 副标题在5个字以上)private String summary;DecimalMin(value 0,message 阅读数量不能小于0)private Integer readCount;Email(message 邮箱不符合规则)private String email; }3.Controller使用Bean RestController public class ArticleController {//发布新文章/*** Validated:Spring中的注解支持JSR 303规范还能对group验证。可以在类、方法、参数上使用* BindingResult:包含Bean的验证结果*/PostMapping(/article/add)public MapString, Object addArticle(Validated RequestBody ArticleVo article, BindingResult br) {MapString, Object map new HashMap();if (br.hasErrors()) {ListFieldError fieldErrors br.getFieldErrors();for (int i 0, len fieldErrors.size(); i len; i) {FieldError field fieldErrors.get(i);map.put(i - field.getField(), field.getDefaultMessage());}}return map;} }5.2.1.5.4分组校验 上面的ArticleVo用来新增文章新的文章主键id是系统生成的。现在要修改文章比如修改某个文章的titlesummary readCountemail 等。此时id必须有值修改这个id的文章。新增和修改操作对id有不同的约束要求通过group来区分是否验证。 1.添加group标志 Data public class ArticleVo {//组就是接口名public static interface AddArticleGroup {};public static interface EditArticleGroup {};NotNull(message 文章id必须有值, groups {EditArticleGroup.class})Min(value 1, message id大于0, groups {EditArticleGroup.class})private Integer id;NotNull(message 必须有作者, groups {AddArticleGroup.class, EditArticleGroup.class})private Integer userId;NotBlank(message 文章必须有标题, groups {AddArticleGroup.class, EditArticleGroup.class})//Size 认为 null是有效值。Size(min 3, max 30, message 标题在3个字符以上, groups {AddArticleGroup.class, EditArticleGroup.class})private String title;NotBlank(message 必须有副标题, groups {AddArticleGroup.class, EditArticleGroup.class})Size(min 5, max 60, message 副标题在5个字以上, groups {AddArticleGroup.class, EditArticleGroup.class})private String summary;DecimalMin(value 0, message 阅读数量不能小于0, groups {AddArticleGroup.class, EditArticleGroup.class})private Integer readCount;Email(message 邮箱不符合规则, groups {AddArticleGroup.class, EditArticleGroup.class})private String email; }2.修改Controller不同方法增加group标志 RestController public class ArticleController {PostMapping(/article/add)public MapString, Object addArticle(Validated(ArticleVo.AddArticleGroup.class) RequestBody ArticleVo article, BindingResult br) {MapString, Object map new HashMap();if (br.hasErrors()) {ListFieldError fieldErrors br.getFieldErrors();for (int i 0, len fieldErrors.size(); i len; i) {FieldError field fieldErrors.get(i);map.put(i - field.getField(), field.getDefaultMessage());}}return map;}PostMapping(/article/edit)public MapString, Object editArticle(Validated(ArticleVo.EditArticleGroup.class) RequestBody ArticleVo article, BindingResult br) {MapString, Object map new HashMap();if (br.hasErrors()) {ListFieldError fieldErrors br.getFieldErrors();for (int i 0, len fieldErrors.size(); i len; i) {FieldError field fieldErrors.get(i);map.put(i - field.getField(), field.getDefaultMessage());}}return map;} }3.测试代码 POST http://localhost:8080/article/edit Content-Type: application/json{id: 10,userId: 10,title: 云原生,summary: 云原生SpringClod,Linux,readCount: 10,email: abc163.com }5.2.2模型Model 在许多实际项目需求中后台要从控制器直接返回前端所需的数据这时Model大家族就派上用场了。Model指的是Spring MVC中的”M“用来传输数据。从控制器直接返回数据给前端配置jsp模板技术都能够展示M中存储的数据。Model简单理解就是给前端浏览器的数据放在Model中ModelAndView里的任意值还有json格式的字符串都是Model。 RequestMapping(/exam/quick) public String quick(Model model) {model.addAttribute(title, Web开发);model.addAttribute(time, LocalDateTime.now());return quick; }5.2.3视图View SpringMVC中的View视图用来展示数据的。无论使用thymleaf、jsp还是其他技术classpath有jar就能使用视图了。程序员主要就是配置更改Spring Boot3不推荐FreeMarker、jsp这些了。页面的视图技术Thymeleaf、Groovy Templates。org.springframework.web.servlet.View 视图的接口实现此接口的都是视图类视图类作为Bean被Spring管理。 5.2.3.1页面视图 Thymeleaf作为代替jsp的视图技术可以编写页面排列数据。 1.创建Controller控制器方法返回ModelAndView GetMapping(/hello) public ModelAndView hello() {//ModelAndView表示数据和视图ModelAndView mv new ModelAndView();mv.addObject(name, 李四);mv.addObject(age, 20);mv.setViewName(hello);return mv; }2.创建视图在resources/templates创建hello.html !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head bodydiv th:text${name}/div br/div th:text${age}/div br/ /body /htmlapplication.properties默认thymeleaf的设置 #前缀 视图文件存放位置 spring.thymeleaf.prefixclasspath:/templates/ #后缀 视图文件扩展名 spring.thymeleaf.suffix.html3.测试浏览器访问 5.2.3.2JSON视图 在一个类中定义其他多个引用类型或集合类型构成复杂json 1.编写实体类 Data public class User {private String username;private Integer age;private RoleVO roleVO; }Data public class RoleVO {private Integer id;private String roleName;private String memo; }2.增加控制器方法 GetMapping(/json) ResponseBody public User returnJson() {User user new User();user.setUsername(张三);user.setAge(20);RoleVO roleVO new RoleVO();roleVO.setRoleName(管理员);roleVO.setMemo(具有较高的权限);roleVO.setId(10);user.setRoleVO(roleVO);return user; }3.浏览器访问 5.2.3.3ResponseEntity ResponseEntity包含HttpStatus Code和应答数据的结合体。因为有Http Code能表达标准的语义200成功404没有发现等。 1.ResponseEntity做控制器方法返回值 GetMapping(/json3) ResponseBody public ResponseEntityUser returnEntity() {User user new User();user.setUsername(张三);user.setAge(20);RoleVO roleVO new RoleVO();roleVO.setRoleName(管理员);roleVO.setMemo(具有较高的权限);roleVO.setId(10);user.setRoleVO(roleVO);ResponseEntityUser response new ResponseEntity(user, HttpStatus.OK);return response; }2.测试 5.2.3.4Map作为返回值 Map作为返回值是数据能够自动转为json 1.创建Map返回值的方法 GetMapping(/map) ResponseBody public MapString, Object returnMap() {MapString, Object map new HashMap();map.put(name, lisi);map.put(age, 20);return map; }2.测试 5.3SpringMVC请求流程 SpringMVC框架是基于Servlet技术的。以请求为驱动围绕Servlet设计的。SpringMVC处理用户请求与访问一个Servlet是类似的请求发送给Servlet执行doService方法最后响应结果给浏览器完成一次请求处理。 DispatcherServlet是核心对象称为中央调度器。负责接收所有对Controller的请求调用开发者的Controller处理业务逻辑将Controller方法的返回值经过视图处理响应给浏览器。 红色的DispatcherServlet是框架创建的核心对象。蓝色的部分框架已经提供多个对象开发任意可自定义替换默认的对象。绿色的部分是开发人员自己创建的对象控制器Conroller和视图对象。 5.4SpringMVC自动配置 SpringBoot检测classpath上存在的类从而判断当前应用使用的是哪个Servlet Web服务器从而决定定义相应的工厂组件也就是Web服务器。配置类ServerProperties.class配置web server服务器 ConfigurationProperties(prefix server, ignoreUnknownFields true) public class ServerProperties { }application文件配置服务器现在使用tomcat服务器 #配置服务器 #服务器端口号 server.port8081 #上下文访问路径 server.servlet.context-path/api #request、response字符编码 server.servlet.encoding.charsetUTF-8 #强制request、response设置charset字符编码 server.servlet.encoding.forcetrue#配置tomcat服务器的日志 #日志路径 server.tomcat.accesslog.directoryD:/log #启用访问日志 server.tomcat.accesslog.enabledtrue #日志文件名前缀 server.tomcat.accesslog.prefixaccess_log #日志文件日期时间 server.tomcat.accesslog.file-date-format.yyyy-MM-dd #日志文件名称后缀 server.tomcat.accesslog.suffix.log #post 请求内容最大值默认2M server.tomcat.max-http-form-post-size2000000 #服务器最大连接数 server.tomcat.max-connections8192SpringMVC配置 #配置DispatcherServlet spring.mvc.servlet.path/course #Servlet的加载顺序越小越先加载 spring.mvc.servlet.load-on-startup0 #时间格式可以接受请求参数使用 spring.mvc.format.date-timeyyyy-MM-dd HH:mm:ss//测试日期参数GetMapping(/param/date)ResponseBodypublic String paramDate(LocalDateTime date) {return 日期 date;} http://localhost:8081/api/course/param/date?date2203-02-02 12:10:105.5Servlets、Filters、Listeners web应用还会用到Servlet、Filter或Listener。这些对象能够作为Spring Bean注册到嵌入式的Tomcat中。ServletRegistrationBean、FilterRegistrationBean 和ServletListenerRegistrationBean 控制 ServletFilterListener。Order或Ordered接口控制对象的先后顺序。Servlet现在完全支持注解的使用方式WebServlet。 5.5.1Servlets 5.5.1.1WebServlet使用Servlet 1.创建Servlet WebServlet(urlPatterns /helloServlet,name HelloServlet) public class HelloServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType(text/html;charsetutf-8);PrintWriter out response.getWriter();out.println(这是一个SpringBoot中的Servlet);out.flush();out.close();} }2.扫描Servlet注解 //扫描WebServlet注解 ServletComponentScan(basePackages com.hhb.web) SpringBootApplication public class Springboot13ServletFilterApplication {public static void main(String[] args) {SpringApplication.run(Springboot13ServletFilterApplication.class, args);}}3.测试 5.5.1.2ServletRegistrationBean 1.创建Servlet不需要注解 public class LoginServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType(text/html;charsetutf-8);PrintWriter out response.getWriter();out.println(这是一个登录的Servlet);out.flush();out.close();} }2.配置Servlet Configuration public class WebAppConfig {Beanpublic ServletRegistrationBean servletRegistrationBean() {//创建ServletRegistrationBean登录一个或多个ServletServletRegistrationBean bean new ServletRegistrationBean();bean.setServlet(new LoginServlet());bean.addUrlMappings(/user/login);bean.setLoadOnStartup(1);return bean;} }3.测试 5.5.2创建Filter Filter对象使用频率比较高比如记录日志、权限验证、敏感字符过滤等等。Web框架中包含内置的FilterSpringMVC中也包含较多的内置Filter。 5.5.2.1WebFilter注解 WebFilter创建Filter对象使用方式同WebServlet 1.创建过滤器 WebFilter(urlPatterns /*) public class LogFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {String uri ((HttpServletRequest) request).getRequestURI().toString();System.out.println(***LogFilter过滤器执行了uri uri);chain.doFilter(request, response);} }2.扫描包 ServletComponentScan(basePackages com.hhb.web) SpringBootApplication public class Springboot13ServletFilterApplication {public static void main(String[] args) {SpringApplication.run(Springboot13ServletFilterApplication.class, args);} }3.浏览器访问测试 5.5.2.2FilterRegistrationBean FilterRegistrationBean 与 ServletRegistrationBean 使用方式类似无需注解。 注册Filter Bean public FilterRegistrationBean filterRegistrationBean() {FilterRegistrationBean bean new FilterRegistrationBean();bean.setFilter(new LogFilter());bean.addUrlPatterns(/*);return bean; }5.5.2.3Filter排序 多个Filter对象如果要排序有两种途径 过滤器类名称按字典顺序排列,AuthFilter-LogFilterFilterRegistrationBean登记Filter设置order顺序数值越小越先执行。 1.创建两个Filter使用之前的AuthFilter、LogFilter public class LogFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {String uri ((HttpServletRequest) request).getRequestURI().toString();System.out.println(LogFilter过滤器执行了uri uri);chain.doFilter(request, response);} }public class AuthFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {String uri ((HttpServletRequest) request).getRequestURI().toString();System.out.println(AuthFilter过滤器执行了uri uri);chain.doFilter(request, response);} }2.创建配置类登记Filter Bean public FilterRegistrationBean logFilter() {FilterRegistrationBean log new FilterRegistrationBean();log.setFilter(new LogFilter());log.setOrder(1);log.addUrlPatterns(/*);return log; }Bean public FilterRegistrationBean authFilter() {FilterRegistrationBean auth new FilterRegistrationBean();auth.setFilter(new AuthFilter());auth.setOrder(2);auth.addUrlPatterns(/*);return auth; }3.测试Filter 5.5.2.4使用框架中的Filter SpringBoot中有许多已经定义好的Filter这些Filter实现类一些功能如果我们需要使用他们可以像自己的Filter一样通过FilterRegistrationBean注册Filter对象。现在我们想记录每个请求的日志。CommonsRequestLoggingFilter 就能完成简单的请求记录。 1.登记CommonsRequestLoggingFilter Bean public FilterRegistrationBean addOtherFilter() {FilterRegistrationBean filterRegistrationBean new FilterRegistrationBean();//创建Filter对象CommonsRequestLoggingFilter commonLog new CommonsRequestLoggingFilter();//包含请求uricommonLog.setIncludeQueryString(true);//登记FilterfilterRegistrationBean.setFilter(commonLog);//拦截所有地址filterRegistrationBean.addUrlPatterns(/*);return filterRegistrationBean; }2.设置日志级别为debug修改application.properties logging.level.webdebug3.测试访问 5.5.3Listener 创建监听器 WebListener(Listener 的描述说明) public class MySessionListener implements HttpSessionListener {Overridepublic void sessionCreated(HttpSessionEvent se) {HttpSessionListener.super.sessionCreated(se);} }5.6WebMvcConfigurer WebMvcConfigurer作为配置类是采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制就是SpringMVC XML配置文件的JavaConfig编码实现方式。WebMvcConfigurer是一个接口需要自定义某个对象实现接口并覆盖某个方法。主要方法功能介绍一下 public interface WebMvcConfigurer {//帮助配置 HandlerMappingdefault void configurePathMatch(PathMatchConfigurer configurer) {}//处理内容协商default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}//异步请求default void configureAsyncSupport(AsyncSupportConfigurer configurer) {}//配置默认 servletdefault void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}//配置内容转换器default void addFormatters(FormatterRegistry registry) {}//配置拦截器default void addInterceptors(InterceptorRegistry registry) {}//处理静态资源default void addResourceHandlers(ResourceHandlerRegistry registry) {}//配置全局跨域default void addCorsMappings(CorsRegistry registry) {}//配置视图页面跳转default void addViewControllers(ViewControllerRegistry registry) {}//配置视图解析器default void configureViewResolvers(ViewResolverRegistry registry) {}//自定义参数解析器处理请求参数default void addArgumentResolvers(ListHandlerMethodArgumentResolver resolvers) {}//自定义控制器方法返回值处理器default void addReturnValueHandlers(ListHandlerMethodReturnValueHandler handlers) {}//配置 HttpMessageConvertersdefault void configureMessageConverters(ListHttpMessageConverter? converters) {}//配置 HttpMessageConvertersdefault void extendMessageConverters(ListHttpMessageConverter? converters) {}//配置异常处理器default void configureHandlerExceptionResolvers(ListHandlerExceptionResolver resolvers) {}//扩展异常处理器default void extendHandlerExceptionResolvers(ListHandlerExceptionResolver resolvers) {}//JSR303 的自定义验证器default Validator getValidator() {return null;}//消息处理对象default MessageCodesResolver getMessageCodesResolver() {return null;} }5.6.1页面跳转控制器 SpringBoot中使用页面视图比如Thymeleaf。要跳转显示某个页面必须通过Controller对象。也就是我们需要创建一个Controller转发到一个视图才行。如果我们现在需要显示页面可以无需这个Controller。addViewControllers()完成从请求到视图跳转。 项目代码结构 1.创建视图 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body h3欢迎/h3 /body /html2.创建SpringMVC配置类 //SpringMVC配置使用JavaConfig的方式配置SpringMVC代替原来的xml配置文件 Configuration public class MvcSettings implements WebMvcConfigurer {//页面跳转控制器从请求直达视图页面无需controllerOverridepublic void addViewControllers(ViewControllerRegistry registry) {//配置页面的控制addViewController(请求uri).setViewName(目标视图)registry.addViewController(/welcome).setViewName(index);} }3.测试功能 5.6.2数据格式化 Formatter是数据转换接口将一种数据类型转换为另一种数据类型。与Formatter功能类似的还有ConverterST。本章研究Formatter接口。 Formatter只能将String类型转换为其他数据类型这点在Web应用适用更广因为Web请求的所有参数都是String我们需要把String转为Integer、Long、Date等等。 Spring中内置了一些Formatter DateFormatterString和Date之间的解析与格式化InetAddressFormatterString和InetAddress之间的解析与格式化PercentStyleFormatterString与Number之间的解析与格式化带货币符号NumberFormatString和Number之间的解析与格式化 接口原型 public interface FormatterT extends PrinterT, ParserT {}Formatter是一个组合接口没有自己的方法。内容来自Printer和 ParserPrinter将T类型转换为String格式化输出Parser将String类型转为期望的T对象 需求将“11112222333,NF4561”接收代码中用DeviceInfo存储参数值 1.创建DeviceInfo数据类 Data public class DeviceInfo {private String item1;private String item2;private String item3;private String item4;private String item5; }2.自定义Formatter //将请求参数String转为DeviceInfo public class DeviceFormatter implements FormatterDeviceInfo {//text表示请求参数的值Overridepublic DeviceInfo parse(String text, Locale locale) throws ParseException {DeviceInfo info null;if (StringUtils.hasLength(text)) {String[] items text.split(;);info new DeviceInfo();info.setItem1(items[0]);info.setItem2(items[1]);info.setItem3(items[2]);info.setItem4(items[3]);info.setItem5(items[4]);}return info;}Overridepublic String print(DeviceInfo object, Locale locale) {StringJoiner joiner new StringJoiner(#);joiner.add(object.getItem1()).add(object.getItem2()).add(object.getItem3()).add(object.getItem4()).add(object.getItem5());return joiner.toString();} }3.登记自定义的DeviceFormatter //转换器 Override public void addFormatters(FormatterRegistry registry) {registry.addFormatter(new DeviceFormatter()); }4.新建Controller接收请求设备数据 RestController public class DeviceController {PostMapping(/device/add)public String addDeviceInfo(RequestParam(device) DeviceInfo info){return 接收的设备信息info.toString();} }5.单元测试 POST http://localhost:8080/device/add Content-Type: application/x-www-form-urlencodeddevice1111;2222;333,NF;4;5615.6.3拦截器 HandlerInterceptor接口和它的实现类称为拦截器是SpringMVC的一种对象。拦截器是SpringMVC框架的对象与Servlet无关。拦截器能够预先处理发给Controller的请求可以决定请求是否被Controller处理。用户请求是先由DispatcherServlet接收后在Controller之前执行的拦截器对象。一个项目中有众多的拦截器框架中预定义的拦截器自定义拦截器。下面我们说说自定义拦截器的应用。拦截器定义步骤 声明类实现HandlerInterceptor接口重写三个方法需要哪个重写哪个登记拦截器 5.6.3.1一个拦截器 需求zhangsan操作员用户只能查看文章不能修改删除。 1.创建文章的Controller RestController public class ArticleController {PostMapping(/article/add)public String addArticle() {return 发布新的文章;}PostMapping(/article/edit)public String editArticle() {return 修改文章;}DeleteMapping(/article/remove)public String removeArticle() {return 删除文章;}GetMapping(/article/query)public String queryArticle() {return 查询文章;} }2.创建有关的权限拦截器 public class AuthInterceptor implements HandlerInterceptor {public static final String COMMON_USER zhangsan;//判断登录的用户能否执行相应的动作Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(AuthInterceptor权限拦截器);//登录的用户String loginUser request.getParameter(loginUser);//获取请求的uri地址String requestURI request.getRequestURI();//判断用户和操作if (COMMON_USER.equals(loginUser) (requestURI.startsWith(/article/add) ||requestURI.startsWith(/article/edit) ||requestURI.startsWith(/article/remove))) {return false;}return true;} }3.登记拦截器 //拦截器 Override public void addInterceptors(InterceptorRegistry registry) {//权限拦截器AuthInterceptor authInterceptor new AuthInterceptor();registry.addInterceptor(authInterceptor).addPathPatterns(/article/**)//拦截以article开头的所有请求.excludePathPatterns(/article/query);//不拦截的地址 }4.测试拦截器 ### POST http://localhost:8080/article/add Content-Type: application/x-www-form-urlencodedloginUserzhangsantitleVue### GET http://localhost:8080/article/query Content-Type: application/x-www-form-urlencodedloginUserzhangsantitleVue5.6.3.2多个拦截器 增加一个验证登录用户的拦截器只有zhangsanlisiadmin能够登录系统。其他用户不可以。两个拦截器登录的拦截器先执行权限拦截器后执行order()方法设置顺序整数值越小先执行。 1.创建登录拦截器 public class LoginInterceptor implements HandlerInterceptor {private ListString permitUser new ArrayList();public LoginInterceptor() {this.permitUser Arrays.asList(zhangsan, lisi, admin);}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println(LoginInterceptor执行了);//获取登录的用户名称String loginUser request.getParameter(loginUser);//只有三个用户能够访问系统if (StringUtils.hasText(loginUser) permitUser.contains(loginUser)) {return true;}return false;} }2.登记拦截器设置顺序order //拦截器 Override public void addInterceptors(InterceptorRegistry registry) {//权限拦截器AuthInterceptor authInterceptor new AuthInterceptor();registry.addInterceptor(authInterceptor).order(2).addPathPatterns(/article/**)//拦截以article开头的所有请求.excludePathPatterns(/article/query);//不拦截的地址//登录拦截器LoginInterceptor loginInterceptor new LoginInterceptor();registry.addInterceptor(loginInterceptor).order(1)//顺序整数值越小越先执行.addPathPatterns(/**)//拦截所有对controller的请求.excludePathPatterns(/article/query);//排除 }5.7文件上传 SpringBoot上传文件现在变得非常简单提供了封装好的处理上传文件的接口MultipartResolver用于解析上传文件的请求。MultipartFile表示上传的文件提供了方便的方法保存文件到磁盘。 MultipartFile API 方法作用getName()参数名称getOriginalFilename()上传文件原始名称isEmpty()上传文件是否为空getSize()上传的文件字节大小getInputStream()文件的InputStream可用于读取部件的内容transferTo(File dest)保存上传文件到目标dest 5.7.1MultipartResolver 1.服务器创建目录存放上传后的文件 例如在 D:/upload 2.创建index.html作为上传后的显示页面 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body h3文件上传成功/h3 /body /html3.创建上传文件页面 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body div stylemargin-left: 200pxh3文件上传/h3form actionuploadFile enctypemultipart/form-data methodpost选择文件input typefile nameupfilebrinput typesubmit value上传/form /div /body /html要求 enctype“multipart/form-data”method“post”表示一个上传文件upfile自定义上传文件参数名称 4.创建Controller package com.hhb.upload.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile;import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID;Controller public class UploadFileController {//上传文件PostMapping(/uploadFile)public String uploadFile(RequestParam(upfile) MultipartFile multipartFile) throws IOException {System.out.println(开始处理上传文件);MapString, Object info new HashMap();if (!multipartFile.isEmpty()) {info.put(上传文件的参数名称, multipartFile.getName());info.put(内容类型, multipartFile.getContentType());var ext unknown;//原始文件名称例如a.gifvar filename multipartFile.getOriginalFilename();//indexOf(.) 判断.第一次出现的位置if (filename.indexOf(.) 0) {//截取.之后的字符ext filename.substring(filename.indexOf(.) 1);}//生成服务器使用的文件名称var newFileName UUID.randomUUID().toString() . ext;//存储服务器的文件var path D://upload// newFileName;//把文件保存到path目录multipartFile.transferTo(new File(path));info.put(文件名称, newFileName);}System.out.println(info info);//重定向到index页面防止刷新避免重复上传return redirect:/index.html;} }5.测试 浏览器访问 http://localhost:8080/upload.html 文件上传查看 D:/upload 目录上传的文件 SpringBoot默认单个文件最大支持1MB一次请求最大10MB改变默认值需要application修改配置项。 #一次请求最大支持5MB spring.servlet.multipart.max-request-size5MB #单个文件最大支持100KB spring.servlet.multipart.max-file-size100KB #超过指定大小直接写文件到磁盘不再内存处理 spring.servlet.multipart.file-size-threshold0KB配置错误页面**(规定格式)** resources/static/error/5xx.html !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body h3文件上传错误/h3 /body /html5.7.2Servlet规范 Servlet3.0规范中定义了jakarta.servlet.http.Part接口处理multipart/form-data POST请求中接收到表单数据。有了Part对象其write()方法将上传文件保存到服务器本地磁盘目录。在HttpServletRequest接口中引入的新方法 getParts():返回Part对象的集合。getPart(字符串名称):检索具有给定名称的单个Part对象。 原生的Servlet规范的文件上传 Controller public class UploadAction {PostMapping(/files)public String upload(HttpServletRequest request) throws ServletException, IOException {for (Part part : request.getParts()) {String filename extractFileName(part);//将文件写入服务器的目录part.write(filename);}return redirect:/index.html;}private String extractFileName(Part part) {String contentDisp part.getHeader(content-disposition);System.out.println(contentDisp contentDisp);String[] items contentDisp.split(;);for (String s : items) {if (s.trim().startsWith(filename)) {return s.substring(s.indexOf() 2, s.length() - 1);}}return ;} }application文件配置服务器存储文件位置 spring.servlet.multipart.locationD://upload5.7.3多文件上传 多文件上传在接收文件参数部分有所改变MultiPartFile [] files。循环遍历数组解析每个上传的文件。 前端请求页面 !DOCTYPE html html langen body div stylemargin-left: 200pxh3文件上传/h3form actionfile enctypemultipart/form-data methodpost选择文件-1:input typefile nameupfile br/ br/选择文件-2:input typefile nameupfile br/ br/选择文件-3:input typefile nameupfile br/ br/input typesubmit value上传/form /div /body /html5.8全局异常处理 在Controller处理请求过程中发生了异常DispatcherServlet将异常处理委托给异常处理器处理异常的类实现HandlerExceptionResolver接口的都是异常处理类。项目中的异常一般都是集中处理定义全局异常处理器。再结合框架提供的注解例如ExceptionHandler、ControllerAdvice、RestControllerAdvice一起完成异常的处理。ControllerAdvice与RestControllerAdvice区别在于RestControllerAdvice加入了ResponseBody。 5.8.1全局异常处理器 1.创建输入数字的页面 在static目录下创建input.html,static目录下的资源浏览器可以直接访问。 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body form actiondivide methodpost除nbsp;nbsp;数:input typetext namen1br被除数:input typetext namen2brinput typesubmit value计算 /form /body /html2.创建控制器计算两个整数相除 RestController public class NumberController {PostMapping(/divide)public String some(Integer n1, Integer n2) {int res n1 / n2;return n1/n2 res;} }3.浏览器访问input.html计算两个数字相除 显示默认错误页面 4.创建自定义异常处理器 /*** 1.在类的上面加ControllerAdvice、RestControllerAdvice灵活组合* 2.在类中自定义方法处理各种异常。方法定义同Controller类中的方法的定义*/ //控制器增强给Controller增加异常处理功能类似AOP的思想 ControllerAdvice public class GlobalExceptionHandler {//定义方法处理数学异常/*** ExceptionHandler:指定处理异常的方法 位置在方法的上面* 属性是异常类的class数组如果你的系统抛出的异常类型与ExceptionHandler声明的相同由当前方法处理异常*//*ExceptionHandler({ArithmeticException.class})public String handlerArithmeticException(ArithmeticException e, Model model) {String error e.getMessage();model.addAttribute(error, error);return exp;//视图}*///不带视图直接返回数据ExceptionHandler({ArithmeticException.class})ResponseBodypublic MapString, String handlerReturnDataException(ArithmeticException e) {MapString, String error new HashMap();error.put(msg, e.getMessage());error.put(tips, 被除数不能为0);return error;} } 5.创建错误提示页面 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body h3显示异常的信息:div th:text${error}/div /h3 /body /html再测试显示提示页面 5.8.2BeanValidator异常处理 使用JSR-303验证参数时我们是在Controller方法声明BindingResult对象获取校验结果。Controller的方法很多每个方法都加入BindingResult处理检验参数比较繁琐。校验参数失败抛出异常给框架异常处理器能够捕获到MethodArgumentNotValidException它是BindException的子类。BindException异常实现了BindingResult接口异常类能够得到BindingResult对象进一步获取JSR303校验的异常信息。 1.添加JSR-303依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId /dependency2.创建Bean对象属性加入JSR-303注解 Data public class OrderVO {NotBlank(message 订单名称不能为空)private String name;NotNull(message 商品必须有数量)Range(min 1, max 99, message 一个订单的商品数量在{min}--{max})private Integer amount;NotNull(message 用户不能为空)Min(value 1, message 从1开始)private Integer userId; }3.Controller接收请求 RestController public class OrderController {PostMapping(/order/new)public String createOrder(Validated RequestBody OrderVO orderVO) {return 订单信息 orderVO.toString();} }4.创建异常处理器 ControllerAdvice public class GlobalExceptionHandler {//处理JSR303 验证参数的异常//ExceptionHandler({BindException.class})ExceptionHandler({MethodArgumentNotValidException.class})ResponseBodypublic MapString, Object handlerJSR303Exception(MethodArgumentNotValidException e) {System.out.println(**********JSR303**********);MapString, Object map new HashMap();BindingResult result e.getBindingResult();if (result.hasErrors()) {ListFieldError errors result.getFieldErrors();for (int i 0, len errors.size(); i len; i) {FieldError field errors.get(i);map.put(field.getField(), field.getDefaultMessage());}}return map;} }5.测试 POST http://localhost:8080/order/new Content-Type: application/json{name: ,amount: 0,userId: 10 }5.8.3ProblemDetail[SpringBoot3] 一直以来SpringBoot默认的异常反馈内容比较单一包含Http Status Code、时间、异常信息。但具体异常原因没有体现这次SpringBoot3对错误信息增强了。 5.8.3.1 RFC 7807 ”Problem Details“ 的 JSON 应答格式 { type: https://example.com/probs/out-of-credit, title: You do not have enough credit., detail: Your current balance is 30, but that costs 50., instance: /account/12345/transactions/abc }”Problem Details“ 包含内容 标准字段描述是否必须type标识错误类型的URI。在浏览器中加载这个URI应该转向这个错误的文档。默认为 about:blank可认为是title问题类型的简单描述否datail错误信息详细描述否instance标识该特定故障实例的URI它可以作为发生的这个错误的ID否status错误使用的HTTP状态代码它必须与实际状态匹配否 … 5.8.3.2MediaType RFC 7807增加了两种媒体类型application/problemjson或application/problemxml。返回错误的HTTP响应应在其Content-Type响应标头中包含适当的内容类型并且客户端可以检查该标头以确认格式。 5.8.3.3Spring支持Problem Detail 5.8.3.4自定义异常处理器ProblemDetail 需求我们示例查询某个isbn的图书。在application.yml中配置图书的初始数据用户访问一个api地址查询某个isbn的图书查询不到抛出自定义异常BootNotFoundException自定义异常处理器捕获异常。ProblemDeatil作为应答结果支持RFC 7807。 1.新建图书的Record普通的POJO类都是可以的 public record BookRecord(String isbn,String name,String author) { }2.创建存储多本图书的容器类 Setter Getter ConfigurationProperties(prefix product) //将数据存入到BookContainer public class BookContainer {private ListBookRecord books; }3.application.yml配置图书基础数据 #指定初始的book数据代替数据库 product:books:- isbn: B001name: javaauthor: lisi- isbn: B002name: tomcatauthor: zhangsan- isbn: B003name: jvmauthor: wangwu#访问路径 server:servlet:context-path: /api 4.新建自定义异常类 public class BookNotFoundException extends RuntimeException {public BookNotFoundException() {super();}public BookNotFoundException(String message) {super(message);} }5.新建控制器类 RestController public class BookController {//注入BookContainerAutowiredprivate BookContainer bookContainer;//根据isbn查询图书如果没有查到抛出异常GetMapping(/book)public BookRecord getBook(String isbn) {OptionalBookRecord bookRecord bookContainer.getBooks().stream().filter(el -el.isbn().equals(isbn)).findFirst();if (bookRecord.isEmpty()) {throw new BookNotFoundException( isbn : isbn -没有此图书);}return bookRecord.get();} }6.新建异常处理器 RestControllerAdvice public class GlobalExceptionHandler {//定义的ProblemDetailExceptionHandler({BookNotFoundException.class})public ProblemDetail handlerBookNotFoundException(BookNotFoundException e) {//ProblemDetailProblemDetail problemDetail ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());//type:异常类型是一个uriuri找到解决问题的途径problemDetail.setType(URI.create(/api/probs/not-found));problemDetail.setTitle(图书异常);//增加自定义的字段problemDetail.setProperty(时间, Instant.now());problemDetail.setProperty(客服, 362619368qq.com);return problemDetail;} }7.测试接口 5.8.3.5ErrorResponse SpringBoot识别ErrorResponse类型作为异常的应答结果。可以直接使用ErrorResponse作为异常处理方法的返回值。 修改异常处理器GlobalExceptionHandler RestControllerAdvice public class GlobalExceptionHandler {//返回ErrorResponseExceptionHandler({BookNotFoundException.class})public ErrorResponse handlerException(BookNotFoundException e) {ErrorResponseException error new ErrorResponseException(HttpStatus.NOT_FOUND, e);return error;} }测试接口 5.8.3.6扩展ErrorResponseException 自定义异常可以扩展ErrorResponseExceptionSpringMVC将处理异常以符合RFC7807的格式返回错误响应。 1.创建新的异常类继承ErrorResponseException //自定义异常类让SpringMVC的异常处理器使用 public class IsbnNotFoundException extends ErrorResponseException {public IsbnNotFoundException(HttpStatus httpStatus, String detail) {super(httpStatus, createProblemDetail(httpStatus, detail), null);}private static ProblemDetail createProblemDetail(HttpStatus status, String detail) {//封装RFC7807字段ProblemDetail problemDetail ProblemDetail.forStatus(status);problemDetail.setType(URI.create(/api/probs/not-found));problemDetail.setTitle(图书异常);problemDetail.setDetail(detail);//自定义字段problemDetail.setProperty(严重程度, 低);problemDetail.setProperty(客服邮箱, 36261968qq.com);return problemDetail;} }2.抛出IsbnNotFoundException RestController public class BookController {//注入BookContainerAutowiredprivate BookContainer bookContainer;//根据isbn查询图书如果没有查到抛出异常GetMapping(/book)public BookRecord getBook(String isbn) {OptionalBookRecord bookRecord bookContainer.getBooks().stream().filter(el -el.isbn().equals(isbn)).findFirst();if (bookRecord.isEmpty()) {//throw new BookNotFoundException( isbn : isbn -没有此图书);throw new IsbnNotFoundException(HttpStatus.NOT_FOUND, isbn : isbn -没有此图书);}return bookRecord.get();} }3.启动RFC7807支持修改application.yml增加配置 spring:mvc:problemdetails:enabled: true4.测试接口
http://www.huolong8.cn/news/65616/

相关文章:

  • 网站设计程序微商手机网站制作
  • 铜山网站开发有哪些可以在线做海报的网站
  • 做网站送白酒简单网站建设方案
  • 长沙做网站一般多少钱wordpress插件 七牛
  • 贴心的广州网站建设做响应式网站哪家公司好
  • 互联网金融网站设计大庆建设网站首页
  • 网站多大需要服务器哪个网站有工笔教程
  • 网站 手机版网站建设先有域名然后呢
  • 全栈工程师是做网站吗上海网站排名提升
  • 网站开发设计培训价格阿丰 做网站
  • 做网站广告多少钱邹平网站建设优化公司
  • 昆明网站优化公司银川公司做网站
  • 大连城乡住房建设厅网站昭通昭阳区城乡建设管理局网站
  • 关于平面设计的网站班级建设网站
  • 网站选项卡图标代码wordpress数据调用
  • 商家入驻网站开发wordpress算数的插件
  • e盒印网站开发网站开发网页
  • 西樵网站制作给个免费的网站好人有好报
  • 免费建立自己的个人网站全球商业网
  • linux建站和wordpress建站佛山网站定制
  • 邳州哪家做百度推广网站零食店网站构建策划报告
  • 手袋 东莞网站建设wordpress 自媒体插件
  • 怎么看网站备案深圳燃气公司地址在哪里
  • 网站模版 优帮云themeforest wordpress
  • 网站开发保密协议 doc网站开发模板图片
  • 南通小企业网站建设简历模板电子版
  • 网站建设公司的政策风险网钛cms做的网站
  • 建设网站的app荆州论坛
  • 设计类参考网站推荐管理wordpress
  • wordpress建立网站吗企业网站网页设计的步骤