一、 Spring Boot介绍
Spring Boot诞生的目的就是用来简化Spring应用开发过程。该框架使用了特定的方式来进行配置,从而使得开发人员不在需要定义一系列样板化的配置文件,而专注于核心业务开发。帮助开发人员快速的构建出基于Spring的应用。它会在后台整合项目所需的第三方依赖类库或框架,不再需要编写复杂的XML配置文件,仅通过几行代码就能实现一个可运行的Web应用。
- 直接嵌入 Tomcat 或 Jetty 服务器,不需要部署 WAR 文件。
- 提供许多基于Maven的 POM配置模板来简化工程配置。
- 提供可以直接在生产环境中使用的功能,如性能指标、应用信息和应用健康检查。
- 提供实现自动化配置的基础设施
Spring Boot启动器。Spring Boot是由一系列启动器组成的,这些启动器构成一个强大的灵活的开发助手。开发人员根据项目需要,选择并组合相应的启动器,就可以快速搭建一个适合项目需要的基础运行框架。
常用Spring Boot启动器:
- spring-boot-starter 核心模块,包含自动配置支持、日志库和对 YAML 配置文件的支持。
- spring-boot-starter-aop 支持面向切面编程(AOP),包含 spring-aop 和 AspectJ 。
- spring-boot-starter-data-mongodb 包含 spring-data-mongodb 来支持 MongoDB。
- spring-boot-starter-redis 支持Redis键值存储数据库,包含spring-redis
- spring-boot-starter-jdbc 支持使用 JDBC 访问数据库。
- spring-boot-starter-test 包含常用的测试所需的依赖,如 JUnit、Hamcrest、Mockito 和 spring-test 等。
- spring-boot-starter-web 支持 Web 应用开发,包含 Tomcat 和 spring-mvc、spring-webmvc
- spring-boot-starter-websocket 支持使用 Tomcat 开发 WebSocket 应用。
- spring-boot-starter-ws 支持 Spring Web Services。
- spring-boot-starter-log4j 添加 Log4j 的支持。
- spring-boot-starter-logging 使用 Spring Boot 默认的日志框架 Logback。
- spring-boot-starter-mail 支持javax.mail模块
- spring-boot-starter-remote-shell 支持远程 SSH命令操作。
- spring-boot-starter-tomcat 使用 Spring Boot 默认的 Tomcat 作为应用服务器。
- spring-boot-starter-jetty 使用 Jetty 而不是默认的 Tomcat 作为应用服务器。
二、Maven配置
创建好Maven项目 IDEA创建Maven工程,然后编辑pom.xml
pom.xml
<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.smart</groupId> <artifactId>springBootDemo1</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>springBootDemo1 Maven Webapp</name> <url>http://maven.apache.org</url> <!--①继承Spring Boot默认配置--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> </parent> <dependencies> <!--②添加第一个Boot Web启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--③如果想使用Jetty服务器就添加这个依赖,默认使用Tomcat--> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-jetty</artifactId>--> <!--</dependency>--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!--④配置运行插件--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <useSystemClassLoader>false</useSystemClassLoader> </configuration> </plugin> </plugins> </build> </project>
①处继承了Spring Boot提供的根默认配置依赖,这里引入spring-boot-starter-parent的好处是在②处添加启动器时不必再声明版本号。
③处注释掉了一个Jetty容器依赖,Spring Boot默认会采用内嵌的Tomcat运行当前应用,如果想使用Jetty运行当前应用,就加上这个依赖。
④处引用了一个Spring Boot运行插件。刷新IDEA开发工具右边的Maven Projects面板,就可以看到Spring Boot运行命令。
三、 Application主类
程序包结构图:
Spring Boot有一个Application应用主类放在com.smart主包下,这个主类声明了main()方法,并在类级别上标注@Configuration、@ComponentScan、@EnableAutoConfiguration注解。在Spring Boot 1.2+中可以使用@SpringBootApplication注解代替前面三个注解。
Application.java
package com.smart; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer; /** * Created by Mistra.WR on 2017/8/17/017. */ //@Configuration //@ComponentScan //@EnableAutoConfiguration @SpringBootApplication//此注解可以代替上面三个注解 public class Application{ public static void main(String[] args) throws Exception{ SpringApplication.run(Application.class,args); } }
Spring Boot启动应用非常简单,只需在main()方法中通过SpringApplication.run()方法启动即可。
四、 持久层实现
Spring框架提供了几种可选的操作数据库的方式,可以直接使用Spring内置轻量级的JdbcTemplate,也可以使用第三方持久化框架Hibernate或Mybatis。分别提供了相应的启动器spring-boot-starter-jdbc和spring-boot-starter-jpa。
初始化配置,在pom.xml文件中导入spring-boot-starter-jdbc依赖以及访问数据库的JDBC驱动器。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency>
导入依赖包以后,为了让Spring Boot能够自动装配数据源的连接,需要在资源根目录resources下创建一个application.properties,配置数据库的连接信息。
application.properties
#①配置数据库连接信息
spring.datasource.name=sampleDs
spring.datasource.url=jdbc:mysql://localhost:3306/sampledb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#②指定自定义连接池
#spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
#③连接池配置信息
spring.datasource.max-wait=10000
spring.datasource.max-active=50
spring.datasource.max-idle=10
spring.datasource.min-idle=8
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=select 1
#④配置JNDI数据源
#spring.datasource.jndi-name=java:comp/env/jdbc/sampleDs
#⑤初始化数据库脚本
#spring.datasource.initialize=true
#spring.datasource.platform=mysql
#spring.datasource.data=data
#spring.datasource.schema=schema
Spring Boot中,可以通过两种方式配置数据库连接。
- 一种是通过自定义连接的方式,如在①处配置了连接所需属性。在默认情况下,Boot启动器自动创建tomcat-jdbc连接池。也可以通过像②处自定义连接池,如DBCP,C3P0。
- 另外一种是通过JNDI方式设置,如在④处为spring.datasource.jndi-name属性指定一个JNDI连接名称即可。
1、User
package com.smart.domain; import java.io.Serializable; import java.util.Date; /** * Created by Mistra.WR on 2017/8/5/005. */ public class User implements Serializable{ private int userID; private String username; private String password; private int credits; private String lastIp; private Date lastVisit; ...... }
2.LoginLog
package com.smart.dao; import java.io.Serializable; import java.util.Date; /** * Created by Mistra.WR on 2017/8/5/005. */ public class LoginLog implements Serializable{ private int loginLogid; private int userId; private String ip; private Date loginDate; ...... }
3.UserDao
package com.smart.dao; import com.smart.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.stereotype.Repository; import java.sql.ResultSet; import java.sql.SQLException; /** * Created by Mistra.WR on 2017/8/15/015. */ @Repository public class UserDao { private JdbcTemplate jdbcTemplate; private final static String MATCH_COUNT_SQL = "select count(*) from t_user" + " where user_name = ? and password=?"; private final static String UPDATE_LOGININFO_SQL = "update t_user set "+ " last_visit=?,last_ip=?,credits=? where user_id=?"; @Autowired //自动注入JdbcTemplate的bean public void setJdbcTemplatedbcTemplate(JdbcTemplate jdbcTemplate){ this.jdbcTemplate = jdbcTemplate; } public int getMatchCount(String userName,String password){ return jdbcTemplate.queryForObject(MATCH_COUNT_SQL,new Object[]{userName,password}, Integer.class).intValue(); } public User findUserByUserName(final String userName){ String sqlStr = " SELECT user_id,user_name,credits " + " FROM t_user WHERE user_name =? "; final User user = new User(); jdbcTemplate.query(sqlStr, new Object[]{userName}, new RowCallbackHandler() { public void processRow(ResultSet resultSet) throws SQLException { user.setUserID(resultSet.getInt("user_id")); user.setUsername(userName); user.setCredits(resultSet.getInt("credits")); } } ); return user; } public void updateLoginInfo(User user){ jdbcTemplate.update(UPDATE_LOGININFO_SQL,new Object[]{user.getLastVisit(),user.getLastIp(),user.getCredits(),user.getUserID()}); } }
五、 业务层实现
与前一篇文章一样,UserService。
UserService.java
package com.smart.service; import com.smart.dao.LoginLogDao; import com.smart.dao.UserDao; import com.smart.domain.LoginLog; import com.smart.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * Created by Mistra.WR on 2017/8/10/010. */ @Service public class UserService { private UserDao userDao; private LoginLogDao loginLogDao; @Autowired private void setUserDao(UserDao userDao){ this.userDao = userDao; } @Autowired private void setLoginLogDao(LoginLogDao loginLogDao){ this.loginLogDao = loginLogDao; } public boolean hasMatcherUser(String username,String password){ int matchCount = userDao.getMatchCount(username,password); return matchCount > 0; } public User findUserByUserName(String username){ return userDao.findUserByUserName(username); } @Transactional public void loginSuccess(User user){ user.setCredits( 5 + user.getCredits()); LoginLog loginLog = new LoginLog(); loginLog.setIp(user.getLastIp()); loginLog.setUserId(user.getUserID()); loginLog.setLoginDate(user.getLastVisit()); userDao.updateLoginInfo(user); loginLogDao.insertLoginLog(loginLog); } }
在编写业务层代码时有两个中啊哟的步骤:一时编写正确的业务逻辑;二是对业务事务的管控。
在Spring Boot中,使用事务非常简单,首先在主类Application上标注@EnableTransactionManagement注解(开启事务支持),然后再访问Service方法上标注 @Transactional注解即可。
如果将 @Transactional注解标注在Service类级别上,name当前Service类的所有方法都将被事务增强。
如果用户想自己定义事务管理器,在Application类中添加一个即可。
修改之后的Application主类:
package com.smart; /** * Created by Mistra.WR on 2017/8/17/017. */ //@Configuration //@ComponentScan //@EnableAutoConfiguration @SpringBootApplication//此注解可以代替上面三个注解 @EnableTransactionManagement//开启事物支持,启用注解事物管理 public class Application{ public static void main(String[] args) throws Exception{ SpringApplication.run(Application.class,args); } @Bean public PlatformTransactionManager txManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
在Application中添加自定义事务管理器方法txManager(),并在方法上标注@Bean注解,此时Spring Boot会加载自定义的事务管理器,不会重新实例化其它事务管理器。
六、 展现层实现
1.配置pom.xml依赖
由于使用了JSP作为视图,用到了JSTL标签,因此pom.xml需要添加相关依赖包。
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency>
2.配置Spring MVC框架
在Boot环境中配置MVC很简单,只需要将上面的主类Application稍作修改。
package com.smart; import org.apache.tomcat.jdbc.pool.DataSource; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Created by Mistra.WR on 2017/8/17/017. */ //@Configuration //@ComponentScan //@EnableAutoConfiguration @SpringBootApplication//此注解可以代替上面三个注解 @EnableTransactionManagement//开启事物支持,启用注解事物管理 public class Application extends SpringBootServletInitializer {//① public static void main(String[] args) throws Exception{ SpringApplication.run(Application.class,args); } //② protected SpringApplicationBuilder configure(SpringApplicationBuilder application){ return application.sources(Application.class); } @Bean public PlatformTransactionManager txManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
在①处继承了Spring Boot提供的Servlet初始化器SpringBootServletInitializer,在②处重写了SpringBootServletInitializer的configure()方法。
3.LoginController
ackage com.smart.web; import com.smart.domain.User; import com.smart.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.util.Date; /** * Created by Mistra.WR on 2017/8/14/014. */ @Controller public class LoginController { private UserService userService; @Autowired public void setUserService(UserService userService){ this.userService = userService; } //负责处理/index.html的请求 @RequestMapping(value = {"/" , "/index.html"})//可配置多个映射路径 public String loginPage(){ return "login"; } //负责处理/loginCheck.html的请求 @RequestMapping(value = "/loginCheck.html") public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){ boolean isValidUser = userService.hasMatcherUser(loginCommand.getUsername(),loginCommand.getPassword()); if (!isValidUser){ return new ModelAndView("login","error","用户名或密码错误"); }else{ User user = userService.findUserByUserName(loginCommand.getUsername()); user.setLastIp(request.getLocalAddr()); user.setLastVisit(new Date()); userService.loginSuccess(user); request.getSession().setAttribute("user",user); return new ModelAndView("main"); } } }
4.JSP页面
在src/main/webapp/WEB-INF目录下创建一个jsp文件夹,跟前面一篇文章的两个jsp页面一样(login.jsp和main.jsp),就不列代码了。
规划好视图目录后,最后一步就是崽application.properties中配置创建好的视图路径。
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
七、 运行应用
在Maven Projects面板中双击spring-boot:run命令,即可启动应用。