使用Spring Boot你可以不用或者只使用很少的Spring配置搭建项目,
可以以最小化的依赖开始spring应用,
Spring Boot可以以jar包的形式独立运行,他可以根据类路径中的jar包、类、为jar包里的类自动配置Bean,这样极大减少我们要使用的配置。
以下内容有不对的地方,还请告知,感谢!
demo结构图
一、首先new一个maven项目
pom.xml文件(因有些标签属性不是很懂,就加了一些注释在里面,可删除)
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 根目录 --> <!-- 项目或者组织的唯一标志,并且配置时生成路径也是由此生成,如org.myproject.mojo生成的相对路径为:/org/myproject/mojo --> <groupId>com.sec.demeter</groupId> <!-- 项目的通用名称 --> <artifactId>demeter-demo</artifactId> <!-- 项目的版本 --> <version>1.0-SNAPSHOT</version> <!-- 打包机制,如pom,jar,maven-plugin,ejb,war,ear,rar,par --> <packaging>jar</packaging> <!-- POM关系:主要为依赖(dependencies),继承(parent),合成 --> <!-- 继承于该jar包 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.2.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--<java.version>1.8</java.version>--> </properties> <repositories> <repository> <id>spring-snapshots</id> <url>http://repo.spring.io/libs-snapshot</url> </repository> </repositories> <!-- 配置仓库 --> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <url>http://repo.spring.io/libs-snapshot</url> </pluginRepository> </pluginRepositories> <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> <skip>true</skip> </configuration> </plugin> </plugins> </build> <!-- 构建设置 --> <dependencies> <dependency> <!-- 属性, type:默认为jar类型,常用的类型有:jar,ejb-client,test-jar... || scope:是用来指定当前包的依赖范围,maven的依赖范围 || optional:设置指依赖是否可选,默认为false,即子项目默认都继承,为true,则子项目必需显示的引入,与dependencyManagement里定义的依赖类似 || exclusions:如果X需要A,A包含B依赖,那么X可以声明不要B依赖,只要在exclusions中声明exclusion || exclusion:是将B从依赖树中删除,如上配置,alibaba.apollo.webx不想使用com.alibaba.external ,但是alibaba.apollo.webx是集成了com.alibaba.external,r所以就需要排除掉 --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- JPA全称 JavaPersistence API.JPA通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 引入Hibernate依赖包 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.7.Final</version> </dependency> <!-- SQLSERVER --> <dependency> <groupId>net.sourceforge.jtds</groupId> <artifactId>jtds</artifactId> <version>1.2.4</version> </dependency> </dependencies> </project>
二、创建Application类【启动类,有两种方式,可以参考注释中的简要说明】
package com.springBoot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; /** * Created by Lisa.Li on 2016/11/7. * <p> * 运行方式 * 1:通过在Application中添加@EnableAutoConfiguration标签 开启自动配置, * ---然后通过SpringApplication.run(Application.class, args) 运行这个控制器 * ---这种方式只运行了一个控制器比较方便。 * ---需要在浏览器中输入http://localhost:8080/hello 就会在页面上展示 Hello World, Hello Spring boot * <p> * 2:通过@SpringBootApplication + @ComponentScan 开启注解扫描并自动注册相应的注解Bean * ---运行Application类即可发布整个应用 */ // 方式1 // @Controller // @EnableAutoConfiguration // public class Application { // // @RequestMapping(value="/hello", method= RequestMethod.GET) // @ResponseBody // String index() { // return "Hello World, Hello Spring boot"; // } // // public static void main(String[] args) throws Exception { // SpringApplication.run(Application.class, args); // } // } // 方式2 @SpringBootApplication @ComponentScan(basePackages = { "com.springBoot.controller", "com.springBoot.model", "com.springBoot.dao" }) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); System.out.println("******************** starting success!"); } }
三、集成Hibernate持久层框架
- pom.xml文件需要引入依赖包,刚才贴的pom.xml已经加了hibernate的依赖,
- 添加application.properties配置文件,此外还配置了server的端口号和contextPath
#----------- SQL SERVER ------ spring.datasource.url = jdbc:jtds:sqlserver://xxx.xx.xx.xxx:xxxx/数据库名 spring.datasource.username = xx spring.datasource.password = xxx spring.datasource.initialize = false spring.jpa.show-sql = true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect jdbc.initialSize = 1 jdbc.maxActive = 20 jdbc.maxIdle = 10 jdbc.maxWait = 120000 hibernate.dialect = org.hibernate.dialect.SQLServerDialect hibernate.show_sql = true hibernate.jdbc.batch_size = 20 hibernate.connection.pool_size = 20 #----------- Server Config ------ server.port = 8080 server.contextPath = /demo #----------- Logger Config ------ logging.level.org.springframework.web = DEBUG #the log level for all demeter package. logging.level.com.movitech.demeter = DEBUG
四、写实体类【建表SQL语句写在 CreateModel_userInfo.sql 中】
package com.springBoot.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * Created by Lisa.Li on 2016/11/10. */ @Entity @Table(name = "test_user_info") public class UserInfo { private Integer id; private String userName; private String passWord; private String userType; private String realName; private String qq; private String email; private String tel; private Boolean valid; private String createUser; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name = "user_name") public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Column(name = "pass_word") public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } @Column(name = "user_type") public String getUserType() { return userType; } public void setUserType(String userType) { this.userType = userType; } @Column(name = "real_name") public String getRealName() { return realName; } public void setRealName(String realName) { this.realName = realName; } @Column(name = "qq") public String getQq() { return qq; } public void setQq(String qq) { this.qq = qq; } @Column(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Column(name = "tel") public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } @Column(name = "valid") public Boolean getValid() { return valid; } public void setValid(Boolean valid) { this.valid = valid; } @Column(name = "create_user") public String getCreateUser() { return createUser; } public void setCreateUser(String createUser) { this.createUser = createUser; } public String toString() { return "UserInfo [id=" + id + ",userName=" + userName + ",passWord=" + passWord + ",userType" + userType + ",realName=" + realName + ",qq=" + qq + ",email=" + email + ",tel=" + tel + ",valid=" + valid + ",createUser=" + createUser + "]"; } }
五、写Dao【数据访问层】,使用Spring Data JPA建立数据访问层十分简单,只需要定义一个继承JpaRepository的接口即可,默认已经有了最基本的CRUD
package com.springBoot.dao; import com.springBoot.model.UserInfo; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * Created by Lisa.Li on 2016/11/10. */ public interface UserInfoDao extends JpaRepository<UserInfo, Long> { // @Query("SELECT id,user_name,pass_word,user_type FROM UserInfo WHERE user_name = :userName") UserInfo findUserByUserName(String userName); List<UserInfo> findAll(); @Transactional @Modifying @Query("UPDATE UserInfo SET valid = 0 WHERE id = :id") void delete(@Param("id") Integer id); }
六、添加Controller层【暴露API接口给前端】
package com.springBoot.controller; import com.springBoot.model.UserInfo; import com.springBoot.dao.UserInfoDao; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; /** * Created by Lisa.Li on 2016/11/10. */ @RestController public class UserInfoController { Log log = LogFactory.getLog(this.getClass()); @Autowired private UserInfoDao userInfoDao; @RequestMapping(value = "hello") String index() { return "Hello World! Hello Spring boot!"; } /** * 添加用户 * * @param userInfo user * @return UserInfo */ @RequestMapping(value = "user/addUser", method = RequestMethod.POST) public UserInfo addUser(@RequestBody UserInfo userInfo) { log.debug("******************** add user"); return userInfoDao.save(userInfo); } /** * 更新用户(调用save接口,传id) * * @param userInfo user * @return UserInfo */ @RequestMapping(value = "user/updateUser", method = RequestMethod.PUT) public UserInfo updateUser(@RequestBody UserInfo userInfo) { log.debug("******************** update user, id" + userInfo.getId()); return userInfoDao.save(userInfo); } /** * 逻辑删除用户 * * @param id 主键 */ @RequestMapping(value = "user/invalidUser/{id}", method = RequestMethod.DELETE) public void invalidUser(@PathVariable("id") Integer id) { log.debug("******************** invalid user, id: " + id); userInfoDao.delete(id); } /** * 查询user by XX * * @param name userName * @return UserInfo */ @RequestMapping(value = "user/getUserByName/{name}", method = RequestMethod.GET) public UserInfo getUserByName(@PathVariable("name") String name) { log.debug("******************** get User by name:" + name); UserInfo userInfo = userInfoDao.findUserByUserName(name); log.debug(userInfo); return userInfo; } /** * find all users * * @return List<UserInfo> */ @RequestMapping(value = "user/findAll", method = RequestMethod.GET) public List<UserInfo> findAll() { log.debug("******************** get all users"); List<UserInfo> userInfos = userInfoDao.findAll(); return userInfos; } }
七、启动项目,使用启动类【Application.java】中方式二, P.S. 上传的图片有点失真,请见谅。
启动成功会在控制台输出Started.......
此时可以调用UserInfoController中的API了,
【此demo项目的contextPath被我配置成 /demo,所以访问接口时请添加 /demo 】,
P.S. 我一般使用IDEA中Rest Client工具进行访问【前提是IDEA中的Database连接正常】
也可以使用Google Chrome 插件Advanced REST client进行访问,
这样最基本的CRUD功能就实现了。
八、遇到的问题
- 若不配置server的端口号,默认是8080;
- 若不配置srever的contextPath默认是“/”;
- 第一次写dao层时,在findUserByUserName方法用注解的方式写SQL语句报错,
@Query("SELECT id,user_name,pass_word,user_type FROM UserInfo WHERE user_name = :userName")
原因是蓝色部分我第一次写成表名test_user_info了,应该写成表对应的实体类的名字。
4. 再后来发现dao层继承JpaRepository接口之后,对于查询可以有以下实现方法
4.1. 根据属性名查询,Spring Data JPA支持通过定义在Repository接口中的方法来定义查询,而方法名是根据实体类的属性名确定的,
如:findByUserName、findByUserNameLike、findByUserNameAndTel等
5. 调用update方法时,若没有定义某些字段的值,则会被更新成null,
解决方法参考博客:http://www.cnblogs.com/seed_lee/archive/2011/02/15/1955631.html
6. 写invalid接口时,override源生delete方法,
6.1. 第一次没有添加@Modifying标签,报错Not supported for DML operations [UPDATE com.springBoot.model.TestUserInfo SET valid = 0 WHERE id = :id]
6.2. 第二次加了标签报错:Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
才发现需要添加注解@Transactional
后续真正开始项目时,肯定会遇到各种问题,会不定期更新此文......