1. 程式人生 > >Spring 5 Mvc 零配置檔案/Java Config 環境搭建(排坑之旅)

Spring 5 Mvc 零配置檔案/Java Config 環境搭建(排坑之旅)

初學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;
    }


}

當你做完配置執行後,你會發現,無論你改掉什麼靜態資源,前端都不會相應的顯示。
我覺得是在你專案執行的時候,靜態資源和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.xml

C:\Users\syxy37.IntelliJIdea2018.1\system\tomcat\Unnamed_rainJob_4\conf\Catalina\localhost\Root.xml 裡有war 解壓的class 檔案和靜態檔案的指向