java註解方式(不用xml)配置web框架spring+SpringMVC

公司現在用了gradle構建工具
而且用java註解的方式配置項目,不再使用xml的方式,因爲網上這方面教程比較少,所以在此記錄一個基本的框架的搭建,包括測試類的寫法!
框架:spring+springMVC+hibernate
構建工具:gradle
開發工具:eclipse
github地址:https://github.com/gyb123456/MyGradle
項目結構如下:這裏寫圖片描述
我把項目源碼放到我的github上了;

主要看下com.sys包就行了,我主要講解這裏的。看到和sys平級的三個java文件了沒,這就是項目配置的3個java類。
先給3個參考鏈接
1、Spring實戰5-基於Spring構建Web應用
https://segmentfault.com/a/1190000004343063?_ea=575820
2、單元測試配置
http://www.infoq.com/cn/articles/Unit-Testing-Complete-Integration-Testing-Begins
3、別人的配置
http://blog.csdn.net/csdn_xuexiaoqiang/article/details/71844535
4、 寫給java web一年左右工作經驗的人
https://my.oschina.net/aaron74/blog/282304
我就是參考它們寫的。


1、先說下DispatcherServletInit類繼承自
AbstractAnnotationConfigDispatcherServletInitializer,tomcat啓動時會自動掃描繼承該類的文件,所以這個文件是整個項目的程序入口,在這裏配置根容器、Spring mvc容器,攔截請求等,具體的自己看代碼註釋吧。

/**
 *DispatcherServletInit類
 * 整個項目的程序入口
 * @author gyb
 *
 */
package com;

import javax.servlet.Filter;

import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class DispatcherServletInit extends AbstractAnnotationConfigDispatcherServletInitializer{
@Override //根容器,用於獲取Spring應用容器的配置文件
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootConfig.class};
    }

    @Override //Spring mvc容器,是根容器的子容器
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }

    @Override //"/"表示由DispatcherServlet處理所有向該應用發起的請求。
    protected String[] getServletMappings() {
        return new String[]{"/"};   
    }

    @Override
    protected Filter[] getServletFilters() {
    //          OpenSessionInViewFilter  openSessionInViewFilter  = new OpenSessionInViewFilter ();
            CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();  
            characterEncodingFilter.setEncoding("UTF-8");  
            characterEncodingFilter.setForceEncoding(true);  
            return new Filter[] {characterEncodingFilter,characterEncodingFilter};  
//      return super.getServletFilters();

    }

}

2、RootConfig類

package com;

import java.beans.PropertyVetoException;
import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.sys.biz.impl.ConstTypeBizImpl;

@Configuration
/*  @EnableAspectJAutoProxy:開啓AOP代理自動配置
    proxyTargetClass=true:表示使用CGLib動態代理技術織入增強,決定是基於接口的還是基於類的代理被創建。默認爲false(JDK代理)
    即<aop:aspectj-autoproxy proxy-target-class="true"/> 
*/
@EnableAspectJAutoProxy(proxyTargetClass=true) //解決實現接口後,spring不能創建類實例的問題
@EnableScheduling //通過@EnableScheduling註解開啓對計劃任務的支持
@ComponentScan(
    basePackages={"com.sys,com.base"},
    excludeFilters={//設置不掃描的文件,這裏會排除springMVC掃描過的包
        @Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
    }
)
//啓用註解事務管理,等同於xml配置方式的 <tx:annotation-driven />
@EnableTransactionManagement
public class RootConfig {

    /**配置C3P0
     * */
    @Bean
    public ComboPooledDataSource dataSource() throws PropertyVetoException{
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
        cpds.setJdbcUrl("jdbc:mysql://10.1.30.207:3306/InfoIssue?characterEncoding=utf8");
        cpds.setUser("root");
        cpds.setPassword("root");
        return cpds;
    }

    /**Hibernate SessionFactory
     * */
    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource){
        LocalSessionFactoryBean sf = new LocalSessionFactoryBean();
        sf.setDataSource(dataSource);
        sf.setPackagesToScan(new String[]{"com"});
        Properties props = new Properties();
        props.setProperty("dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
        sf.setHibernateProperties(props);
        return sf;
    }

    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory);
        return transactionManager;
    }
    //這是一個Bean後置處理器,它會在所有擁有#Repository註解的類上添加一個通知器,這樣就會捕獲任何平臺相關的異常並以Spring非檢查型訪問異常的形式重新拋出。
    @Bean
    public BeanPostProcessor persistenceTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

}

3、WebConfig類

package com;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc   //啓用Spring MVC組件
@ComponentScan("com.sys.ctrl")  //配置掃描的ctrl層
public class WebConfig extends WebMvcConfigurerAdapter{

    //配置JSP視圖解析器
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/JSP/");
        resolver.setSuffix(".jsp");
        //可以在JSP頁面中通過${}訪問beans
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    //配置靜態資源的處理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();//把針對靜態資源的請求轉交給servlert容器的default servlet處理
    }

    /**
     * Jackson配置
     * @return
     */
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
//      MediaType mediaType1 = new MediaType("application\\json");
//      MediaType mediaType2 = new MediaType("charset=UTF-8");
//      supportedMediaTypes.add(mediaType1);
//      supportedMediaTypes.add(mediaType2);

        supportedMediaTypes = MediaType.parseMediaTypes("application/json; charset=utf-8");

        converter.setSupportedMediaTypes(supportedMediaTypes );
        return converter;
    }
    /*//如何在Spring MVC中統一對返回的Json進行加密?http://www.tuicool.com/articles/E3I3qyi
     * @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        return new MappingJackson2HttpMessageConverter() {
            //重寫writeInternal方法,在返回內容前首先進行加密
            @Override
            protected void writeInternal(Object object,
                                         HttpOutputMessage outputMessage) throws IOException,
                    HttpMessageNotWritableException {
                //使用Jackson的ObjectMapper將Java對象轉換成Json String
                ObjectMapper mapper = new ObjectMapper();
                String json = mapper.writeValueAsString(object);
                LOGGER.error(json);
                //加密
                String result = json + "加密了!";
                LOGGER.error(result);
                //輸出
                outputMessage.getBody().write(result.getBytes());
            }
        };
    }*/
    /**
     * Jackson配置
     * 添加自定義轉換器
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(mappingJackson2HttpMessageConverter());
        super.configureMessageConverters(converters);
    }
}

這些文件都是我遇到以後填好的坑,每個細節都得注意,一個註解都不能少。

下面是build.gradle文件的配置,包括插件或者jar的版本號都要對應,否則項目會報錯,這也是我遇到坑以後,在百度上查到的並填的坑!

/*
 * This build file was generated by the Gradle 'init' task.
 *
 * user guide available at https://docs.gradle.org/3.3/userguide/tutorial_java_projects.html
 */

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'com.bmuschko.tomcat'

sourceCompatibility = 1.8
version = '1.0'

//解決編碼GBK的不可映射字符
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

repositories {
    maven{ url "http://repo.spring.io/release"}
    jcenter()
}

dependencies {
    def tomcatVersion = '8.0.42'
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
           "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
           "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"
}

dependencies {
    compile 'org.springframework:spring-context:4.3.8.RELEASE',
            'org.springframework:spring-web:4.3.8.RELEASE',
            'org.springframework:spring-webmvc:4.3.8.RELEASE',
            'org.springframework:spring-orm:4.3.8.RELEASE',

            'org.hibernate:hibernate-core:4.3.11.Final',

            'com.mchange:c3p0:0.9.5.2',

            'mysql:mysql-connector-java:6.0.6',

            'com.jcraft:jsch:0.1.46',

            //jackson包
            'com.fasterxml.jackson.core:jackson-databind:2.6.1'
            'com.fasterxml.jackson.core:jackson-annotations:2.6.1'
            'com.fasterxml.jackson.core:jackson-core:2.6.1'

    providedCompile 'javax.servlet:javax.servlet-api:4.0.0-b07' //用4.0.0-b07版本,否則3.0坑爹
    testCompile 'junit:junit:4.12',
                'org.springframework:spring-test:4.3.8.RELEASE'
}

buildscript {
    repositories {
        jcenter()
    }
    dependencies{
        classpath 'com.bmuschko:gradle-tomcat-plugin:2.2.5'
    }
}

test{
    testLogging{
        showStandardStreams = true
        events 'started', 'passed', 'skipped', 'failed'
    }
}

4、至此項目已經搭建好了,但是呢,測試文件還沒說。我寫下測試類sys.dao下面的ConstTypeTest的配置

package com.sys.dao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.RootConfig;
import com.WebConfig;
import com.sys.biz.impl.ConstDictBizImpl;
import com.sys.ctrl.ConstDictCtrl;
import com.sys.ctrl.ConstTypeCtrl;
import com.sys.po.ConstDict;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes=RootConfig.class)

@WebAppConfiguration //(value = "src/main/webapp")
@ContextHierarchy({
        @ContextConfiguration(name = "parent", classes = RootConfig.class),
        @ContextConfiguration(name = "child", classes = WebConfig.class)})
//@Transactional
public class ConstTypeTest {

    @Autowired
    private ConstTypeCtrl ConstTypeBizImpl; 
    @Autowired
    private ConstDictCtrl ConstDictCtrl;
    @Autowired
    private ConstDictBizImpl constDictBizImpl;
    @Test
    public  void findAll() {
//      List<ConstType> list = ConstTypeBizImpl.findAll();
        ConstDict po = new ConstDict();
        po.setVal("lll");
        po.setName("啦啦啦");
        po.setTypeId(1);
        ConstDictCtrl.save(po, null);
//      constDictBizImpl.save(po);



        System.out.println("=============");
    }
}

結束!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章