一.SpringMVC简介和体验
(一)先容
(二)创建SpringMVC项目
1.创建Maven项目
2.导入依赖
- <properties>
- <spring.version>6.0.6</spring.version>
- <servlet.api>9.1.0</servlet.api>
- <maven.compiler.source>17</maven.compiler.source>
- <maven.compiler.target>17</maven.compiler.target>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <!-- springioc相关依赖 -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <!-- web相关依赖 -->
- <!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 -->
- <!--
- 在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用
- Jakarta EE 提供的相应类库和命名空间。错误信息 “‘org.springframework.web.servlet.DispatcherServlet’
- is not assignable to ‘javax.servlet.Servlet,jakarta.servlet.Servlet’” 表明你使用了旧版本的
- Servlet API,没有更新到 Jakarta EE 规范。
- -->
- <dependency>
- <groupId>jakarta.platform</groupId>
- <artifactId>jakarta.jakartaee-web-api</artifactId>
- <version>${servlet.api}</version>
- <scope>provided</scope>
- </dependency>
- <!-- springwebmvc相关依赖 -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${spring.version}</version>
- </dependency>
- </dependencies>
复制代码 3.转成maven/web步调
用jbljavatoweb插件将Java项目转换为Web项目
webapp出现蓝点代表乐成转成maven/web步调
4.controller声明
handler就是controller内部的具体方法
- @Controller
- public class HelloController {
- @RequestMapping("springmvc/hello")//对外访问的地址 到handlerMapping注册的注解
- @ResponseBody//直接返回字符串给前端,不去找视图解析器
- public String hello() {
- System.out.println("hello,springmvc");
- return "hello springmvc!";
- }
- }
复制代码 5.Spring MVC焦点组件设置类
声明springmvc涉及组件信息的设置类
(1)controller设置ioc容器
(2).handlerMapping handlerAdapter加入到ioc容器
- @Configuration
- @ComponentScan("com.yan.controller")
- public class MvcConfig {
- @Bean
- public RequestMappingHandlerMapping handlerMapping() {
- return new RequestMappingHandlerMapping();
- }
- @Bean
- public RequestMappingHandlerAdapter handlerAdapter(){
- return new RequestMappingHandlerAdapter();
- }
- }
复制代码 6.SpringMVC情况搭建
本类可以被web项目加载,会初始化ioc容器,会设置dispatcherServlet的地址
- public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
- /**
- * 指定service / mapper层的配置类
- */
- @Override
- protected Class<?>[] getRootConfigClasses() {
- return null;
- }
- /**
- * 指定springmvc的配置类
- *
- * @return
- */
- @Override
- protected Class<?>[] getServletConfigClasses() {
- return new Class<?>[]{MvcConfig.class};
- }
- /**
- * 设置dispatcherServlet的处理路径!
- * 一般情况下为 / 代表处理所有请求!
- */
- @Override
- protected String[] getServletMappings() {
- return new String[]{"/"};
- }
- }
复制代码 7将攻击部署在tomcat上,启动测试
(三)WebApplicationInitializer接口
每当web项目启动,就会自动调用WebApplicationInitializer接口的onStartup方法AbstractAnnotationConfigDispatcherServletInitializer, 用于 DispatcherServlet 初始化 (实现了WebApplicationInitializer接口),该基类既要完成 WebApplicationInitializer 接口中设置servlet容器的功能,又完成了设置MVC的功能,即同时设置了 DispatcherServlet 和 ContextLoaderListener 。
二.SpringMVC接收数据
(一)访问路径设置
@RequestMapping注解的作用就是将哀求的 URL 地址和处理哀求的方式(handler方法)关联起来,建立映射关系。
@WebServlet:必须用/开头
@RequestMapping:不必利用/开头
1.精准路径
精准地址可以有一个或多个
@RequestMapping(value = {"/user/register"})
2.含糊路径
/* 为单层恣意字符串,只能匹配URL地址中的一层,如果想正确匹配两层,那么就写“/*/*”以此类推
/** 为恣意层恣意字符串,可以匹配URL地址中的多层。
3.类和方法级别区别
(1)设置到类级别
类上提取通用的访问地址
(2)设置到方法级别
方法上是具体的handler地址
访问:类地址+方法地址即可
4.哀求方式指定
- public enum RequestMethod {
- GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
- }
复制代码 (1)默认情况下:
@RequestMapping("/logout")
只要地址精确,任何哀求方式都可以访问!
(2)指定哀求方式下:
@RequestMapping(value = "regist", method = {RequestMethod.GET})
不符合哀求方式会出现405异常
5.进阶注解
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
进阶注解只能添加到handler方法上,无法添加到类上!
(二)接收参数
1.param和json参数比较
(1)参数编码
param类型:ASCII码
JSON类型:UTF-8
(2)参数顺序
param参数没有顺序限定,但是JSON类型的参数是有序的,JSON采用键值对形式
(3)数据类型
param类型的参数支持字符串类型,数组类型和布尔类型等简单类型
JSON适合更复杂的格式
(4)可读性
param类型参数更简单,易读但是JSON格式在传递嵌套数据结构更勤洗易懂
2.param参数接收
(1)直接接值
-形参列表填写对应名称的参数即可 哀求参数名=形参参数名
-可以不给形参传递值
- @RequestMapping("data")
- @ResponseBody
- public String data(String name, int age) {
- System.out.println("name=" + name + ",age" + age);
- return "name = " + name + "age = " + age;
- }
复制代码 (2)@RequestParam注解
可以利用 @RequestParam 解释将 Servlet 哀求参数(即查询参数或表单数据)绑定到控制器中的方法参数。
@RequestParam(
value="指定哀求参数,如果形参名和参数名同等,可以省略",
required=false 前端是否必须传递,默认为必须,不传报错400异常,
defaultValue="1" 当非必须传递时,可以设置默认值)
利用场景
-指定绑定的哀求参数名
-要求哀求参数必须传递
-为哀求参数提供默认值
- @RequestMapping("data1")
- @ResponseBody
- public String data1(@RequestParam(value = "account") String username, @RequestParam(required = false, defaultValue = "1") int page) {
- return "username = " + username + " , page= " + page;
- }
复制代码 (3)特殊场景接值
-一名多值
多选框,提交的数据的时间一个key对应多个值,我们可以利用集合进行接收!
不加@RequestParam将hbs对应的一个字符赋值给集合,类型异常
加了注解,HandlerAdapter用集合的add方法加入字符串
- //hbs=吃&hbs=玩&hbs=打
- @GetMapping("data2")
- @ResponseBody
- public String data2(@RequestParam List<String> hbs) {
- System.out.println("hbs=" + hbs);
- return "ok";
- }
复制代码 -实体接收
可以在方法内部直接利用对象的属性来访问哀求参数,要求声明实体类属性名等于哀求参数名
- @Data
- public class User {
- private String name;
- private int age;
- }
复制代码- @RequestMapping("data3")
- @ResponseBody
- public String data3(User user) {
- System.out.println(user);
- return user.toString();
- }
复制代码
3.路径参数接收
Spring MVC 框架提供了 @PathVariable 注解来处理路径传递参数。
@PathVariable 注解允许将 URL 中的占位符映射到控制器方法中的参数
-动态路径设计: /user/{动态部分}/{动态部分} 动态部分利用{}包罗即可! {}内部动态标识!
-形参列表取值:
@PathVariable Long id 如果形参名 = {动态标识} 自动赋值!
@PathVariable("动态标识") Long id 如果形参名 != {动态标识} 可以通过指定动态标识赋值!
- @RequestMapping("{account}/{password}")
- public String login(@PathVariable(value = "account", required = true) String username, @PathVariable String password) {
- return username+password;
- }
复制代码 4.JSON参数接收
界说一个用于接收 JSON 数据的 Java 类
- @Data
- public class Person {
- private String name;
- private int age;
- private String gender;
- }
复制代码 在控制器中,利用 @RequestBody 注解来接收 JSON 数据,并将其转换为 Java 对象,例如:
- @RequestMapping("json")
- @Controller
- @ResponseBody
- public class JsonController {
- @PostMapping("data")
- public String data(@RequestBody Person person) {
- System.out.println("person:" + person);
- return person.toString();
- }
- }
复制代码 测试:
原因:
Java原生的api只支持路径参数和param参数,不支持json
json是前端格式
解决:导入json处理的依赖 ,handlerAdopter设置json转换器
利用此注解@EnableWebMvc加入json处理器
- @EnableWebMvc //handlerAdopter 配置json转换器
- @Configuration
- @ComponentScan("com.yan")
- public class MvcConfig {
- @Bean
- public RequestMappingHandlerMapping handlerMapping() {
- return new RequestMappingHandlerMapping();
- }
- @Bean
- public RequestMappingHandlerAdapter handlerAdapter(){
- return new RequestMappingHandlerAdapter();
- }
- }
复制代码 pom.xml 加入jackson依赖
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.15.0</version>
- </dependency>
复制代码 @EnableWebMvc注解说明
添加 HandlerMapping,HandlerAdapter,给HandlerAdapter添加jacksonJson处理器
(三)接收Cookie数据
- @Controller
- @RequestMapping("cookie")
- @ResponseBody
- public class CookieController {
- @RequestMapping("data")
- public String data(@CookieValue(value = "cookieName") String value) {
- System.out.println("value=" + value);
- return value;
- }
- @GetMapping("save")
- public String save(HttpServletResponse response){
- Cookie cookie = new Cookie("cookieName", "root");
- response.addCookie(cookie);
- return "ok";
- }
- }
复制代码 (四)接收哀求头数据
- @Controller
- @RequestMapping("header")
- @ResponseBody
- public class HeaderController {
- @GetMapping("data")
- public String data(@RequestHeader("Host") String host) {
- System.out.println("host = " + host);
- return "host = " + host;
- }
- }
复制代码 (五)原生Api对象获取
想要获取哀求或者相应对象,或者会话等,可以直接在形参列表传入,而且不分先后顺序!
举例:
获取ServletContext和HttpSession对象
- @GetMapping("api")
- public String getApi(HttpServletRequest req, HttpServletResponse resp, HttpSession httpSession){
- ServletContext servletContext = req.getServletContext();
- return null;
- }
复制代码 springmvc会在初始化容器的时间,将servletContext对象存储到ioc容器中,也可以用@Autowired注解自动装配servletContext对象
三.SpringMVC相应数据
(一)转发和重定向
1.方法的返回值都是String
2.不加responseBody注解
3.返回字符串前面 redirect:/重定向地址 forward:/哀求转发地址
转发和重定向都一样,都是项目下路径!转到项目内的资源都不需要添加项目根路径!
转发只能向项目下的资源跳转
重定向可以是项目下的资源也可以是项目外的资源,重定向到项目外的资源如百度网址
redirect:http://www.baidu.com
- @GetMapping("forward")
- public String forward() {
- return "forward:/index";
- }
- @GetMapping("redirect")
- public String redirect() {
- return "redirect:/jsp/index";
- }
复制代码
(二)返回JSON数据
1.前置准备
(1)导入json依赖
(2)@EnableWebMvc
2.@ResponseBody注解
@RestController =@Controller + @ResponseBody
以是利用了 @RestController 注解就相当于给类中的每个方法都加了 @ResponseBody 注解。
如果类中每个方法上都标志了 @ResponseBody 注解,那么这些注解就可以提取到类上。
- @RequestMapping("json")
- @Controller
- @ResponseBody
- public class JsonController {
- @GetMapping("data")
- public User data() {
- User user = new User();
- user.setName("two dogs");
- user.setAge(2);
- return user;
- }
- @GetMapping("data2")
- public List<User> data1() {
- User user = new User();
- user.setName("two dogs");
- user.setAge(2);
- List<User> users = new ArrayList<>();
- users.add(user);
- return users;
- }
- }
复制代码 (三)返回静态资源
1.原因
对 SpringMVC 来说,必须有对应的 @RequestMapping 才气找随处理哀求的方法
现在 images/photo.jpg 哀求没有对应的 @RequestMapping 以是返回 404
2.问题解决
在 SpringMVC 设置设置类:
- @EnableWebMvc // 配置json转换器
- @Configuration
- @ComponentScan("com.yan")
- public class MvcConfig implements WebMvcConfigurer {
- //开启静态资源处理
- @Override
- public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- configurer.enable();
- }
- }
复制代码 四.RESTful风格设计和实践
(一)哀求方式要求
GET用来获取资源
POST用来新建资源(也可以用于更新资源)
PUT用来更新资源
DELETE用来删除资源
(二)路径要求
利用URL+哀求方式确定具体的动作,handler的地址+哀求方式都相同才是重复
通用原则:
- 路径参数应该用于指定资源的唯一标识或者 ID,而哀求参数应该用于指定查询条件或者操作参数。
- 哀求参数应该限定在 10 个以内,过多的哀求参数可能导致接口难以维护和利用。
- 对于敏感信息,最好利用 POST 和哀求体来传递参数。
(三)接口设计
为什么查询用户详情,就利用路径传递参数,多条件含糊查询,就利用哀求参数传递?
-对于查询用户详情,利用路径传递参数是因为这是一个单一资源的查询,即查询一条用户记录。利用路径参数可以明确指定所哀求的资源,便于服务器定位并返回对应的资源,也符合 RESTful 风格的要求。
-而对于多条件含糊查询,利用哀求参数传递参数是因为这是一个资源集合的查询,即查询多条用户记录。利用哀求参数可以通过组合差别参数来限定查询结果,路径参数的组合和分列可能会很多,不如利用哀求参数更加灵活和简便。
(四)代码实现
- public class User {
- private Integer id;
- private String name;
- private Integer age;
- }
复制代码- @RestController
- @RequestMapping("user")
- public class UserController {
- @GetMapping
- public List<User> page(@RequestParam(required = false, defaultValue = "1") int page,
- @RequestParam(required = false, defaultValue = "10") int size) {
- System.out.println("page=" + page + "size" + size);
- return null;
- }
- @PostMapping
- public User save(@RequestBody User user) {
- return user;
- }
- @GetMapping("{id}")
- public User detail(@PathVariable Integer id) {
- return null;
- }
- @PutMapping
- public User update(@RequestBody User user) {
- return user;
- }
- @DeleteMapping("{id}")
- public User delete(@PathVariable Integer id) {
- return null;
- }
- @GetMapping("search")
- public List<User> search(String keywork,
- @RequestParam(required = false, defaultValue = "1") int page,
- @RequestParam(required = false, defaultValue = "10") int size) {
- return null;
- }
- }
复制代码 五.SpringMVC扩展
(一)全局异常处理机制
声明式异常处理:则是将异常处理的逻辑从具体的业务逻辑中分离出来,通过设置等方式进行统一的管理和处理。
1.声明异常处理控制器类
@ControllerAdvice 代表当前类的异常处理controller!
@RestControllerAdvice=@ControllerAdvice+@ResponseBody
2.声明异常处理hander方法
@ExceptionHandler(HttpMessageNotReadableException.class)
该注解标志异常处理Handler,而且指定发生异常调用该方法!指定的异常,可以精准查找,找不到才查找父异常
3.设置文件扫描控制器类设置
确保异常处理控制类被扫描
- @RestControllerAdvice
- public class GlobalExceptionHandler {
- @ExceptionHandler(ArithmeticException.class)
- public Object ArithmeticExceptionHandler(ArithmeticException e) {
- //自定义处理异常即可
- String message = e.getMessage();
- return message;
- }
- @ExceptionHandler(Exception.class)
- public Object ExceptionHandler(Exception e) {
- String message = e.getMessage();
- return message;
- }
- }
复制代码 (二)拦截器的利用
1.创建拦截器类
- public class MyInterceptor implements HandlerInterceptor {
- /**
- * 执行handeler之前,调用的拦截方法
- *
- * @param request
- * @param response
- * @param handler 我们要调用的方法的对象
- * @return
- * @throws Exception
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- return true;
- }
- /**
- * 当handler执行完毕后触发的方法,没有拦截机制
- *
- * @param request
- * @param response
- * @param handler
- * @param modelAndView 返回的视图和共享域数据对象
- * @throws Exception
- */
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- }
- /**
- * 整体处理完毕
- *
- * @param request
- * @param response
- * @param handler
- * @param ex 报错了异常对象
- * @throws Exception
- */
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- }
- }
复制代码 2.修改设置类添加拦截器
- @Configuration
- @ComponentScan("com.yan")
- @EnableWebMvc
- public class MvcConfig implements WebMvcConfigurer {
- //添加拦截器
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new MyInterceptor());
- }
- }
复制代码 3.设置详解
a.默认拦截全部
- @Configuration
- @ComponentScan("com.yan")
- @EnableWebMvc
- public class MvcConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new MyInterceptor());
-
- }
- }
复制代码 b.精准设置
设置拦截器处理指定哀求 路径可以设置一个或者多个,为项目下路径即可
也支持 /* 和 /** 含糊路径。 * 恣意一层字符串 ** 恣意层 恣意字符串
- @Configuration
- @ComponentScan("com.yan")
- @EnableWebMvc
- public class MvcConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new MyInterceptor())
- .addPathPatterns("/user/data");
- }
- }
复制代码 c.排除设置
排除匹配,排除应该在匹配的范围内排除
- @Configuration
- @ComponentScan("com.yan")
- @EnableWebMvc
- public class MvcConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new MyInterceptor())
- .addPathPatterns("/user/**").excludePathPatterns("/user/data");
- }
- }
复制代码 4.多个拦截器的执行顺序
preHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照设置顺序调用各个 preHandle() 方法。
postHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照设置相反的顺序调用各个 postHandle() 方法。
afterCompletion() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照设置相反的顺序调用各个 afterCompletion() 方法。
(三)参数校验
1.导入依赖
- <!-- 校验注解 -->
- <dependency>
- <groupId>jakarta.platform</groupId>
- <artifactId>jakarta.jakartaee-web-api</artifactId>
- <version>9.1.0</version>
- <scope>provided</scope>
- </dependency>
-
- <!-- 校验注解实现-->
- <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
- <dependency>
- <groupId>org.hibernate.validator</groupId>
- <artifactId>hibernate-validator</artifactId>
- <version>8.0.0.Final</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
- <dependency>
- <groupId>org.hibernate.validator</groupId>
- <artifactId>hibernate-validator-annotation-processor</artifactId>
- <version>8.0.0.Final</version>
- </dependency>
复制代码 2.创建实体类,为其添加校验对象
要求:
(1)name 不为null且不为空 字符串
@NotBlank 集合 @NotEmpty 包装 @NotNull
(2)password长度大于6
(3)age必须>=1
(4)email 邮箱格式字符串
(5)birthday 过去时间
- public class User {
- @NotBlank
- private String name;
- @Length(min = 6)//标注值字符串大小必须在指定的范围内
- private String password;
- @Min(1) //标注值必须大于或等于 value
- private int age;
- @Email //标注值必须是格式正确的 Email 地址
- private String email;
- @Past //标注值只能用于日期型,且必须是过去的日期
- private Date birthday;
- }
复制代码 3.handler(@Validated 实体类 对象)
要接收json,还要加上@RequestBody 注解
- @RequestMapping("user")
- @RestController
- public class UserController {
- @GetMapping
- public User regist(@Validated @RequestBody User user){
- return user;
- }
- }
复制代码 测试:
4.handler标志和绑定错误收集
捕捉绑定错误信息
在实体类参数和 BindingResult 之间不能有任何其他参数
BindingResult可以接受错误信息,避免信息抛出
- @GetMapping
- public Object regist(@Validated @RequestBody User user, BindingResult result) {
- if (result.hasErrors()) {
- Map data = new HashMap();
- data.put("code", 400);
- data.put("msg", "参数校验异常");
- return data;
- }
- return user;
- }
复制代码 测试:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |