前面兩篇文章介紹了 基於XML方式搭建SpringMVC先後臺交互系統的方法,博文連接以下:
http://www.cnblogs.com/hunterCecil/p/8252060.html
http://www.cnblogs.com/hunterCecil/p/6924935.htmlhtml
本文重點介紹一下基於java配置+註解方式搭建系統的過程步驟。前端
1、摘要
一、所需軟件列表:
1) tomcat : apache-tomcat-7.0.54 服務端容器
2) Intellij: Intellij IDEA 2016.3.1 開發工具
3) Syslog: SQLyog Community 數據庫工具
2. 步驟簡述:
1) 新建一個 Java 項目, 按下圖依次選擇:
2) 項目目錄以下:
各目錄存儲文件以下:java
(1)java.com : 目錄下用於存放後臺代碼:mysql
config: 配置啓動類
controller: 應用層實現類
dao: 數據訪問層的bean
entity: 對象實體類
service: 業務層bean, 具體的數據庫操做實現類
(2)resource:
jdbc.properties: 數據庫配置
log4j.properties: 日誌配置相關屬性
users.sql: 建表語句web
(3)webapp: 客戶端展現相關文件spring
2、 相關配置文件
1. web.xml配置(用於配置Spring 相關配置項:上下文、日誌、字符集、監聽器等經過配置文件加載,這裏只配置welcome-file-list及session-config)sql
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="false"> <!-- session超時 --> <session-config> <session-timeout>60</session-timeout> </session-config> <!-- 歡迎頁面 -->; <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
2. jdbc. properties數據庫
jdbc.driver = com.mysql.jdbc.Driver db.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 db.username = root db.password = *****
3. log4j.propertiesapache
#日誌輸出級別 log4j.rootLogger=INFO,stdout,other #設置stdout的日誌輸出控制檯 log4j.appender.stdout=org.apache.log4j.ConsoleAppender #輸出日誌到控制檯的方式,默認爲System.out log4j.appender.stdout.Target = System.out #設置使用靈活佈局 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout #靈活定義輸出格式 log4j.appender.stdout.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}] %l %m %n #設置other的日誌輸出控制檯 log4j.appender.other=org.apache.log4j.RollingFileAppender #設置other的輸出日誌 log4j.appender.other.File=/WEB-INF/logs/log.log #設置other的日誌最大限制 log4j.appender.other.MaxFileSize=1024KB #最多隻保存20個備份文件 log4j.appender.other.MaxBackupIndex=1000 #輸出INFO級別以上的日誌 og4j.appender.other.Threshold=INFO #設置使用靈活佈局 log4j.appender.other.layout=org.apache.log4j.PatternLayout #靈活定義輸出格式 log4j.appender.other.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}] %l %t %m %n
4. uses.sqlapi
-- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` tinyint (20), `name` varchar (90), `age` tinyint (100), PRIMARY KEY (`id`), ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user -- ---------------------------- insert into `user` (`id`, `name`, `age`) values('2','zhangsan','32'); insert into `user` (`id`, `name`, `age`) values('3','lisi','33'); insert into `user` (`id`, `name`, `age`) values('1','wangwu','12');
5. config目錄下文件:
DatabaseConfig
@Configuration @EnableTransactionManagement public class DatabaseConfig { private static final Logger logger = Logger.getLogger(DatabaseConfig.class.getName()); @Value("${jdbc.driver}") private String jdbcDriver; @Value("${db.url}") private String dbUrl; @Value("${db.username}") private String username; @Value("${db.password}") private String password; @Bean(destroyMethod = "close") public DataSource dataSource() { logger.info("mysql url:"+dbUrl); BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(jdbcDriver); dataSource.setUrl(dbUrl); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public DataSourceTransactionManager txManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); return sessionFactory.getObject(); } }
PropertiesConfig
@Configuration @PropertySource(value={"classpath:jdbc.properties"}) public class PropertiesConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() { return new PropertySourcesPlaceholderConfigurer(); } }
RootConfig
@Configuration @ComponentScan(basePackages = {"com"}) public class RootConfig { }
WebConfig
@Configuration @EnableWebMvc @EnableAspectJAutoProxy @EnableTransactionManagement @ComponentScan("com.controller") @MapperScan("com.dao") public class WebConfig extends WebMvcConfigurerAdapter { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setExposeContextBeansAsAttributes(true); return resolver; } @Bean public StringHttpMessageConverter stringHttpMessageConverter(){ return new StringHttpMessageConverter(); } @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){ return new MappingJackson2HttpMessageConverter(); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(stringHttpMessageConverter()); converters.add(mappingJackson2HttpMessageConverter()); super.configureMessageConverters(converters); } /** * 啓用spring mvc 的註解 */ public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
WebAppInitializer
/** * 配置SpringMVC須要添加DispatchServlet , * DispatcherServlet主要負責前端調用URL的分發, * 它在Web容器初始化的時候被註冊。 * 這裏配置中繼承了DispatchServlet 的一個抽象類AbstractAnnotationConfigDispatcherServletInitializer , * 此抽象類的父類在實例化的時候會註冊一個DispatchServlet到容器中 * 這裏配置了容器初始化時須要加載的配置類 RootConfig,PropertiesConfig 和 WebConfig */ public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { /** 應用上下文、配置文件讀取,數據庫配置*/ @Override protected Class<?>[] getRootConfigClasses() { System.out.println("======1.應用上下文、配置文件讀取,數據庫配置 load ================"); return new Class<?>[]{RootConfig.class, PropertiesConfig.class, DatabaseConfig.class}; } /* web上下文 */ @Override protected Class<?>[] getServletConfigClasses() { System.out.println("======2.web上下文 load ================"); return new Class<?>[]{WebConfig.class}; } /* DispatcherServlet的映射路徑 */ @Override protected String[] getServletMappings() { System.out.println("======3.DispatcherServlet的映射路徑 load ================"); return new String[]{"/"}; } /* 註冊過濾器,映射路徑與DispatcherServlet一致,路徑不一致的過濾器須要註冊到另外的WebApplicationInitializer中*/ @Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceEncoding(true); return new Filter[]{characterEncodingFilter}; } }
6. controller-TestController
@Controller public class TestController { @Autowired @Qualifier("userService") private UserService userService; @RequestMapping(value = "/test", method = RequestMethod.GET) public String test() { return "test"; } @RequestMapping(value = "/getuser/{username}", method = RequestMethod.GET) @ResponseBody public User getUser(@PathVariable String username) { return userService.loadUserByUsername(username); } }
7. dao-UserDao
@Controller public class TestController { @Autowired @Qualifier("userService") private UserService userService; @RequestMapping(value = "/test", method = RequestMethod.GET) public String test() { return "test"; } @RequestMapping(value = "/getuser/{username}", method = RequestMethod.GET) @ResponseBody public User getUser(@PathVariable String username) { return userService.loadUserByUsername(username); } }
8. entity-User
public class User { private Integer id; private String name; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
9. log-logAspect
@Component @Aspect public class LogAspect { private static final Logger logger = Logger.getLogger(LogAspect.class.getName()); @Pointcut("execution(* com.controller.*.*(..))") public void performance() { } @Before("performance()") public void optionBefore(JoinPoint joinPoint){ System.out.println("@Before開始執行"+joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); } @After("performance()") public void optionAfter(JoinPoint joinPoint){ System.out.println("@After結束執行"+joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); } @Around("performance()") public Object optionAround(ProceedingJoinPoint pjp) throws Throwable { Object retVal = null; System.out.println("@Around start.."); try { retVal = pjp.proceed(); } catch (Throwable ex) { System.out.println("error in @Around"); throw ex; } System.out.println("@Around end"); return retVal; } @AfterReturning(pointcut = "performance()", returning = "returnValue") public void optionAfterReturn(JoinPoint joinPoint, Object returnValue) { System.out.println("@AfterReturning:目標方法爲:" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); System.out.println("@AfterReturning:參數爲:" + Arrays.toString(joinPoint.getArgs())); System.out.println("@AfterReturning:返回值爲:" + returnValue); System.out.println("@AfterReturning:被織入的目標對象爲:" + joinPoint.getTarget()); } @AfterThrowing(pointcut = "performance()", throwing = "e") public void optionError(JoinPoint joinPoint, Throwable e) { logger.log(Level.WARNING,"異常方法:{" + joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "}" + "異常類型:{" + e.getClass().getName() + "}" + "異常信息:{" + e.getMessage() + "}" + "參數:{" + Arrays.toString(joinPoint.getArgs()) + "}", e); } }
10. service-UserService
public interface UserService { User loadUserByUsername(String username); void saveUser(User user); }
11. service-impl-UserServiceImpl
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Transactional(readOnly = true) public User loadUserByUsername(String username) { return userDao.loadUserByUsername(username); } @Transactional public void saveUser(User user) { userDao.saveUser(user); } }
12. maven 對應的pom文件以下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com</groupId> <artifactId>springJavaConfig</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>springJavaConfig Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.6</java.version> </properties> <dependencies> <dependency> <!--Unit Test --> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- SpringMVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency>
<!--Mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.5</version> </dependency> </dependencies> <build> <finalName>springJavaConfig</finalName> </build> </project>
三. 啓動過程打印日誌:
Connected to server
[2018-01-17 10:47:20,950] Artifact springJavaConfig:war exploded: Artifact is being deployed, please wait...
一月 17, 2018 10:47:23 上午 org.apache.catalina.startup.TldConfig execute
信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
======1.應用上下文、配置文件讀取,數據庫配置 load ================ ======2.web上下文 load ================ ======3.DispatcherServlet的映射路徑 load ================
一月 17, 2018 10:47:24 上午 org.springframework.web.context.ContextLoader initWebApplicationContext
信息: Root WebApplicationContext: initialization started
一月 17, 2018 10:47:24 上午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext prepareRefresh
信息: Refreshing Root WebApplicationContext: startup date [Wed Jan 17 10:47:24 CST 2018]; root of context hierarchy
一月 17, 2018 10:47:24 上午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
信息: Registering annotated classes: [class com.config.RootConfig,class com.config.PropertiesConfig,class com.config.DatabaseConfig]
一月 17, 2018 10:47:25 上午 com.config.DatabaseConfig dataSource
信息: mysql url:jdbc:mysql://10.42.120.201:3306/test?useUnicode=true&characterEncoding=UTF-8
一月 17, 2018 10:47:25 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
信息: Mapped "{[/test],methods=[GET]}" onto public java.lang.String com.controller.TestController.test()
一月 17, 2018 10:47:25 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
信息: Mapped "{[/getuser/{username}],methods=[GET]}" onto public com.entity.User com.controller.TestController.getUser(java.lang.String)
一月 17, 2018 10:47:25 上午 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
信息: Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
信息: Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Wed Jan 17 10:47:24 CST 2018]; root of context hierarchy
一月 17, 2018 10:47:26 上午 org.springframework.web.context.ContextLoader initWebApplicationContext
信息: Root WebApplicationContext: initialization completed in 2370 ms
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.DispatcherServlet initServletBean
信息: FrameworkServlet 'dispatcher': initialization started
一月 17, 2018 10:47:26 上午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext prepareRefresh
信息: Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Wed Jan 17 10:47:26 CST 2018]; parent: Root WebApplicationContext
一月 17, 2018 10:47:26 上午 org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
信息: Registering annotated classes: [class com.config.WebConfig]
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
信息: Mapped "{[/test],methods=[GET]}" onto public java.lang.String com.controller.TestController.test()
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
信息: Mapped "{[/getuser/{username}],methods=[GET]}" onto public com.entity.User com.controller.TestController.getUser(java.lang.String)
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
信息: Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter initControllerAdviceCache
信息: Looking for @ControllerAdvice: WebApplicationContext for namespace 'dispatcher-servlet': startup date [Wed Jan 17 10:47:26 CST 2018]; parent: Root WebApplicationContext
一月 17, 2018 10:47:26 上午 org.springframework.web.servlet.DispatcherServlet initServletBean
信息: FrameworkServlet 'dispatcher': initialization completed in 356 ms
[2018-01-17 10:47:26,774] Artifact springJavaConfig:war exploded: Artifact is deployed successfully
[2018-01-17 10:47:26,775] Artifact springJavaConfig:war exploded: Deploy took 5,825 milliseconds
能夠看到,WebAppInitializer類中咱們的配置類已經按順序加載過了。
4、 測試
url 輸入 http://localhost:8080/getuser/zhangsan,能夠查看切面部分打印日誌以下:
@Around start.. @Before開始執行com.controller.TestController.getUser @Around end @After結束執行com.controller.TestController.getUser @AfterReturning:目標方法爲:com.controller.TestController.getUser @AfterReturning:參數爲:[zhangsan] @AfterReturning:返回值爲:com.entity.User@182bab1a @AfterReturning:被織入的目標對象爲:com.controller.TestController@24b0c989