SSM-SpringMVC(五)-纯注解整合SSM
用Initializer取代web.xml
-
删除web.xml新建一个WebInitializer类,并实现AbstractAnnotationConfigDispatcherServletInitializer接口
//com.zh.cfg.WebInitializer public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { /** * 父容器的配置类 */ @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } /** * 子容器的配置类(SpringMVC相关的配置类) */ @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMVCConfig.class}; } /** * 配置DispatcherServlet的url-pattern */ @Override protected String[] getServletMappings() { return new String[]{"/"}; } @Override public void onStartup(ServletContext servletContext) throws ServletException { super.onStartup(servletContext); // 添加Filter //post请求解决乱码问题 FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("CharacterEncodingFilter", new CharacterEncodingFilter("UTF-8")); encodingFilter.addMappingForUrlPatterns(null, false, "/*"); } }
-
该类的本质是:项目部署的时候创建该对象,然后调用onStartup方法,该方法内部会自动调用getRootConfigClasses、getServletConfigClasses、getServletMappings对应的方法
Initializer的本质
- AbstractAnnotationConfigDispatcherServletInitializer的本质
- 最终是实现了WebApplicationInitializer接口
- 项目部署到Web容器时,就会初始化实现了WebApplicationInitializer接口的实例,并调用它的onStartup方法
-
也可以自己定义一个类WebInitializer2,实现WebApplicationInitializer接口,然后主动调用父子容器等方法
public class WebInitializer2 implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { // 父容器配置 AnnotationConfigWebApplicationContext springCtx = new AnnotationConfigWebApplicationContext(); springCtx.register(SpringConfig.class); // 通过监听器加载配置信息 servletContext.addListener(new ContextLoaderListener(springCtx)); // 子容器配置 AnnotationConfigWebApplicationContext mvcCtx = new AnnotationConfigWebApplicationContext(); mvcCtx.register(SpringMVCConfig.class); //交给DispatcherServlet进行初始化子容器 ServletRegistration.Dynamic servlet = servletContext.addServlet( "DispatcherServlet", new DispatcherServlet(mvcCtx)); servlet.setLoadOnStartup(0); servlet.addMapping("/"); // filter FilterRegistration.Dynamic encodingFilter = servletContext.addFilter( "CharacterEncodingFilter", new CharacterEncodingFilter("UTF-8")); encodingFilter.addMappingForUrlPatterns(null, false, "/*"); } }
创建父子容器
- 纯注解实现Spring容器,取代applicationContext.xml
- 注意:SpringConfig可以不需要再写@Configuration
//父容器存放service、dao //converter其他也会用到,所以放到父容器中 @ComponentScan({"com.zh.service", "com.zh.converter"}) @PropertySource("classpath:db.properties") @MapperScan("${mybatis.mapperScan}") @EnableTransactionManagement public class SpringConfig { @Value("${jdbc.driverClassName}") private String driverClassName; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Value("${mybatis.typeAliasesPackage}") private String typeAliasesPackage; //自动注入 @Value("${mybatis.configLocation}") private String configLocation; @Bean public DataSource dataSource() { DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driverClassName); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); return ds; } @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setTypeAliasesPackage(typeAliasesPackage); //单独加载mybaits核心配置文件 bean.setConfigLocation(new ClassPathResource(configLocation)); return bean; } @Bean public DataSourceTransactionManager txMgr(DataSource dataSource) { DataSourceTransactionManager mgr = new DataSourceTransactionManager(); mgr.setDataSource(dataSource); return mgr; } }
-
纯注解实现SpringMVC容器,取代dispatcherServlet.xml
//子容器存放controller、拦截器(仅仅用于controller层) @ComponentScan({"com.zh.controller", "com.zh.interceptor"}) @EnableWebMvc public class SpringMVCConfig implements WebMvcConfigurer { //自动注入拦截器 @Autowired private MyInterceptor myInterceptor; @Autowired private DateConverter dateConverter; //将拦截器对象放入容器 @Bean public MyInterceptor myInterceptor() { return new MyInterceptor(); } //前后缀拼接 @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/page/"); resolver.setSuffix(".jsp"); return resolver; } //文件上传,相当于<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> @Bean public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver resolver = new CommonsMultipartResolver(); resolver.setDefaultEncoding("UTF-8"); return resolver; } //设置拦截器,拦截路径,相当于 <mvc:interceptors> @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor) .addPathPatterns("/**") .excludePathPatterns("/asset/**"); } //相当于<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(dateConverter); } /** * 相当于<mvc:default-servlet-handler/> * 用以处理静态资源 */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } //设置返回String、json响应数据的编码 MessageConverters,相当于<mvc:message-converters> @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 设置返回的普通字符串的编码 StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); stringConverter.setDefaultCharset(StandardCharsets.UTF_8); converters.add(stringConverter); // 设置返回的JSON数据的编码 MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); jsonConverter.setDefaultCharset(StandardCharsets.UTF_8); converters.add(jsonConverter); } }
其他代码说明
- service、dao、domain、controller都没有变化
-
新增MyInterceptor
@Component public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor - preHandle - " + request.getRequestURI()); return true; } }
-
DateConverter
@Component public class DateConverter implements Converter<String, Date> { @Override public Date convert(String source) { try { return new SimpleDateFormat("yyyy-MM-dd").parse(source); } catch (ParseException e) { e.printStackTrace(); return null; } } }
-
controller添加测试
@Controller public class TestControlller { @GetMapping("/test1") public String test1() { // /WEB-INF/page/test.jsp return "test"; } @GetMapping("/test2") @ResponseBody public String test2() { return "测试中文数据"; } @GetMapping("/test3") @ResponseBody public String test3(@RequestParam("birthday") Date birthday) { return birthday.toString(); } @PostMapping("/test4") @ResponseBody public String test4(@RequestParam("name") String name, @RequestParam("photo") MultipartFile photo) { return "Success - " + name + " - " + photo.toString(); } }
-
db.properties
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test-mybatis jdbc.username=root jdbc.password=root mybatis.typeAliasesPackage=com.zh.domain mybatis.mapperScan=com.zh.dao mybatis.configLocation=mybatis-config.xml