1.pom文件导入依赖,如果设置了<packing>war<packing>并想使用war包,那么在tomcat中的Deployment中请通过+选择External Source再选中这个war包;如果没有设置,那么请通过+选择Artifact再选择对应的“模块名+Web exploded”的,修改好Application Context后请通过“编辑”的一支笔一样的图标按钮,将右侧的jar文件放入左侧的lib目录下。
如果是war方式,请注意修改代码后及时clear和compile;如果选择的是tomcat热部署,请记得把jar文件放入lib文件夹下。配置图片放在本文最后
我个人比较喜欢测试代码时不打包,因为tomcat选择打包的war需要每次修改后重新clear和compile。而选择添加jar文件则可以热部署,修改后测试效果更快更省时间。
2.写一个类继承
AbstractAnnotationConfigDispatcherServletInitializer
/** * 相当于配置了一个DispatcherServlet * 如果是父子容器,就在getRootConfigClasses中写父容器,getServletConfigClasses中写子容器 * 但如果只有一个容器,就写在getRootConfigClasses中 * 这个类需要servlet的依赖 */ public class WebMvcConfig extends AbstractAnnotationConfigDispatcherServletInitializer { /** * 添加真正的配置类,可以有多个, * 例如WebSocketConfig需要实现两个接口,但是它们有相同的方法需要重写 * 那么可以在WebSocketConfig中写一个内部类A,再把内部类A也配置进去 * @return */ @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{WebSocketConfig.class}; // return new Class[]{WebSocketConfig.class, A.class}; } /** * 如果你配置了父子容器,那么这里也需要配置 * 我个人觉得父子容器没必要,从来不用 * 正常来讲就选择配置getRootConfigClasses方法就可以 * @return */ @Override protected Class<?>[] getServletConfigClasses() { return new Class[0]; } /** * 一般都写“/”,如果有特殊需要也可以自己改 * @return */ @Override protected String[] getServletMappings() { return new String[] {"/"}; } }
3.配置类:
/** * 实现WebMvcConfigurer接口可以重写该接口中的一些较为好用的方法,比较方便 */ // 声明该类是配置类 @Configuration // 打开MVC的注解驱动 @EnableWebMvc // mapper文件所扫描的dao包 @MapperScan("com.nf.supermarket.dao") // 组件扫描,主要是controller和service的实现类所在的包 @ComponentScan({"com.nf.supermarket.controller", "com.nf.supermarket.service.impl", "com.nf.supermarket.util", "com.nf.supermarket.aop"}) // 数据库连接所需数据文件获取 @PropertySource("classpath:sql/db.properties") // 打开事务管理 @EnableTransactionManagement // 切面代理 @EnableAspectJAutoProxy(proxyTargetClass = true) public class xxxConfig implements WebMvcConfigurer { @Value("${mysql.url}") private String url; @Value("${mysql.username}") private String username; @Value("${mysql.password}") private String password; /** * 配置druid的连接池 * 本来是需要同一个连接的,但连接池内部有其实现方法,只需要保证是同一个连接池即可 * 如果存在driverClassName,就可以根据url找到driverClassName,因此无需再配置 * * @return 一个被spring管理的连接池 */ @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } /** * 生成dao的代理类 * * @return 返回一个被spring管理的sqlSessionFactory * @throws Exception mapper文件未找到及getObject方法调用出错 */ @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource()); // 设置哪里找到mapper文件 sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/**/*.xml")); // 设置配置 sqlSessionFactoryBean.setConfiguration(configuration()); // 设置插件 sqlSessionFactoryBean.setPlugins(pageInterceptor()); return sqlSessionFactoryBean.getObject(); } /** * 注入事务驱动 * * @return 数据源事务管理 */ @Bean public DataSourceTransactionManager dataSourceTransactionManager() { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource()); return dataSourceTransactionManager; } /** * mybatis的配置 * * @return SqlSessionFactoryBean对象所需设置的配置 */ private org.apache.ibatis.session.Configuration configuration() { org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); // 输出执行的sql语句,日志某些类似的效果,更清晰了解做了什么 configuration.setLogImpl(StdOutImpl.class); // 下划线转驼峰形式 configuration.setMapUnderscoreToCamelCase(true); return configuration; } /** * 分页插件,但项目中用了layui,因此只是借用了它的组合分页SQL语句功能 * * @return 一个分页拦截器对象 */ private PageInterceptor pageInterceptor() { PageInterceptor pageInterceptor = new PageInterceptor(); Properties properties = new Properties(); // 支持方法参数 properties.setProperty("supportMethodsArguments", "true"); // 参数合理化,使页数正确 properties.setProperty("reasonable", "true"); pageInterceptor.setProperties(properties); return pageInterceptor; } /** * 凡是/static路径开头的文件,一律到resouces文件下的static包下找 * * @param registry 登记资源解析器 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { ResourceHandlerRegistration resourceHandlerRegistration = registry.addResourceHandler("/static/**"); resourceHandlerRegistration.addResourceLocations("classpath:/static/"); } /** * 视图解析 * * @param registry 登记视图解析 */ @Override public void configureViewResolvers(ViewResolverRegistry registry) { // WEB-INF前加/表示相对路径,如果不加在某些情况下会出错 registry.jsp("/WEB-INF/views/", ".jsp"); } /** * 添加拦截器,保证权限能够正常启用 * * @param registry 登记拦截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { InterceptorRegistration interceptorRegistration = registry.addInterceptor(new UserInterceptor()); interceptorRegistration.addPathPatterns("/**"); interceptorRegistration.excludePathPatterns("/login"); // "/"是LoginController的默认,即启动时的界面 interceptorRegistration.excludePathPatterns("/"); interceptorRegistration.excludePathPatterns("/retrievePassword"); interceptorRegistration.excludePathPatterns("/getVerificationCode"); interceptorRegistration.excludePathPatterns("/updatePassword"); // static后面要加/** interceptorRegistration.excludePathPatterns("/static/**"); InterceptorRegistration interceptorRegistration1 = registry.addInterceptor(new PowerInterceptor()); interceptorRegistration1.addPathPatterns("/unit/**"); interceptorRegistration1.addPathPatterns("/wholesaler/**"); interceptorRegistration1.addPathPatterns("/employee/**"); interceptorRegistration1.addPathPatterns("/userInfo/**"); interceptorRegistration1.addPathPatterns("/commodity/**"); } /** * 配合apache的commons依赖上传文件 * * @return 文件上传处理 */ @Bean public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(); commonsMultipartResolver.setMaxUploadSize(1024 * 1024 * 1024L); return commonsMultipartResolver; } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setDateFormat(sdf); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper); //通过设置索引,让自己的转换器放在最前面,否则默认的jackson转换器会在前面,用不上我们设置的转换器. converters.add(0, converter); } }
其实也就是实现
WebMvcConfigurer
里面可以重写一些有用的方法,根据需要来写,例如:我需要能够直接在浏览器地址访问web目录下和WEB-INF同级的html页面
@Configuration @EnableWebSocketMessageBroker @EnableWebMvc @ComponentScan("com.test") public class StompConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("chat"); registry.addEndpoint("chat").withSockJS(); } /** * 因为不能同时实现WebSocketMessageBrokerConfigurer和WebMvcConfigurer * 所以写一个内部类分别实现 */ class SssConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { ResourceHandlerRegistration resourceHandlerRegistration = registry.addResourceHandler("/*.html"); resourceHandlerRegistration.addResourceLocations("/"); ResourceHandlerRegistration resourceHandlerRegistration1 = registry.addResourceHandler("/*.js"); resourceHandlerRegistration1.addResourceLocations("/"); } } }
4.直接启动tomcat就可以了
tomcat配置图片: