工厂网站怎么做,seo营销推广,潍坊哪里可以做网站,为何上不了建设银行网站SpringMVC技术与servlet技术功能等同#xff0c;均属于web层开发技术
SpringMVC简介
SpringMVC概述
SpringMVC是一种基于Java实现MIVC模型的轻量级web框架
优点
使用简单#xff0c;开发便捷#xff08;相比于servlet)灵活性强
SpringMVC是一种表现层框架技术
Spring…SpringMVC技术与servlet技术功能等同均属于web层开发技术
SpringMVC简介
SpringMVC概述
SpringMVC是一种基于Java实现MIVC模型的轻量级web框架
优点
使用简单开发便捷相比于servlet)灵活性强
SpringMVC是一种表现层框架技术
SpringMVC用于进行表现层功能开发
SpringMVC入门案例
①使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标
?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns: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.itheima/groupIdartifactIdspringmvc_01_quickstart/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingpropertiesmaven.compiler.source11/maven.compiler.sourcemaven.compiler.target11/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!--1.导入坐标springmvc和servlet--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.2.10.RELEASE/version/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.1/versionconfigurationport8080/portpath//path/configuration/plugin/plugins/build/project
②创建SpringMVC控制器类等同于Servlet功能
package com.example.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;// 2.定义controller
// 2.1使用Controller定义bean
Controller
public class UserController {// 2.2设置当前操作的访问路径RequestMapping(/save)// 2.3设置当前操作的返回值类型ResponseBodypublic String save() {System.out.println(user save ...);return {info:springmvc};}
}
③初始化SpringMVC环境同Spring环境设定SpringMVC加载对应的bean
package com.example.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;// 3.创建springmvc的配置文件加载controller对应的bean
Configuration
ComponentScan(com.example.controller)
public class SpringMVCConfig {
}④初始化Servlet容器加载SpringMVC环境并设置SpringMVC技术处理的请求
package com.example.config;import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;// 4.定义一个servlet容器启动的配置类在里面加载spring的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {//加载springmvc配置类产生springmvc容器本质还是spring容器protected WebApplicationContext createServletApplicationContext() {//初始化WebApplicationContext对象AnnotationConfigWebApplicationContext ctx new AnnotationConfigWebApplicationContext();//加载指定配置类ctx.register(SpringMVCConfig.class);return ctx;}//设置由springmvc控制器处理的请求映射路径protected String[] getServletMappings() {return new String[]{/};}//加载spring配置类protected WebApplicationContext createRootApplicationContext() {return null;}
}
注解
名称Controller
类型类注解
位置SpringMVC控制器类定义上方
作用设定SpringMVC的核心控制器bean
范例
Controller
public class UserController {
}名称RequestMapping
类型方法注解
位置SpringMVC控制器方法定义上方
作用设置当前控制器方法请求访问路径
范例 RequestMapping(/save)public String save() {System.out.println(user save ...);return {info:springmvc};}相关属性
value默认请求访问路径
名称ResponseBody
类型方法注解
位置SpringMVC控制器方法定义上方
作用设置当前控制器方法响应内容为当前返回值无需解析
范例
// 2.定义controller
// 2.1使用Controller定义bean
Controller
public class UserController {// 2.2设置当前操作的访问路径RequestMapping(/save)// 2.3设置当前操作的返回值类型ResponseBodypublic String save() {System.out.println(user save ...);return {info:springmvc};}
}AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类 AbstractDispatcherServletInitializer提供三个接口方法供用户实现 createServletApplicationContext()方法创建Servlet容器时加载SpringMVC对应的bean并放入WebApplicationContext对象范围中而WebApplicationContext的作用范围为ServletContext范围即整个web容器范围createRootApplicationContext()方法如果创建Servlet容器时需要加载非SpringMVC对应的bean使用当前方法进行使用方式同createServletApplicationContext()getServletMappings()方法设定SpringMVC对应的请求映射路径设置为/表示拦截所有请求任意请求都将转入到SpringMVC进行处理 入门案例工作流程分析
启动服务器初始化过程
服务器启动执行ServletContainersInitConfig类初始化web容器执行createServletApplicationContext方法创建了WebApplicationContext对象加载SpringMvcConfig执行ComponentScan加载对应的bean加载UserController每个RequestMapping的名称对应一个具体的方法执行getServletMappings方法定义所有的请求都通过SpringMVC
单次请求过程
发送请求localhost/saveweb容器发现所有请求都经过SpringMVC将请求交给SpringMVC处理解析请求路径/save由/save匹配执行对应的方法save(执行save()检测到有ResponseBody直接将save()方法的返回值作为响应求体返回给请求方
bean加载控制
SpringMVC加载其相关bean(表现层bean),也就是controller包下的类
Spring控制的bean
业务bean(Service)功能bean(DataSource,SqlSessionFactoryBean,MapperScannerConfigurer等)
如何让Spring和SpringMVC分开加载各自的内容。
因为功能不同如何避免Spring错误加载到SpringMVC的bean?
方式一:Spring加载的bean设定扫描范围为com.itheima,排除掉controller包中的bean
Configuration
ComponentScan(valuecom.itheima,excludeFiltersComponentScan.Filter(type FilterType.ANNOTATION,classes Controller.class)
)
public class SpringConfig {
}excludeFilters属性设置扫描加载bean时排除的过滤规则
type属性设置排除规则当前使用按照bean定义时的注解类型进行排除
ANNOTATION按照注解排除
ASSIGNABLE_TYPE:按照指定的类型过滤
ASPECTJ:按照Aspectj表达式排除基本上不会用
REGEX:按照正则表达式排除
CUSTOM:按照自定义规则排除
classes属性设置排除的具体注解类当前设置排除Controller定义的bean
方式二:Spring加载的bean设定扫描范围为精准范围例如service包、dao包等
Configuration
ComponentScan({com.itheima.service,comitheima.dao})
public class SpringConfig {
}方式三:不区分Spring与SpringMVC的环境加载到同一个环境中[了解即可]
PostMan
Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件
作用常用于进行接口测试
特征
简单实用美观大方
请求与响应
请求映射路径 名称RequestMapping 类型方法注解 类注解 位置SpringMVC控制器方法定义上方 作用设置当前控制器方法请求访问路径如果设置在类上统一设置当前控制器方法请求访问路径前缀 范例 import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起形成完整的请求映射路径
RequestMapping(/user)
public class UserController {//请求路径映射RequestMapping(/save)ResponseBodypublic String save(){System.out.println(user save ...);return {module:user save};}//请求路径映射RequestMapping(/delete)ResponseBodypublic String delete(){System.out.println(user delete ...);return {module:user delete};}}属性 value默认请求访问路径或访问路径前缀
请求参数
Controller
public class UserController {//请求路径映射RequestMapping(/commonParam)ResponseBodypublic String commonParam(String name,int age) {System.out.println(name:name,age:age);return {user:common param};}}GET请求
选择GET。
postman中直接输入
http://localhost:8080/commonParam?namefaizage555点击send
运行结果
name:faiz,age:555POST请求
选择POST。
在postman中输入
http://localhost:8080/commonParam下面选择body,再选择x-www-form-urlencoded
再KEY和VALUE下分别添加
name faiz
age 555点击send运行结果为
name:faiz,age:555Post请求中文乱码处理:
为web容器添加过滤器并指定字符集Spring-web包中提供了专用的字符过滤器
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;import javax.servlet.Filter;public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {protected Class?[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}protected String[] getServletMappings() {return new String[]{/};}protected Class?[] getRootConfigClasses() {return new Class[0];}// 乱码处理Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter new CharacterEncodingFilter();filter.setEncoding(UTF-8);return new Filter[]{filter};}
}普通参数
普通参数url地址传参地址参数名与形参变量名相同定义形参即可接收参数请求参数名与形参变量名不同使用RequestParam绑定参数关系
Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起形成完整的请求映射路径
//RequestMapping(/user)
public class UserController {//请求路径映射RequestMapping(/commonParam)ResponseBodypublic String commonParam(RequestParam(name2) String name,int age) {System.out.println(name:name,age:age);return {user:common param};}}POJO参数
POJO参数请求参数名与形参对象属性名相同定义POJO类型形参即可接收参数
package com.itheima.domain;public class User {String name;int age;public User(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}Overridepublic String toString() {return User{ name name \ , age age };}
}
package com.itheima.controller;import com.itheima.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起形成完整的请求映射路径
//RequestMapping(/user)
public class UserController {//请求路径映射RequestMapping(/commonParam)ResponseBodypublic String commonParam(User user) {System.out.println(user:user);return {user:common param};}}
http://localhost:8080/commonParam?namefaizage555运行结果为
user:User{namefaiz, age555}嵌套POJO参数
嵌套POJO参数POJO对象中包含POJO对象
package com.itheima.domain;public class Address {String province;String city;public String getProvince() {return province;}public void setProvince(String province) {this.province province;}public String getCity() {return city;}public void setCity(String city) {this.city city;}Overridepublic String toString() {return Address{ province province \ , city city \ };}
}package com.itheima.domain;public class User {String name;int age;Address address;public Address getAddress() {return address;}public void setAddress(Address address) {this.address address;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}Overridepublic String toString() {return User{ name name \ , age age , address address };}
}
嵌套POJO参数请求参数名与形参对象属性名相同按照对象层次结构关系即可接收嵌套POJO属性参数
package com.itheima.controller;import com.itheima.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;Controller
//类上方配置的请求映射与方法上面配置的请求映射连接在一起形成完整的请求映射路径
//RequestMapping(/user)
public class UserController {//请求路径映射RequestMapping(/commonParam)ResponseBodypublic String commonParam(User user) {System.out.println(user:user);return {user:common param};}}http://localhost:8080/commonParam?namefaizage555address.citysyaddress.provincehn运行结果为
user:User{namefaiz, age555, addressAddress{provincehn, citysy}}数组参数
数组参数请求参数名与形参对象属性名相同且请求参数为多个定义数组类型形参即可接收参数
Controller
public class UserController {//请求路径映射RequestMapping(/param)ResponseBodypublic String param(String[] names) {System.out.println(names: Arrays.toString(names));return {user:common param};}}
http://localhost:8080/param?namesfaiznameswxmnamestdzs运行结果为
names:[faiz, wxm, tdzs]集合保存普通参数
集合保存普通参数请求参数名与形参集合对象名相同且请求参数为多个RequestParam绑定参数关系
Controller
public class UserController {//请求路径映射RequestMapping(/param)ResponseBodypublic String param(RequestParam ListString names) {System.out.println(names: names);return {user:common param};}}http://localhost:8080/param?namesfaiznameswxmnamestdzs运行结果为
names:[faiz, wxm, tdzs]接收请求中的json数据
添加json数据转换相关坐标 dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.13.4/version/dependency设置发送json数据请求body中添加json数据 再postman中选择Body再选择raw再选择JSON 开启自动转换json数据的支持
Configuration
ComponentScan(com.itheima.controller)
EnableWebMvc // 这里
public class SpringMvcConfig {
}设置接收json数据
Controller
public class UserController {//请求路径映射RequestMapping(/param)ResponseBodypublic String param(RequestBody ListString names) {System.out.println(names: names);return {user:common param};}}
在postman中输入
[aa,bb,cc,dd]点击send,结果为
names:[aa, bb, cc, dd]RequestBody与RequestParam区别 区别 RequestParam用于接收url地址传参表单传参【application/x-www-form-urlencoded】 RequestBody用于接收json数据【application/json】 应用 后期开发中发送json格式数据为主RequestBody应用较广 如果发送非json格式数据选用RequestParam接收请求参数
日期类型参数传递 日期类型数据基于系统不同格式也不尽相同 2088-08-18 2088/08/18 08/18/2088 接收形参时根据不同的日期格式设置不同的接收方式
Controller
public class UserController {//请求路径映射RequestMapping(/param)ResponseBodypublic String param(Date date,DateTimeFormat(pattern yyyy-MM-dd) Date date1,DateTimeFormat(pattern yyyy/MM/dd HH:mm:ss) Date date2) {System.out.println(date: date);System.out.println(date1: date1);System.out.println(date2: date2);return {user:common param};}}
http://localhost:8080/param?date2023/07/22date12023-07-21date22023/07/22 09:33:55运行结果为
date:Sat Jul 22 00:00:00 GMT08:00 2023
date1:Fri Jul 21 00:00:00 GMT08:00 2023
date2:Sat Jul 22 09:33:55 GMT08:00 2023响应
响应页面了解
Controller
RequestMapping(/book)
public class BookController {//请求路径映射RequestMapping(index)public String index(){System.out.println(index);return /book.jsp;}
}响应文本数据了解
Controller
RequestMapping(/book)
public class BookController {RequestMapping(text)ResponseBodypublic String text(){System.out.println(text);return Hello World;}
}响应json数据对象转json
Controller
RequestMapping(/book)
public class BookController {//请求路径映射RequestMapping(index)public String index(){System.out.println(index);return /book.jsp;}RequestMapping(text)ResponseBodypublic String text(){System.out.println(text);return Hello World;}RequestMapping(pojo)ResponseBodypublic User pojo(){User user new User();user.setName(faiz);user.setAge(18);return user;}
}http://localhost:8080/book/pojo运行结果
{name: faiz,age: 18,address: null
}响应json数据对象集合转json数组
Controller
RequestMapping(/book)
public class BookController {//请求路径映射RequestMapping(list)ResponseBodypublic ListUser list(){User user new User();user.setName(faiz);user.setAge(18);User user2 new User();user2.setName(faiz);user2.setAge(18);ListUser list new ArrayList();list.add(user);list.add(user2);return list;}
}http://localhost:8080/book/list运行结果为
[{name: faiz,age: 18,address: null},{name: faiz,age: 18,address: null}
]名称ResponseBody
类型方法注解
位置SpringMVC控制器方法定义上方
作用设置当前控制器返回值作为响应体
REST风格
REST简介
RESTRepresentational State Transfer表现形式状态转换 传统风格资源描述形式 http://localhost/user/getById?id1 http://localhost/user/saveUser REST风格描述形式 http://localhost/user/1 http://localhost/user
优点
隐藏资源的访问行为无法通过地址得知对资源是何种操作书写简化
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
http://localhost/users 查询全部用户信息 GET查询http://localhost/users/1 查询指定用户信息 GET查询http://localhost/users 添加用户信息 POST新增/保存http://localhost/users 修改用户信息 PUT修改/更新http://localhost/users/1 删除用户信息 DELETE删除
根据REST风格对资源进行访问称为RESTful
RESTful入门案例
package com.itheima.controller;import com.itheima.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;Controller
public class UserController {//请求路径映射RequestMapping(value /users,method RequestMethod.POST)ResponseBodypublic String save(){System.out.println(user save ...);return {module:user save};}//请求路径映射RequestMapping(value /users/{id},method RequestMethod.DELETE)ResponseBodypublic String delete(PathVariable Integer id){System.out.println(user delete ...id);return {module:user delete};}//请求路径映射RequestMapping(value /users,method RequestMethod.PUT)ResponseBodypublic String update(RequestBody User user){System.out.println(user update ...user);return {module:user update};}//请求路径映射RequestMapping(value /users/{id},method RequestMethod.GET)ResponseBodypublic String getById(PathVariable Integer id){System.out.println(user getById ...id);return {module:user getById};}}
RequestMapping
名称RequestMapping
类型方法注解
位置SpringMVC控制器方法定义上方
作用设置当前控制器方法请求访问路径
属性
value默认请求访问路径methodhttp请求动作标准动作GET/POST/PUT/DELETE
PathVariable
名称PathVariable
类型形参注解
位置SpringMVC控制器方法形参定义前面
作用绑定路径参数与处理器方法形参间的关系要求路径参数名与形参名一一对应
RequestBody RequestParam PathVariable
区别 RequestParam用于接收url地址传参或表单传参RequestBody用于接收json数据PathVariable用于接收路径参数使用{参数名称}描述路径参数 应用 后期开发中发送请求参数超过1个时以json格式为主RequestBody应用较广如果发送非json格式数据选用RequestParam接收请求参数采用RESTful进行开发当参数数量较少时例如1个可以采用PathVariable接收请求路径变量通常用于传递id值
REST快速开发
//Controller
//ResponseBody
RestController
RequestMapping(users)
public class UserController {//请求路径映射
// RequestMapping(method RequestMethod.POST)PostMappingpublic String save(){System.out.println(user save ...);return {module:user save};}//请求路径映射
// RequestMapping(value /{id},method RequestMethod.DELETE)DeleteMapping(/{id})public String delete(PathVariable Integer id){System.out.println(user delete ...id);return {module:user delete};}//请求路径映射
// RequestMapping(method RequestMethod.PUT)PutMappingpublic String update(RequestBody User user){System.out.println(user update ...user);return {module:user update};}//请求路径映射
// RequestMapping(value /{id},method RequestMethod.GET)GetMapping(/{id})public String getById(PathVariable Integer id){System.out.println(user getById ...id);return {module:user getById};}}RestController
名称RestController
类型类注解
位置基于SpringMVC的RESTful开发控制器类定义上方
作用设置当前控制器类为RESTful风格等同于Controller与ResponseBody两个注解组合功能
GetMapping PostMapping PutMapping DeleteMapping
名称GetMapping PostMapping PutMapping DeleteMapping
类型方法注解
位置基于SpringMVC的RESTful开发控制器方法定义上方
作用设置当前控制器方法请求访问路径与请求动作每种对应一个请求动作例如GetMapping对应GET请求
属性
value默认请求访问路径
设置对静态资源的访问放行
Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {//当访问/pages/????时候走/pages目录下的内容registry.addResourceHandler(/pages/**).addResourceLocations(/pages/);registry.addResourceHandler(/js/**).addResourceLocations(/js/);registry.addResourceHandler(/css/**).addResourceLocations(/css/);registry.addResourceHandler(/plugins/**).addResourceLocations(/plugins/);}
}
SSM整合
SSM整合
SSM整合流程
1.创建工程
2.SSM整合
Spring SpringConfig MyBatis MybatisconfigJdbcConfigjdbc.properties SpringMVC servletConfigSpringMvcConfig
3.功能模块
表与实体类dao(接口自动代理)service(接口实现类) 业务层接口测试整合JUnit ) controller 表现层接口测试PostMan )
表现层数据封装
表现层数据封装
设置统一数据返回结果类
package org.example.controller;public class Result {private Object data;private Integer code;private String msg;public Result() {}public Result(Integer code, Object data) {this.data data;this.code code;}public Result(Integer code, Object data, String msg) {this.data data;this.code code;this.msg msg;}public Object getData() {return data;}public void setData(Object data) {this.data data;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg msg;}
} 注意事项 Result类中的字段并不是固定的可以根据需要自行增减提供若干个构造方法方便操作 设置统一数据返回结果编码
package org.example.controller;public class Code {public static final Integer SAVE_OK 20011;public static final Integer DELETE_OK 20021;public static final Integer UPDATE_OK 20031;public static final Integer GET_OK 20041;public static final Integer SAVE_ERR 20010;public static final Integer DELETE_ERR 20020;public static final Integer UPDATE_ERR 20030;public static final Integer GET_ERR 20040;
} 注意事项 Code类的常量设计也不是固定的可以根据需要自行增减例如将查询再进行细分为GET_OKGET_All_OKGET_PAGE_OK 根据情况设定合理的Result
package org.example.controller;import org.example.domain.Book;
import org.example.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;RestController
RequestMapping(/books)
public class BookController {Autowiredprivate BookService bookService;PostMappingpublic Result save(RequestBody Book book) {boolean flag bookService.save(book);return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);}PutMappingpublic Result update(RequestBody Book book) {boolean flag bookService.update(book);return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);}DeleteMapping(/{id})public Result delete(PathVariable Integer id) {boolean flag bookService.delete(id);return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);}GetMapping(/{id})public Result getById(PathVariable Integer id) {Book book bookService.getById(id);Integer code book ! null ? Code.GET_OK : Code.GET_ERR;String msg book ! null ? : 数据查询失败请重试;return new Result(code,book,msg);}GetMappingpublic Result getAll() {ListBook bookList bookService.getAll();Integer code bookList ! null ? Code.GET_OK : Code.GET_ERR;String msg bookList ! null ? : 数据查询失败请重试;return new Result(code,bookList,msg);}
}异常处理器
出现异常现象的常见位置与常见诱因如下:
框架内部抛出的异常:因使用不合规导致数据层抛出的异常:因外部服务器故障导致例如:服务器访问超时)业务层抛出的异常:因业务逻辑书写错误导致例如:遍历业务书写操作导致索引异常等)表现层抛出的异常:因数据收集、校验等规则导致例如:不匹配的数据类型间导致异常)工具类抛出的异常:因工具类书写不严谨不够健壮导致例如:必要释放的连接长期未释放等) 各个层级均出现异常异常处理代码书写在哪一层? 所有的异常均抛出到表现层进行处理 表现层处理异常每个方法中单独书写代码书写量巨大且意义不强如何解决——AOP思想 异常处理器
集中的、统一的处理项目中出现的异常
在controller下新建一个类
package org.example.controller;import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;RestControllerAdvice
public class ProjectExceptionAdvice {ExceptionHandler(Exception.class)public Result doException(Exception e) {System.out.println(异常:e);return new Result(555,null,e.toString());}
}
项目异常处理方案
项目异常分类
业务异常(BusinessException) 规范的用户行为产生的异常不规范的用户行为操作产生的异常 系统异常(SystemException) 项目运行过程中可预计且无法避免的异常 其他异常(Exception) 编程人员未预期到的异常
项目异常处理方案
业务异常(BusinessException) 发送对应消息传递给用户提醒规范操作 系统异常(SystemException) 发送固定消息传递给用户安抚用户发送特定消息给运维人员提醒维护记录日志 其他异常(Exception) 发送固定消息传递给用户安抚用户发送特定消息给编程人员提醒维护(纳入预期范围内)记录日志
自定义项目系统级异常
package org.example.exception;public class SystemException extends RuntimeException{private Integer code;public SystemException(String message, Integer code) {super(message);this.code code;}public SystemException(String message, Throwable cause, Integer code) {super(message, cause);this.code code;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code code;}
}
自定义项目业务级异常
package org.example.exception;public class BusinessException extends RuntimeException{private Integer code;public BusinessException(String message, Integer code) {super(message);this.code code;}public BusinessException(String message, Throwable cause, Integer code) {super(message, cause);this.code code;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code code;}
}自定义异常编码持续补充)
package org.example.controller;public class Code {public static final Integer SAVE_OK 20011;public static final Integer DELETE_OK 20021;public static final Integer UPDATE_OK 20031;public static final Integer GET_OK 20041;public static final Integer SAVE_ERR 20010;public static final Integer DELETE_ERR 20020;public static final Integer UPDATE_ERR 20030;public static final Integer GET_ERR 20040;public static final Integer BUSINESS_ERR 60002;public static final Integer BUSINESS_UNKNOWN_ERR 59999;public static final Integer SYSTEM_ERR 50002;
}
触发自定义异常
package org.example.service.impl;import org.example.controller.Code;
import org.example.dao.BookDao;
import org.example.domain.Book;
import org.example.exception.BusinessException;
import org.example.exception.SystemException;
import org.example.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;Service
public class BookServiceImpl implements BookService {Autowiredprivate BookDao bookDao;Overridepublic boolean save(Book book) {bookDao.save(book);return true;}Overridepublic boolean update(Book book) {bookDao.update(book);return true;}Overridepublic boolean delete(Integer id) {bookDao.delete(id);return true;}// 这里Overridepublic Book getById(Integer id) {// 将可能出现的异常进行包装,转换成自定义异常if (id 0) {throw new BusinessException(请输入规范的id, Code.BUSINESS_ERR);}try {int i 1/0;} catch (Exception e) {throw new SystemException(服务器访问超时请重试,e,Code.SYSTEM_ERR);}return bookDao.getById(id);}Overridepublic ListBook getAll() {return bookDao.getAll();}
}
拦截并处理异常
package org.example.controller;import org.example.exception.BusinessException;
import org.example.exception.SystemException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;RestControllerAdvice
public class ProjectExceptionAdvice {ExceptionHandler(SystemException.class)public Result doSystemException(SystemException e) {// 记录日志// 发送消息给运维// 发送邮件给开发人员,e对象发给return new Result(e.getCode(),null,e.getMessage());}ExceptionHandler(BusinessException.class)public Result doSystemException(BusinessException e) {return new Result(e.getCode(),null,e.getMessage());}ExceptionHandler(Exception.class)public Result doException(Exception e) {System.out.println(异常:e);return new Result(Code.BUSINESS_UNKNOWN_ERR,null,系统繁忙请稍后再试);}
}拦截器
拦截器概念
拦截器(Interceptor )是一种动态拦截方法调用的机制在SpringMVC中动态拦截控制器方法的执行
作用:
在指定的方法调用前后执行预先设定后的的代码阻止原始方法的执行
拦截器与过滤器区别
归属不同:Filter属于Servlet技术Interceptor属于SpringMVC技术拦截内容不同:Filter对所有访问进行增强Interceptor仅针对SpringMVC的访问进行增强
入门案例
声明拦截器的bean并实现HandlerInterceptor接口注意:扫描加载bean)
package org.example.controller.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;Component
public class ProjectInceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(preHandle...);// false终止原始操作的执行return true;}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println(postHandle...);}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println(afterCompletion...);}
}定义配置类继承WebMvcConfigurationSupport实现addInterceptor方法注意:扫描加载配置)
Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {Overrideprotected void addInterceptors(InterceptorRegistry registry) {}
}
添加拦截器并设定拦截的访问路径路径可以通过可变参数设置多个
package org.example.config;import org.example.controller.interceptor.ProjectInceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {Autowiredprivate ProjectInceptor projectInceptor;Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/pages/**).addResourceLocations(/pages/);registry.addResourceHandler(/css/**).addResourceLocations(/css/);registry.addResourceHandler(/js/**).addResourceLocations(/js/);registry.addResourceHandler(/plugins/**).addResourceLocations(/plugins/);}Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(projectInceptor).addPathPatterns(/books,/books/*);}
}使用标准接口webMvcConfigurer简化开发注意:侵入式较强)
package org.example.config;import org.example.controller.interceptor.ProjectInceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;Configuration
ComponentScan({org.example.controller})
EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {Autowiredprivate ProjectInceptor projectInceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(projectInceptor).addPathPatterns(/books,/books/*);}}拦截器执行流程 拦截器参数
前置处理 Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String contentType request.getHeader(Content-Type);System.out.println(handler:handler handler.getClass():handler.getClass());HandlerMethod hm (HandlerMethod) handler;System.out.println(preHandle...contentType);// false终止原始操作的执行return true;}参数
request:请求对象response:响应对象handler:被调用的处理器对象本质上是一个方法对象对反射技术中的Method对象进行了再包装
返回值
若返回值为false被拦截的处理器将不执行
后置处理 Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println(postHandle...);}参数
modelAndView:如果处理器执行完成具有返回结果可以读取到对应数据与页面信息并进行调整
完成后处理 Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println(afterCompletion...);}参数
ex:如果处理器执行过程中出现异常对象可以针对异常情况进行单独处理
拦截器链配置
多拦截器执行顺序
当配置多个拦截器时形成拦截器链拦截器链的运行顺序参照拦截器添加顺序为准当拦截器中出现对原始处理器的拦截后面的拦截器均终止运行当拦截器运行中断仅运行配置在前面的拦截器的afterCompletion操作