初学Spring 5 Mvc 零配置文件/Java Config(排坑之旅)
最近,复习web项目,比如spring + spring mvc + spring data
运行环境是:jdk 1.8 + tomcat
编译工具:IntelliJ IDEA 2018.1
在配置上,是采用的配置文件,因为我觉得可能因为代码洁癖和学习spring mvc 的新特性。
1.既然是学Spring mvc 配置 首先要知道这是什么 为什么要用 以下是我浅薄的理解:
传统web 项目 多是用JSP 、Servlet + JDBC 直接搞定:转发 重定向 (页面) 数据传输写在一起,导致意图很清,但是代码结构可能会不容易整理。
所以Mvc 出现 :model(实体been) view(分清是请求静态资源还是接口) controller(接收请求 并处理返回值的接口)。这样的层级会让代码思路清晰。并且还很容易处理安全的问题。
2.然后spring 接受请求访问的流程:
自己的浅薄的见解:
3.闲话少说上配置吧:
配置入口 web.xml:
public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//配置DispatcherServlet映射到 '/' 什么情况进入DispatherServlet
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//spring 注入bean
@Override
protected Class[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
//spring mvc 配置
@Override
protected Class[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected Filter[] getServletFilters() {//注册过滤器
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[]{new HiddenHttpMethodFilter(), characterEncodingFilter};
}
}
Spring配置:
@Configuration
@EnableJpaRepositories(basePackages = {"rainJob.com.dao"})
@ComponentScan(basePackages = {"rainJob.com"}, excludeFilters = {@Filter(type = FilterType.ANNOTATION, value = {EnableWebMvc.class,RestController.class,Controller.class,Repository.class})})
@EnableTransactionManagement
public class RootConfig {
//建议存在properties文件下
public static final String url = "jdbc:mysql://x7.93.15.203:3306/rainJob?useUnicode=true&characterEncoding=utf-8&useSSL=false";
public static final String name = "com.mysql.jdbc.Driver";
public static final String user = "root";
public static final String password = "xxxxxxxxxxxxxx";
/**
* dozer 配置 用于动态解析实体bean
* @return
*/
@Bean(name = "org.dozer.Mapper")
public DozerBeanMapper dozer() {
List<String> mappingFiles = new ArrayList<>();
mappingFiles.add("dozer/dozer-mappings-user.xml");
DozerBeanMapper dozerBean = new DozerBeanMapper();
dozerBean.setMappingFiles(mappingFiles);
return dozerBean;
}
//数据源 spring 下的自带jdbc的链接数据源
@Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(name);
dataSource.setUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
return dataSource;
}
//获取sessionFactory
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DriverManagerDataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean localSession = new LocalContainerEntityManagerFactoryBean();
localSession.setDataSource(dataSource);
localSession.setJpaVendorAdapter(jpaVendorAdapter);
localSession.setPackagesToScan("rainJob.com.entity");
Properties properties = new Properties();
properties.setProperty("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format", "true");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
localSession.setJpaProperties(properties);
return localSession;
}
//jpa规范
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(true);
adapter.setDatabase(Database.MYSQL);
adapter.setGenerateDdl(false);
adapter.setDatabasePlatform("org.hibernate.dialect.HSQLDialect");
return adapter;
}
//事务
@Bean
public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
return transactionManager;
}
@Bean
public BeanPostProcessor paPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}
@Bean
public BeanPostProcessor persistenceTranslation() {
return new PersistenceAnnotationBeanPostProcessor();
}
}
Spring Mvc配置:
@Configuration @EnableWebMvc //相当于 <mvc:annotation-driven/> @ComponentScan(basePackages = {"rainJob.com.controller"}) public class WebConfig implements WebMvcConfigurer { // 配置默认的defaultServlet处理 // <mvc:default-servlet-handler/> @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { // 配置静态资源处理 configurer.enable("default");//对静态资源的请求转发到容器缺省的servlet,而不使用DispatcherServlet } //请求url(spring的url)映射到control的配置 // @Override // public RequestMappingHandlerMapping requestMappingHandlerMapping() { // RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping(); // requestMappingHandlerMapping.setUseSuffixPatternMatch(false); // requestMappingHandlerMapping.setUseTrailingSlashMatch(false); // return requestMappingHandlerMapping; // } /** * 这是定义一个ParameterizableViewController调用时立即转到视图的快捷方式。 * 如果在视图生成响应之前没有Java控制器逻辑要执行,则在静态情况下使用它。 * <mvc:view-controller path="/" view-name="home"/> * @param registry */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("home"); } /** * 静态资源访问控制:假如defaultServlet 没有过滤到接收的静态资源是会报404的 * 配置addResourceHandlers 不能继承WebMvcConfigurationSupport * 因为它拥有子类DelegatingWebMvcConfiguration 已经重写了这个方法。所以运行时,在它方法debug的时候, * 发现我写的方法一点用都没 注意!!! * 下面相当于 * <mvc:resources mapping="/resources/**" location="/statics/" /> * 支持location="classpath:xxxxx" * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/statics/**").addResourceLocations("/statics/"); } // 配置jsp视图解析器 @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/"); resolver.setSuffix(".jsp"); resolver.setOrder(2);//设置优先级 resolver.setCache(false); return resolver; } @Bean //Thymeleaf视图解析器 public ViewResolver thymeleafViewResolver(TemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine); viewResolver.setCharacterEncoding("utf-8"); viewResolver.setCache(false);//去掉缓存 viewResolver.setOrder(1);//设置优先级 viewResolver.setCacheUnresolved(false); return viewResolver; } @Bean //模板引擎 public TemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); templateEngine.clearTemplateCache(); return templateEngine; } /* @Override 简单配置模板 public void configureViewResolvers(ViewResolverRegistry registry) { registry.enableContentNegotiation(new MappingJackson2JsonView()); registry.jsp(); }*/ @Bean public SpringResourceTemplateResolver templateResolver() { //模板解析器 SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); templateResolver.setPrefix("/WEB-INF/"); templateResolver.setSuffix(".html"); templateResolver.setOrder(1); templateResolver.setCacheable(false); templateResolver.setTemplateMode(TemplateMode.HTML); return templateResolver; } }
官网手册:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-enable
当你做完配置运行后,你会发现,无论你改掉什么静态资源,前端都不会相应的显示。
我觉得是在你项目运行的时候,静态资源和class文件 都已经在tomcat webapps 所以只能重新运行才能改变显示。
然后我就在想能不能像eclipse 那样在虚拟路径直接装填类呢。然后对使用工具IntelliJ IDEA进行一些查阅资料:
如上图,假如没有update classes and resources 按下图选择操作:
然后就有了。
以后运行项目会自动生成到虚拟目录,不需要任何插件就能在项目改动的时候,自动装填,可能时间有时差。但是也满足了即改即显示的心里
生成的虚拟目录(是不含有war 解压的class 文件和静态文件):
C:\Users\用户名\对应版本的idea\system\tomcat 例如:C:\Users\syxy37.IntelliJIdea2018.1\system\tomcat
然后有自动生成的 web.xmlC:\Users\syxy37.IntelliJIdea2018.1\system\tomcat\Unnamed_rainJob_4\conf\Catalina\localhost\Root.xml 里有war 解压的class 文件和静态文件的指向