@HandlesTypes({WebApplicationInitializer.class}) public class SpringServletContainerInitializer implements ServletContainerInitializer { public SpringServletContainerInitializer() { } public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException { …… } }
方法 | 说明 |
---|---|
protected abstract Class<?>[] getRootConfigClasses(); | 该方法用于设置 Spring 的配置类。 |
protected abstract Class<?>[] getServletConfigClasses(); | 该方法用于设置 Spring MVC 的配置类。 |
protected abstract String[] getServletMappings(); | 该方法用于指定 DispatcherServelt 的映射规则,即 web.xml 中的 url-pattern。 |
protected Filter[] getServletFilters() | 该方法用于添加各种过滤器(filter)。 |
如果我们自定义的初始化类继承了 AbstractAnnotationConfigDispatcherServletInitializer 并将其部署到 Servlet 容器中,Servvelt 容器会自动加载这个初始化类,并使用它来完成对 DispatcherServlet 和 Spring MVC 的配置工作,示例代码如下。
package net.biancheng.c.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.HiddenHttpMethodFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import javax.servlet.Filter; public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer { // 设置 Spring 的配置类 @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } // 设置 Spring MVC 的配置类 @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } // 为 DispatcherServlet 指定映射规则,相当于 web.xml 中配置的 url-pattern @Override protected String[] getServletMappings() { return new String[]{"/"}; } //添加过滤器 @Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceResponseEncoding(true); HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[]{hiddenHttpMethodFilter}; } }
我们还可以使用一个标注了 @Configuration 注解的 Java 类(通常被称为“配置类”),来代替 Spring 的配置文件。
在这个配置类中,我们可以定义多个被 @Bean 注解修饰的方法,这些方法与 Spring 配置文件中 <bean> 标签的作用一样,都是可以将指定的 Java 对象以 Bean 的形式交由 Spring 的 IoC 容器管理。
例如,在 Spring 的 XML 配置文件中定义的一个 Student 类型 Bean,配置形式如下。
<bean id="student" class="net.biancheng.c.entity.Student"> <property name="stuId" value="1001"></property> <property name="stuName" value="小明"></property> <property name="age" value="18"></property> </bean>
上面的 Spring 配置可以通过 SpringConfig 配置类实现,代码如下。
package net.biancheng.c.config; import net.biancheng.c.entity.Student; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SpringConfig { //定义 Bean @Bean public Student student(){ Student student = new Student(); student.setStuId("1001"); student.setStuName("小明"); student.setAge(18); return student; } }
在配置类中,@Bean 注解修饰的方法说明如下:
方法 | 说明 |
---|---|
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {} | 将静态文件交给 Servlet 容器(Tomcat)内置的默认 Servlet 处理。 |
default void addInterceptors(InterceptorRegistry registry) {} | 添加 Spring MVC 拦截器,对请求进行拦截处理。 |
default void addResourceHandlers(ResourceHandlerRegistry registry) {} |
添加或修改静态资源(例如图片,js,css 等)映射; Spring Boot 默认设置的静态资源文件夹就是通过重写该方法设置的。 |
default void addViewControllers(ViewControllerRegistry registry) {} | 主要用于实现无业务逻辑跳转,例如主页跳转,简单的请求重定向,错误页跳转等 |
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {} | 用于配置默认的消息转换器(转换 HTTP 请求和响应)。 |
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {} |
直接添加消息转换器,会关闭默认的消息转换器列表; 实现该方法即可在不关闭默认转换器的起提下,新增一个自定义转换器。 |
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {} | 配置异常解析器。 |
<!--开启组件扫描--> <context:component-scan base-package="net.biancheng.c"></context:component-scan>
使用配置类开启组件扫描功能的代码如下。
@Configuration //扫描组件 @ComponentScan("net.biancheng.c") public class WebConfig implements WebMvcConfigurer { }
@Configuration //开启组件扫描 @ComponentScan("net.biancheng.c") //开启 Spring MVC注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { }
<!-- 配置 Thymeleaf 视图解析器 --> <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <property name="order" value="1"/> <property name="characterEncoding" value="UTF-8"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring5.SpringTemplateEngine"> <property name="templateResolver"> <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <!-- 视图前缀 --> <property name="prefix" value="/WEB-INF/templates/"/> <!-- 视图后缀 --> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML5"/> <property name="characterEncoding" value="UTF-8"/> </bean> </property> </bean> </property> </bean>
@Configuration //扫描组件 @ComponentScan("net.biancheng.c") //开启MVC注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { //配置生成模板解析器 @Bean public ITemplateResolver templateResolver() { WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过 WebApplicationContext ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext()); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); return templateResolver; } //生成模板引擎并为模板引擎注入模板解析器 @Bean public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); return templateEngine; } //生成视图解析器并为解析器注入模板引擎 @Bean public ViewResolver viewResolver(SpringTemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setCharacterEncoding("UTF-8"); viewResolver.setTemplateEngine(templateEngine); return viewResolver; } }
<!--配置文件上传解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--设置上传文件的默认编码格式--> <property name="defaultEncoding" value="UTF-8"></property> <!--设置允许上传的最大长度--> <property name="maxUploadSize" value="10485760"></property> </bean
@Configuration //扫描组件 @ComponentScan("net.biancheng.c") //开启MVC注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { //配置文件上传解析器 @Bean public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(); commonsMultipartResolver.setDefaultEncoding("UTF-8"); commonsMultipartResolver.setMaxUploadSize(1024*1024*10); return commonsMultipartResolver; } }
package net.biancheng.c.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.HiddenHttpMethodFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import javax.servlet.Filter; //初始化类,代替 web.xml public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer { //设置 Spring 的配置类 @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } //设置 Spring MVC 的配置类 @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } //为 DispatcherServlet 指定映射规则,相当于 web.xml 中配置的 url-pattern @Override protected String[] getServletMappings() { return new String[]{"/"}; } //添加过滤器 @Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceResponseEncoding(true); HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter}; } }
package net.biancheng.c.config; import net.biancheng.c.entity.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Date; //创建一个配置类,代替 Spring 的配置文件 @Configuration public class SpringConfig { //定义 User 类型的 Bean,交由 Spring 容器管理 @Bean public User User(){ User user = new User(); user.setUserName("小明"); user.setBirth(new Date()); user.setHeight(180.0); return user; } }
package net.biancheng.c.config; import net.biancheng.c.converter.MyDateConverter; import net.biancheng.c.interceptor.MyInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.view.ThymeleafViewResolver; import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.templateresolver.ITemplateResolver; import org.thymeleaf.templateresolver.ServletContextTemplateResolver; import java.util.List; import java.util.Properties; //配置类代替 Spring MVC 的配置文件 @Configuration //扫描组件 @ComponentScan("net.biancheng.c") //开启MVC注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { //使用默认的servlet处理静态资源 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } //配置文件上传解析器 @Bean public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(); commonsMultipartResolver.setDefaultEncoding("UTF-8"); commonsMultipartResolver.setMaxUploadSize(1024 * 1024 * 10); return commonsMultipartResolver; } //配置拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { MyInterceptor myInterceptor = new MyInterceptor(); registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/"); } //配置视图控制 @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("user"); } //配置异常映射 @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); Properties prop = new Properties(); prop.setProperty("java.lang.Exception", "error"); //设置异常映射 exceptionResolver.setExceptionMappings(prop); //设置共享异常信息的键 exceptionResolver.setExceptionAttribute("ex"); resolvers.add(exceptionResolver); } //配置生成模板解析器 @Bean public ITemplateResolver templateResolver() { WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过 WebApplicationContext ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext()); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); return templateResolver; } //生成模板引擎并为模板引擎注入模板解析器 @Bean public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); return templateEngine; } //生成视图解析器并未解析器注入模板引擎 @Bean public ViewResolver viewResolver(SpringTemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setCharacterEncoding("UTF-8"); viewResolver.setTemplateEngine(templateEngine); return viewResolver; } //添加类型转换器和格式化器 @Override public void addFormatters(FormatterRegistry registry) { MyDateConverter myDateConverter = new MyDateConverter(); registry.addConverter(myDateConverter); } }
package net.biancheng.c.entity; import org.springframework.web.multipart.MultipartFile; import java.util.Date; import java.util.List; /** * 实体类 User */ public class User { private String userName; private Date birth; private Double height; private List<MultipartFile> photos; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } public Double getHeight() { return height; } public void setHeight(Double height) { this.height = height; } public List<MultipartFile> getPhotos() { return photos; } public void setPhotos(List<MultipartFile> photos) { this.photos = photos; } @Override public String toString() { return "User{" + "userName='" + userName + '\'' + ", birth=" + birth + ", height=" + height + ", photos=" + photos + '}'; } }
package net.biancheng.c.converter; import org.springframework.core.convert.converter.Converter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 自定义日期转换器 */ public class MyDateConverter implements Converter<String, Date> { private String datePatten = "yyyy-MM-dd"; @Override public Date convert(String source) { System.out.println("自定义的类型转换器生效;前端页面传递过来的时间为:" + source); SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePatten); try { return simpleDateFormat.parse(source); } catch (ParseException e) { throw new IllegalArgumentException("无效的日期格式,请使用正确的日期格式" + datePatten); } } }
package net.biancheng.c.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //自定义拦截器 public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器 MyInterceptor 成功拦截请求:preHandle 执行"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("拦截器 MyInterceptor 成功拦截请求:postHandle 执行"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("拦截器 MyInterceptor 成功拦截请求:afterCompletion 执行"); } }
package net.biancheng.c.controller; import net.biancheng.c.entity.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Controller public class TestController { @Resource private User user; /** * 测试 Spring 配置是否生效 * * @return */ @ResponseBody @GetMapping("/test") public User get() { return user; } /** * 测试异常映射是否生效 * * @return */ @GetMapping("/testException") public User get2() { int a = 10 / 0; return user; } @RequestMapping(value = "/user", method = RequestMethod.POST) public String login(User user, HttpServletRequest request, Model model) { List<String> newFileNameList = new ArrayList<>(); List<MultipartFile> photos = user.getPhotos(); for (MultipartFile photo : photos) { String realPath = request.getServletContext().getRealPath("/upload/"); System.out.println(realPath); File fileDir = new File(realPath); if (!fileDir.exists()) { fileDir.mkdir(); } String filename = photo.getOriginalFilename(); System.err.println("正在上传的图片为:" + filename); String newFileName = UUID.randomUUID() + filename; try { //将文件保存指定目录 photo.transferTo(new File(realPath + newFileName)); } catch (Exception e) { e.printStackTrace(); } newFileNameList.add(newFileName); } System.out.println(user); model.addAttribute("type", "success"); model.addAttribute("user", user); model.addAttribute("filePath", "/upload/"); model.addAttribute("fileNameList", newFileNameList); return "success"; } }
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>C语言中文网</title> </head> <body> <form th:action="@{/user}" method="post" enctype="multipart/form-data"> <table> <tr> <td>姓名:</td> <td><input type="text" name="userName" required><br></td> </tr> <tr> <td>生日:</td> <td><input type="date" name="birth" required><br></td> </tr> <tr> <td>身高:</td> <td><input type="text" name="height" required><br></td> </tr> <tr> <td>照片:</td> <td><input type="file" name="photos" multiple="multiple" required><br></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="提交"> <input type="reset" value="重置"> </td> </tr> </table> </form> </body> </html>
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>C语言中文网</title> </head> <body> <table> <tr> <td>用户名:</td> <td th:text="${user.getUserName()}"></td> </tr> <tr> <td>生日:</td> <td th:text="${#dates.format(user.getBirth(),'yyyy-MM-dd')}"></td> </tr> <tr> <td>身高:</td> <td th:text="${user.getHeight()}"></td> </tr> <tr> <td>照片:</td> <td th:each="p:${fileNameList}"> <img th:src="${#servletContext.getContextPath()}+${filePath}+${p}" width='200px' height='200px'/><br> </td> </tr> </table> </body> </html>
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>程序发生异常!</h1> <h1 th:text="${ex}"></h1> </body> </html>
图1:注解配置-1
图2:注解配置-2
图3:注解配置-3
{"userName":"小明","birth":1649402504930,"height":180.0,"photos":null}
程序发生异常! java.lang.ArithmeticException: / by zero17. 使用浏览器访问“http://localhost:8080/springmvc-annotation-config-demo/js/jquery-3.6.0.min.js”,对静态文件 jquery-3.6.0.min.js 进行访问,结果如下。
图4:访问静态文件
本文链接:http://task.lmcjl.com/news/15665.html