笔记参考柏码知识库
基本配置-全注解配置形式 创建Web应用程序。
创建Servlet容器初始化类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class MainInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class []{WebConfiguration.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class [0 ]; } @Override protected String[] getServletMappings() { return new String []{"/" }; } }
配置类中添加注解:
1 2 3 4 5 @Configuration @EnableWebMvc @ComponentScan("com.example.controller") public class WebConfiguration { }
创建Controller类:
1 2 3 4 5 6 7 8 @Controller public class HelloController { @ResponseBody @RequestMapping("/") public String hello () { return "HelloWorld!" ; } }
Controller控制器 使用DispatcherServlet替代Tomcat提供的默认的静态资源Servlet。
配置视图解析器和控制器 导入Thymeleaf依赖:
1 2 3 4 5 <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring6</artifactId > <version > 3.1.1.RELEASE</version > </dependency >
需要将对应的ViewResolver注册为Bean来配置视图解析器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Configuration @EnableWebMvc @ComponentScan("com.example.controller") public class WebConfiguration { @Bean public ThymeleafViewResolver thymeleafViewResolver (SpringTemplateEngine springTemplateEngine) { ThymeleafViewResolver resolver = new ThymeleafViewResolver (); resolver.setOrder(1 ); resolver.setCharacterEncoding("UTF-8" ); resolver.setTemplateEngine(springTemplateEngine); return resolver; } @Bean public SpringResourceTemplateResolver templateResolver () { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver (); resolver.setSuffix(".html" ); resolver.setPrefix("/" ); return resolver; } @Bean public SpringTemplateEngine springTemplateEngine (ITemplateResolver resolver) { SpringTemplateEngine engine = new SpringTemplateEngine (); engine.setTemplateResolver(resolver); return engine; } }
创建Controller,并在类中编写方法用于处理对应地址的请求:
1 2 3 4 5 6 7 8 9 10 @Controller public class HelloController { @RequestMapping(value = "/index") public ModelAndView index () { ModelAndView modelAndView = new ModelAndView ("index" ); modelAndView.getModel().put("name" , "啊这" ); return modelAndView; } }
还可以直接返回View名称,并单独添加Model作为形参进行设置。SpringMVC会将其自动包装为ModelAndView对象,并通过依赖注入自动传递实例对象:
1 2 3 4 5 @RequestMapping(value = "/index") public String index (Model model) { model.addAttribute("name" , "yyds" ); return "index" ; }
让配置类实现WebMvcConfigurer接口,让静态资源通过Tomcat提供的默认Servlet进行解析:
1 2 3 4 5 6 7 8 9 10 @Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) { configurer.enable(); }@Override public void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**" ).addResourceLocations("/static/" ); }
@RequestMapping 路径 路径必须全局唯一,多个路径可以由同一方法处理。
可以将@RequestMapping添加到类名上。表示为此类中的所有请求映射添加一个路径前缀。
1 2 3 4 5 6 7 8 9 @Controller @RequestMapping("/yyds") public class MainController { @RequestMapping({"/index", "/test"}) public ModelAndView index () { return new ModelAndView ("index" ); } }
现在需要访问/yyds/index或是/yyds/test才可以得到此页面。
路径还支持使用通配符进行匹配。
限定请求方式 可以使用method属性限定请求方式:
1 2 3 4 @RequestMapping(value = "/index", method = RequestMethod.POST) public ModelAndView index () { return new ModelAndView ("index" ); }
或使用衍生注解直接指定,如@PostMapping与GetMapping。
限定请求参数 使用params属性,并支持表达式,并可以设置固定值
1 2 3 4 @RequestMapping(value = "/index", params = {"username!=test", "!password"}) public ModelAndView index () { return new ModelAndView ("index" ); }
headers属性限定请求头中的内容,下面代码中如果请求头中携带了Connection属性,将无法访问:
1 2 3 4 @RequestMapping(value = "/index", headers = "!Connection") public ModelAndView index () { return new ModelAndView ("index" ); }
使用两个注解来获取请求中的参数和请求头中的内容。
@RequestHeader与@RequestParam用法一致,以@RequestParam为例。
添加@RequestParam注解获取请求中的参数。
1 2 3 4 5 @RequestMapping(value = "/index") public ModelAndView index (@RequestParam("username") String username) { System.out.println("接受到请求参数:" +username); return new ModelAndView ("index" ); }
如果参数名称与形式参数名称相同,即使不添加@RequestParam也能获取到参数值。一旦添加@RequestParam,那么此请求必须携带指定参数,可以将require属性设定为false来将属性设定为非必须:
1 2 3 4 5 @RequestMapping(value = "/index") public ModelAndView index (@RequestParam(value = "username", required = false) String username) { System.out.println("接受到请求参数:" +username); return new ModelAndView ("index" ); }
还可以设定默认值:
1 2 3 4 5 @RequestMapping(value = "/index") public ModelAndView index (@RequestParam(value = "username", required = false, defaultValue = "伞兵一号") String username) { System.out.println("接受到请求参数:" +username); return new ModelAndView ("index" ); }
如果需要使用Servlet原本的一些类, 直接添加HttpServletRequest或HttpServletResponse为形式参数即可。 HttpSession也可以作为参数传递:
1 2 3 4 5 6 @RequestMapping(value = "/index") public ModelAndView index (HttpSession session) { System.out.println(session.getAttribute("test" )); session.setAttribute("test" , "鸡你太美" ); return new ModelAndView ("index" ); }
还可以直接将请求参数传递给一个实体类:
1 2 3 4 5 @RequestMapping(value = "/index") public ModelAndView index (User user) { System.out.println("获取到cookie值为:" +user); return new ModelAndView ("index" ); }
@CookieValue和@SessionAttrbutie 通过使用@CookieValue注解,快速获取请求携带的Cookie信息:
1 2 3 4 5 6 7 @RequestMapping(value = "/index") public ModelAndView index (HttpServletResponse response, @CookieValue(value = "test", required = false) String test) { System.out.println("获取到cookie值为:" +test); response.addCookie(new Cookie ("test" , "lbwnb" )); return new ModelAndView ("index" ); }
Session也能使用注解快速获取:
1 2 3 4 5 6 7 @RequestMapping(value = "/index") public ModelAndView index (@SessionAttribute(value = "test", required = false) String test, HttpSession session) { session.setAttribute("test" , "xxxx" ); System.out.println(test); return new ModelAndView ("index" ); }
重定向和请求转发 重定向需要在视图名称前添加前缀redirect:
1 2 3 4 5 6 7 8 9 @RequestMapping("/index") public String index () { return "redirect:home" ; }@RequestMapping("/home") public String home () { return "home" ; }
请求转发需要forward前缀:
1 2 3 4 5 6 7 8 9 @RequestMapping("/index") public String index () { return "forward:home" ; }@RequestMapping("/home") public String home () { return "home" ; }
Bean的Web作用域 在SpringMVC中的作用域:
request:对于每次HTTP请求,使用request作用域定义的Bean都将产生一个新实例,请求结束后Bean也消失。
session:对于每一个会话,使用session作用域定义的Bean都将产生一个新实例,会话过期后Bean也消失。
global session:不常用,不做讲解。
使用@RequestScope或是@SessionScope表示此Bean的Web作用域:
1 2 3 4 5 @Bean @RequestScope public TestBean testBean () { return new TestBean (); }
RestFul风格 RESTful风格的设计允许将参数通过URL拼接传到服务端,目的是让URL看起来更简洁实用。
对于路径:
1 http:// localhost:8080 /mvc/i ndex/123456
可以将index的下一级路径作为请求参数进行处理:
1 2 3 4 5 @RequestMapping("/index/{str}") public String index (@PathVariable String str) { System.out.println(str); return "index" ; }
方法的形参列表中必须包括一个与占位符同名的并且添加了@PathVariable注解的参数,或是由@PathVariable注解指定为占位符名称:
1 2 3 4 5 @RequestMapping("/index/{str}") public String index (@PathVariable("str") String text) { System.out.println(text); return "index" ; }
四种请求的映射:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Controller public class MainController { @RequestMapping(value = "/index/{id}", method = RequestMethod.GET) public String get (@PathVariable("id") String text) { System.out.println("获取用户:" +text); return "index" ; } @RequestMapping(value = "/index", method = RequestMethod.POST) public String post (String username) { System.out.println("添加用户:" +username); return "index" ; } @RequestMapping(value = "/index/{id}", method = RequestMethod.DELETE) public String delete (@PathVariable("id") String text) { System.out.println("删除用户:" +text); return "index" ; } @RequestMapping(value = "/index", method = RequestMethod.PUT) public String put (String username) { System.out.println("修改用户:" +username); return "index" ; } }
Interceptor拦截器 拦截器并不是在Servlet之前,它在Servlet与RequestMapping之间,相当于DispatcherServlet在将请求交给对应Controller中的方法之前进行拦截处理,它只会拦截所有Controller中定义的请求映射对应的请求(不会拦截静态资源)。
创建拦截器 需要实现一个HandlerInterceptor接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class MainInterceptor implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("我是处理之前!" ); return true ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("我是处理之后!" ); } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("我是完成之后!" ); } }
在配置类中注册:
1 2 3 4 5 6 @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new MainInterceptor ()) .addPathPatterns("/**" ) .excludePathPatterns("/home" ); }
如果处理过程中抛出异常,那么就不会执行处理后postHandle方法,但是会执行afterCompletion方法,可以在此方法中获取到抛出的异常。
多级拦截器 注册二号拦截器:
1 2 3 4 5 6 7 @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new MainInterceptor ()).addPathPatterns("/**" ).excludePathPatterns("/home" ); registry.addInterceptor(new SubInterceptor ()).addPathPatterns("/**" ); }
拦截顺序就是注册的顺序,因此拦截器会根据注册顺序依次执行。在处理之前,是按照顺序从前向后进行拦截的,但是处理完成之后,就按照倒序执行处理后方法,而完成后是在所有的postHandle执行之后再同样的以倒序方式执行。
异常处理 请求映射方法中出现异常时,会直接展示在前端页面,这是因为SpringMVC为我们提供了默认的异常处理页面,当出现异常时,我们的请求会被直接转交给专门用于异常处理的控制器进行处理。
自定义异常处理控制器:
1 2 3 4 5 6 7 8 9 10 @ControllerAdvice public class ErrorController { @ExceptionHandler(Exception.class) public String error (Exception e, Model model) { e.printStackTrace(); model.addAttribute("e" , e); return "500" ; } }
编写一个专门显示异常的页面:
1 2 3 4 5 6 7 8 9 10 11 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > 500 - 服务器出现了一个内部错误QAQ <div th:text ="${e}" > </div > </body > </html >
1 2 3 4 5 6 @RequestMapping("/index") public String index () { System.out.println("我是处理!" ); if (true ) throw new RuntimeException ("您的氪金力度不足,无法访问!" ); return "index" ; }
JSON 后端JSON解析框架有很多种,比较常用的是Jackson和FastJSON。阿里巴巴的FastJSON是目前号称最快的JSON解析框架。
导入依赖:
1 2 3 4 5 <dependency > <groupId > com.alibaba.fastjson2</groupId > <artifactId > fastjson2</artifactId > <version > 2.0.34</version > </dependency >
编写配置:
1 2 3 4 @Override public void configureMessageConverters (List<HttpMessageConverter<?>> converters) { converters.add(new FastJsonHttpMessageConverter ()); }
直接返回一个对象类型,SpringMVC会自动转换为JSON字符串格式:
1 2 3 4 5 6 7 8 @RequestMapping(value = "/data", produces = "application/json") @ResponseBody public Student data () { Student student = new Student (); student.setName("杰哥" ); student.setAge(18 ); return student; }
文件的上传与下载 上传 添加配置:
1 2 3 4 5 6 7 8 9 10 11 public class MainInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { ... @Override protected void customizeRegistration (ServletRegistration.Dynamic registration) { registration.setMultipartConfig(new MultipartConfigElement ("/Users/nagocoler/Download" )); } }
编写Controller:
1 2 3 4 5 6 7 8 9 @RequestMapping(value = "/upload", method = RequestMethod.POST) @ResponseBody public String upload (@RequestParam MultipartFile file) throws IOException { File fileObj = new File ("test.png" ); file.transferTo(fileObj); System.out.println("用户上传的文件已保存到:" +fileObj.getAbsolutePath()); return "文件上传成功!" ; }
前端添加文件上传点:
1 2 3 4 5 6 <div > <form action ="upload" method ="post" enctype ="multipart/form-data" > <input type ="file" name ="file" > <input type ="submit" > </form > </div >
下载 1 2 3 4 5 6 7 8 9 10 11 @RequestMapping(value = "/download", method = RequestMethod.GET) @ResponseBody public void download (HttpServletResponse response) { response.setContentType("multipart/form-data" ); try (OutputStream stream = response.getOutputStream(); InputStream inputStream = new FileInputStream ("test.png" )){ IOUtils.copy(inputStream, stream); }catch (IOException e){ e.printStackTrace(); } }