1、配置
项目结构目录
创建maven项目
maven配置文件引入包
< 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>
< groupId> com. fanney< / groupId>
< artifactId> springboot< / artifactId>
< version> 0.0 .1 - SNAPSHOT < / version>
< ! -- 定义公共资源版本 -- >
< parent>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- parent< / artifactId>
< version> 1.5 .6 . RELEASE < / version>
< relativePath / >
< / parent>
< properties>
< project. build. sourceEncoding> UTF - 8 < / project. build. sourceEncoding>
< project. reporting. outputEncoding> UTF - 8 < / project. reporting. outputEncoding>
< java. version> 1.8 < / java. version>
< / properties>
< dependencies>
< ! -- 上边引入 parent,因此 下边无需指定版本 -- >
< ! -- 包含 mvc, aop 等jar资源 -- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- web< / artifactId>
< / dependency>
< ! -- 热部署 -- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- devtools< / artifactId>
< optional> true < / optional>
< scope> true < / scope>
< / dependency>
< ! -- mysql -- >
< dependency>
< groupId> mysql< / groupId>
< artifactId> mysql- connector- java< / artifactId>
< version> 5.1 .40 < / version>
< / dependency>
< ! -- 添加oracle jdbc driver
< dependency>
< groupId> com. oracle< / groupId>
< artifactId> ojdbc14< / artifactId>
< version> 10.2 .0 .5 .0 < / version>
< / dependency>
-- >
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- data- jpa< / artifactId>
< / dependency>
< / dependencies>
< build>
< plugins>
< plugin>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- maven- plugin< / artifactId>
< configuration>
< ! -- 没有该配置,devtools 不生效 -- >
< fork> true < / fork>
< / configuration>
< / plugin>
< / plugins>
< / build>
< / project>
配置application-test.properties(测试环境)
(开发环境和线上环境同下)
server. port= 8089
spring. datasource. driver- class - name= com. mysql. jdbc. Driver
spring. datasource. url= jdbc:mysql : / / localhost: 3306 / school
spring. datasource. username= root
spring. datasource. password= 0
spring. jpa. hibernate. ddl- auto= update
spring. jpa. show- sql= true
spring. jackson. serialization. indent_output= true
配置application.properties(可切换环境)
spring. profiles. active= dev
配置事务管理(以类的形式,以配置文件形式可参考spring事务配置)
package com. fanney. springboot. framework;
import java. util. Collections ;
import java. util. HashMap ;
import java. util. Map ;
import org. aspectj. lang. annotation. Aspect ;
import org. springframework. aop. Advisor ;
import org. springframework. aop. aspectj. AspectJExpressionPointcut ;
import org. springframework. aop. support. DefaultPointcutAdvisor ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. context. annotation. Bean ;
import org. springframework. context. annotation. Configuration ;
import org. springframework. transaction. PlatformTransactionManager ;
import org. springframework. transaction. TransactionDefinition ;
import org. springframework. transaction. interceptor. NameMatchTransactionAttributeSource ;
import org. springframework. transaction. interceptor. RollbackRuleAttribute ;
import org. springframework. transaction. interceptor. RuleBasedTransactionAttribute ;
import org. springframework. transaction. interceptor. TransactionAttribute ;
import org. springframework. transaction. interceptor. TransactionInterceptor ;
/ / spring切面编程 把xml换成注解实现
@Aspect
@Configuration
public class TxAdviceInterceptor {
private static final int TX_METHOD_TIMEOUT = 5 ;
/ / 两个点的意思是中间夹层不管是啥名字都会匹配到
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.fanney.springboot..service.*.*(..))" ;
@Autowired
private PlatformTransactionManager transactionManager;
@Bean
public TransactionInterceptor txAdvice ( ) {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource ( ) ;
/ / 只读事务,不做更新操作
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute ( ) ;
readOnlyTx. setReadOnly ( true ) ;
readOnlyTx. setPropagationBehavior ( TransactionDefinition . PROPAGATION_NOT_SUPPORTED ) ;
/ / 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute ( ) ;
requiredTx. setRollbackRules ( Collections . singletonList ( new RollbackRuleAttribute ( Exception . class ) ) ) ;
requiredTx. setPropagationBehavior ( TransactionDefinition . PROPAGATION_REQUIRED ) ;
requiredTx. setTimeout ( TX_METHOD_TIMEOUT ) ;
Map < String , TransactionAttribute > txMap = new HashMap < String , TransactionAttribute > ( ) ;
txMap. put ( "add*" , requiredTx) ;
txMap. put ( "save*" , requiredTx) ;
txMap. put ( "insert*" , requiredTx) ;
txMap. put ( "update*" , requiredTx) ;
txMap. put ( "delete*" , requiredTx) ;
txMap. put ( "get*" , readOnlyTx) ;
txMap. put ( "query*" , readOnlyTx) ;
source. setNameMap ( txMap) ;
TransactionInterceptor txAdvice = new TransactionInterceptor (
transactionManager, source) ;
return txAdvice;
}
@Bean
public Advisor txAdviceAdvisor ( ) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut ( ) ;
pointcut. setExpression ( AOP_POINTCUT_EXPRESSION ) ;
return new DefaultPointcutAdvisor ( pointcut, txAdvice ( ) ) ;
}
}
打印日志(logback-spring.xml)
< ? xml version= "1.0" encoding= "UTF-8" ? >
< configuration>
< ! -- 文件输出格式 -- >
< property name= "PATTERN" value= "%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) |-%-5level [%thread] %c [%L] -| %msg%n" / >
< ! -- test文件路径 -- >
< property name= "TEST_FILE_PATH" value= "d:/test.log" / >
< ! -- pro文件路径 -- >
< property name= "PRO_FILE_PATH" value= "/opt/test/log" / >
< ! -- 开发环境 -- >
< springProfile name= "dev" >
< appender name= "CONSOLE" class = "ch.qos.logback.core.ConsoleAppender" >
< encoder>
< pattern> ${ PATTERN } < / pattern>
< / encoder>
< / appender>
< logger name= "com.fanney.springboot" level= "debug" / >
< root level= "info" >
< appender- ref ref= "CONSOLE" / >
< / root>
< / springProfile>
< ! -- 测试环境 -- >
< ! -- springProfile 标签的 name 属性对应 application. properties 中的 spring. profiles. active 的配置。 -- >
< springProfile name= "test" >
< ! -- 每天产生一个文件 -- >
< appender name= "TEST-FILE" class = "ch.qos.logback.core.rolling.RollingFileAppender" >
< ! -- 文件路径 -- >
< file> ${ TEST_FILE_PATH } < / file>
< rollingPolicy class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
< ! -- 文件名称 -- >
< fileNamePattern> ${ TEST_FILE_PATH } / info. % d{ yyyy- MM - dd} . log< / fileNamePattern>
< ! -- 文件最大保存历史数量 -- >
< MaxHistory > 100 < / MaxHistory >
< / rollingPolicy>
< layout class = "ch.qos.logback.classic.PatternLayout" >
< pattern> ${ PATTERN } < / pattern>
< / layout>
< / appender>
< root level= "info" >
< appender- ref ref= "TEST-FILE" / >
< / root>
< / springProfile>
< ! -- 生产环境 -- >
< springProfile name= "prod" >
< appender name= "PROD_FILE" class = "ch.qos.logback.core.rolling.RollingFileAppender" >
< file> ${ PRO_FILE_PATH } < / file>
< rollingPolicy class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
< fileNamePattern> ${ PRO_FILE_PATH } / warn. % d{ yyyy- MM - dd} . log< / fileNamePattern>
< MaxHistory > 100 < / MaxHistory >
< / rollingPolicy>
< layout class = "ch.qos.logback.classic.PatternLayout" >
< pattern> ${ PATTERN } < / pattern>
< / layout>
< / appender>
< root level= "warn" >
< appender- ref ref= "PROD_FILE" / >
< / root>
< / springProfile>
< / configuration>
2、程序(以增删改查为例)
程序启动入口(SpringbootApplication)
package com. fanney. springboot;
import org. springframework. boot. SpringApplication ;
import org. springframework. boot. autoconfigure. SpringBootApplication ;
@SpringBootApplication
public class SpringbootApplication {
public static void main ( String [ ] args) {
SpringApplication . run ( SpringbootApplication . class , args) ;
}
}
实体类
package com. fanney. springboot. entity;
import javax. persistence. Column ;
import javax. persistence. Entity ;
import javax. persistence. GeneratedValue ;
import javax. persistence. Id ;
/ / 注:jpa才需要的三个注解
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
@Column ( nullable= false )
private String name;
public Long getId ( ) {
return id;
}
public void setId ( Long id) {
this. id = id;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this. name = name;
}
public User ( String name) {
super ( ) ;
this. name = name;
}
public User ( ) {
super ( ) ;
}
@Override
public String toString ( ) {
return "User [id=" + id + ", name=" + name + "]" ;
}
}
service层和serviceImpl实现层
package com. fanney. springboot. service;
import java. util. List ;
import com. fanney. springboot. entity. User ;
public interface UserService {
/ / 新增
public User saveUser ( User user) ;
/ / 删除
public void delete ( Integer id) ;
/ / 修改
public int update ( Integer id, String name) ;
/ / 查询所有
List < User > findAll ( ) ;
/ / 根据编号查询
User findOne ( Integer id) ;
}
package com. fanney. springboot. service. impl;
import java. util. List ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. stereotype. Service ;
import com. fanney. springboot. dao. UserRespository ;
import com. fanney. springboot. entity. User ;
import com. fanney. springboot. service. UserService ;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRespository UserRespository ;
/ / / / 用单独事务的方法
/ / / / @Transactional ( rollbackFor = { IllegalArgumentException . class } )
/ / / / @Transactional ( noRollbackFor = { IllegalArgumentException . class } )
public User saveUser ( User user) {
User result = UserRespository . save ( user) ; / / jpa自带的新增方法
if ( result. getName ( ) . equals ( "sang" ) ) {
throw new IllegalArgumentException ( "sang已存在,数据将回滚" ) ;
}
return result;
}
public void delete ( Integer id) {
try {
UserRespository . delete ( id) ; / / jpa自带的新增方法
} catch ( Exception e) {
throw new IllegalArgumentException ( "执行失败,数据将回滚" ) ;
}
}
public int update ( Integer id, String name) {
int result ;
try {
result = UserRespository . update ( id, name) ; / / jpa自带的新增方法
} catch ( Exception e) {
throw new IllegalArgumentException ( "执行失败,数据将回滚" ) ;
}
return result;
}
/ / 查询所有
public List < User > findAll ( ) {
List < User > userList = null;
try {
userList = UserRespository . findAll ( ) ;
} catch ( Exception e) {
throw new IllegalArgumentException ( "查询失败,数据将回滚" ) ;
}
return userList;
}
public User findOne ( Integer id) {
return UserRespository . findOne ( id) ;
}
}
UserRespository类
package com. fanney. springboot. dao;
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 com. fanney. springboot. entity. User ;
/ / 此处的Integer 是id的类型
public interface UserRespository extends JpaRepository < User , Integer > {
/ * *
* 修改另外写方法
* @param id
* @param name
* @return
* /
@Modifying
@Query ( value = "update user set name = :name where id = :id" , nativeQuery = true )
int update ( @Param ( "id" ) Integer id, @Param ( "name" ) String name) ;
}
controller层
package com. fanney. springboot. controller;
import java. util. List ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. web. bind. annotation. GetMapping ;
import org. springframework. web. bind. annotation. PathVariable ;
import org. springframework. web. bind. annotation. RequestMapping ;
import org. springframework. web. bind. annotation. RequestParam ;
import org. springframework. web. bind. annotation. RestController ;
import com. fanney. springboot. entity. User ;
import com. fanney. springboot. service. UserService ;
/ * *
* 注
* @Controller
@ResponseBody
@RestController 是@ResponseBody 和@Controller 的组合注解。
*
* /
@RestController
public class TestController {
@Autowired
private UserService userService;
/ / @GetMapping 是@RequestMapping ( method = RequestMethod . GET ) 的缩写。该注解将HTTP Get 映射到 特定的处理方法上。
@GetMapping ( "/helloworld" )
public String helloworld ( ) {
return "helloworld" ;
}
/ * *
* 添加用户信息
* @return
* /
@RequestMapping ( "/save" )
public String save ( User user) {
user. setName ( "测试新增用户" ) ;
User result = userService. saveUser ( user) ;
if ( result. getName ( ) . equals ( user. getName ( ) ) ) {
return "新增用户成功" ;
} else {
return "新增用户失败" ;
}
}
/ * *
* @Description : 删除用户
* 访问地址:http : / / localhost: 8080 / delete? id= xx
* @param id 传入的参数: 用户ID
* @return
* @date : 2018 年3 月12 日
* /
@RequestMapping ( "/delete" )
public String delete ( @RequestParam Integer id) {
userService. delete ( id) ;
return "delete" ;
}
/ * *
* @Description : 根据用户ID 修改用户名
* 访问地址:http: / / localhost: 8080 / users/ update? id= xx& name= xx
* @param id 传入的参数: 用户ID
* @return
* @date : 2018 年3 月12 日
* /
@RequestMapping ( "/update" )
public String updateNameById ( @RequestParam Integer id, @RequestParam String name) {
System . out. println ( "修改用户" ) ;
userService. update ( id, name) ;
return "update" ;
}
/ * *
* @Description : 查找所有用户信息
* @return 返回用户列表 [ { "id" : 1 , "name" : "AAAA" } , { "id" : 2 , "name" : "BBBB" } , { "id" : 3 , "name" : "CCCC" } ]
* @date : 2018 年3 月12 日
* /
@RequestMapping ( "/findAll" )
public List < User > findAll ( ) {
System . out. println ( "查询所有用户" ) ;
List < User > userList = userService. findAll ( ) ;
for ( User user:userList ) {
System . out. println ( "用户:" + user) ;
}
return userList;
}
/ * *
* @Description : 根据用户ID 查询用户信息
* 访问地址:http: / / localhost: 8080 / users/ findById/ xx
* @param id
* @return json数据 { "id" : 1 , "name" : "AAAA" }
* @date : 2018 年3 月12 日
* /
@RequestMapping ( "/findById/{id}" )
public User findUserById ( @PathVariable Integer id) {
System . out. println ( "查询用户" ) ;
User user = userService. findOne ( id) ;
System . out. println ( "用户:" + user) ;
return user;
}
}