解决方式
重新更换配置文件修改端口打包
通过临时属性配置新端口
更换配置文件
通过临时属性修改8080端口
java -jar 项目.jar --server.port=8081
添加web部分使用 dbug 日志
java -jar springboot-ssm-0.0.1-SNAPSHOT.jar --server.port=8081 --logging.level.org.springframework.web=debug
文档地址
Core Features
优先级说明
注意:从上往下优先级越来越高
开发中使用的是3,刚才使用命令行使用的是11
在开发中,会遇见自己定义属性名和系统变量名一致的情况,导致自己配置的数据被覆盖
user:
name: sy
实际取出来值是电脑用户名称值
以后如果你们再开发中,自己定义变量但是发现取出来的不是想要的值时,优先考虑属性优先级问题
了解内容
public static void main(String[] args) {
args[0] = "--server.port=9999";
SpringApplication.run(SpringbootSsmApplication.class, args);
}
问题:如果需要修改的配置很多,那么使用这种手动输入的方式很容易出错,可以通过配置文件解决
类路径下配置文件
开发人员使用
类路径下config目录下配置文件
项目经理、技术经理使用
程序包所在目录中配置文件
运维人员、架构师使用
程序包所在目录中config目录下配置文件
最高等级,技术总监
应用场景
A 开发项目时候使用的是类路径下配置文件
A 开发完成之后,需要部署到测试环境,需要修改配置
测试B测试出问题,A 需要去修改bug(需要把配置修改回来)
测试没问题之后,A需要再次修改生产环境的配置
类路径下配置文件:就是我们默认使用的配置文件,优先级是最低
类路径下config目录下配置
程序包所在目录中配置文件
程序包所在目录中config目录下配置文件
通过名称设置图示
绑定类
@Data
@Component
@ConfigurationProperties(prefix = "dbconfig")
public class DbConfig {
private String url;
private String username;
}
dbconfig.url=123123
dbconfig.username=sy
加入如下的依赖,可以解决提示问题
org.springframework.boot
spring-boot-configuration-processor
配置德鲁伊连接池
com.alibaba
druid
1.2.15
@Bean
@ConfigurationProperties(prefix = "druid")
public DruidDataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Component
@ConfigurationProperties(prefix = "dbConfig")
public class DbConfig {
private String url;
private String username;
}
dbConfig.url=123123
dbConfig.user_name=sy
db-config.PASSWORD=12345223123
db-config.home-address=bj
@Data
@Component
@ConfigurationProperties(prefix = "db-config")
public class DbConfig {
private String url;
private String username;
private String password;
private String homeAddress;
}
db-config.timeout=600
@DurationUnit(ChronoUnit.HOURS)
private Duration timeout;
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize datasize;
javax.validation
validation-api
@Max(value = 9999,message = "无效的配置")
@Min(value = 80,message = "无效的配置")
private int port;
开发环境
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/springboot_ssm
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
测试环境
spring:
datasource:
druid:
url: jdbc:mysql://测试环境服务器地址:3306/springboot_ssm
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
生产环境
spring:
datasource:
druid:
url: jdbc:mysql://阿里云地址:3306/springboot_ssm
username: root
password: adminroot
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 8082
server:
port: 8082
---
server:
port: 8888
spring:
profiles: dev
server:
port: 8082
---
spring:
profiles: test
server:
port: 8888
---
spring:
profiles: prod
server:
port: 9999
spring:
profiles:
active: test
---
#开发环境
spring:
profiles: dev
server:
port: 8082
---
#测试环境
spring:
profiles: test
server:
port: 8888
---
#生产环境
spring:
profiles: prod
server:
port: 9999
spring.profiles.active=dev
# 应用名称
spring.application.name=springboot-dev
# 应用服务 WEB 访问端口
server.port=8082
# 应用名称
spring.application.name=springboot-test
# 应用服务 WEB 访问端口
server.port=8888
# 应用名称
spring.application.name=springboot-prod
# 应用服务 WEB 访问端口
server.port=9999
spring:
profiles:
active: test
server:
port: 8082
server:
port: 8888
server:
port: 8888
背景:因为全部把配置配置到一个大文件里面,很多很乱,所以有的公司就使用拆分配置的方式来解决独立的配置耦合太严重的问题
spring:
profiles:
active: dev
include: devmysql,devredis
spring:
profiles:
active: dev
group:
"dev": devmysql,devredis
"test": testmysql,testredis
实际开发中,多环境开发很常用
dev 开发环境
test 测试环境
prod 生产环境
@RestController
public class LogController {
public static final Logger log = LoggerFactory.getLogger(LogController.class);
@GetMapping("/index")
public String index(){
log.info("请求info 信息");
log.debug("请求debug 信息");
log.warn("请求warn 信息");
log.error("请求错误信息");
return "OK";
}
}
logging:
level:
root: info
logging:
# 设置组
group:
controller: cn.sycoder.springbootlog.controller
level:
root: info
# cn.wjcoder.springboot-log.controller: warn
controller: info
导入依赖
org.projectlombok
lombok
@Slf4j
@RestController
public class LogController {
@GetMapping("/index")
public String index(){
log.info("请求info 信息");
log.debug("请求debug 信息");
log.warn("请求warn 信息");
log.error("请求错误信息");
return "OK";
}
}
logging:
pattern:
console: "%d %clr(%-5p){yellow} %clr(${pid}){magenta} ---[%20t] %-40.40c : %m %n"
注意:指定名称输出的优先级会更高
注意版本信息,如果版本太低的时候不支持 logback
按照日期的格式拆分
wj2023-03-24-1.log
wj2023-03-24-2.log
拆分日志文件
logdir: D:\workspace_idea\SpringBoot\springboot-log\
logging:
logback:
rollingpolicy:
max-file-size: 2KB
file-name-pattern: ${logdir}wj-%d{yyyy-MM-dd}-%i.log
file:
name: ${logdir}wj.log
添加依赖
org.springframework.boot
spring-boot-devtools
true
com.alibaba
druid-spring-boot-starter
1.2.15
org.projectlombok
lombok
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.2.2
com.mysql
mysql-connector-j
runtime
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
@Mapper
@Repository
public interface ItemMapper {
@Insert("insert into item(name,remark) value(#{name},#{remark})")
boolean insert(Item item);
@Select("select * from item where id = #{id}")
public Item getById(Long id);
}
@RestController
@RequestMapping("/item")
@Slf4j
public class ItemController {
@Autowired
ItemMapper mapper;
@GetMapping("/{id}")
public Item getById(@PathVariable Long id){
return mapper.getById(id);
}
@PostMapping
public boolean save(@RequestBody Item item){
log.info("获取方法的入参为:{}",item);
return mapper.insert(item);
}
}
@Data
public class Item {
private Long id;
private String name;
private String remark;
}
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/springboot_ssm
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
实际测试没有走mvcweb环境,是直接调用接口的
@SpringBootTest
class SpringbootTestApplicationTests {
@Autowired
ItemController controller;
@Test
public void testSave(){
Item item = new Item();
item.setName("键盘");
item.setRemark("1000元");
controller.save(item);
}
}
数据是实际添加到数据库的,应该回滚
缺乏实际返回值的对比
添加如下注解
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Test
public void getById(@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求的
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get("/item/29");
mvc.perform(builder);
}
对于请求结果的比对
@Test
public void getById(@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求的
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get("/item/20");
ResultActions actions = mvc.perform(builder);
//定义请求结果的预期值
ResultMatcher ok = MockMvcResultMatchers.status().isOk();
actions.andExpect(ok);
}
@Test
public void getById(@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求的
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get("/item/20");
ResultActions actions = mvc.perform(builder);
//定义请求结果的预期值
ResultMatcher ok = MockMvcResultMatchers.status().isOk();
actions.andExpect(ok);
//比较你实际结果值
ResultMatcher json = MockMvcResultMatchers.content().json(
"{\n" +
" \"id\": 20,\n" +
" \"name\": \"笔记本电脑\",\n" +
" \"remark\": \"1二手电脑只要一千块\"\n" +
"}"
);
actions.andExpect(json);
}
@Test
public void getByIdHeader(@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求的
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get("/item/20");
ResultActions actions = mvc.perform(builder);
//比较响应头
ResultMatcher header = MockMvcResultMatchers.header().string("Content-Type","application/json");
actions.andExpect(header);
}
@Test
public void postItemBoolean(@Autowired MockMvc mvc,@Autowired ItemTest itemTest) throws Exception {
Item item = new Item();
item.setName("键盘111");
item.setRemark("1000元1111");
System.out.println("==================");
System.out.println(itemTest);
//创建虚拟请求的
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.post("/item");
builder.contentType("application/json");
builder.accept(MediaType.APPLICATION_JSON);
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(itemTest);
builder.content(s);
ResultActions actions = mvc.perform(builder);
MvcResult mvcResult = actions.andReturn();
System.out.println(mvcResult.getResponse().getStatus());
ResultMatcher ret = MockMvcResultMatchers.content().string("true");
actions.andExpect(ret);
}
testcase:
item:
name: ${random.int(5)}
remark: ${random.int(5)}
@ConfigurationProperties(prefix = "testcase.item")
@Component
@Data
public class ItemTest {
private String name;
private String remark;
}
使用注解 rollback + Transactional
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//开启虚拟mvc的调用
@AutoConfigureMockMvc
@Rollback
@Transactional
class SpringbootTestApplicationTests {
}
开启事务和回滚之后,数据就不会写入数据库了。
application-dev.yml
server:
port: 8083
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/springboot_project
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
logging:
level:
root: info
application-test.yml
server:
port: 8088
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/springboot_project
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
logging:
level:
root: info
application.yml
spring:
profiles:
active: dev
@Data
public class Item {
private Long id;
private String name;
private String remark;
private String type;
}
@Mapper
@Repository
public interface ItemMapper {
@Insert("insert into items(name,type,remark) value(#{name},#{type},#{remark})")
int save(Item item);
@Update("update items set name =#{name},type=#{type},remark=#{remark} where id=#{id}")
int update(Item item);
@Select("select * from items where name like concat('%',#{name},'%')")
List- listByName(@Param("name") String name);
@Select("select * from items")
List
- list();
@Delete("delete from items where id = #{id}")
int delete(@Param("id") Long id);
}
service 接口设计
public interface IItemService {
/**
* 添加操作
* @param item
* @return
*/
boolean save(Item item);
/**
* 删除操作
* @param id
* @return
*/
boolean delete(Long id);
/**
* 查询操作
* @param name
* @return
*/
List- list(String name);
/**
* 修改操作
* @param item
* @return
*/
boolean update(Item item);
}
serviceimpl
@Service
@Transactional
public class ItemServiceImpl implements IItemService {
@Autowired
ItemMapper mapper;
@Override
public boolean save(Item item) {
return mapper.save(item) > 0;
}
@Override
public boolean delete(Long id) {
return mapper.delete(id) > 0;
}
@Override
public List- list(String name) {
if(name != null && !"".equals(name.trim())){
return mapper.listByName(name);
}
return mapper.list();
}
@Override
public boolean update(Item item) {
return mapper.update(item) >0;
}
}
@Data
@Builder
public class Resp {
private int code;
private String msg;
private Object data;
}
public interface RespCode {
int SAVE_SUCCESS_CODE = 20000;
int UPDATE_SUCCESS_CODE = 20010;
int DELETE_SUCCESS_CODE = 20020;
int List_SUCCESS_CODE = 20040;
int SAVE_FAIL_CODE = 20001;
int UPDATE_FAIL_CODE = 20011;
int DELETE_FAIL_CODE = 20021;
int LIST_FAIL_CODE = 20041;
}
@RestController
@Slf4j
@RequestMapping("/item")
public class ItemController {
@Autowired
IItemService service;
@PostMapping
public Resp save(@RequestBody Item item){
log.info("请求save方法的入参为:{}",item);
boolean ret = service.save(item);
return Resp.builder().
code(ret?RespCode.SAVE_SUCCESS_CODE:RespCode.SAVE_FAIL_CODE)
.data(ret)
.build();
}
@PutMapping
public Resp update(@RequestBody Item item){
log.info("请求update方法的入参为:{}",item);
boolean ret = service.update(item);
return Resp.builder().
code(ret?RespCode.UPDATE_SUCCESS_CODE:RespCode.UPDATE_FAIL_CODE)
.data(ret)
.build();
}
@DeleteMapping("/{id}")
public Resp delete(@PathVariable Long id){
log.info("请求delete方法的入参为:{}",id);
boolean ret = service.delete(id);
return Resp.builder().
code(ret?RespCode.DELETE_SUCCESS_CODE:RespCode.DELETE_FAIL_CODE)
.data(ret)
.build();
}
@GetMapping
public Resp list(@RequestParam(required = false) String name){
log.info("请求list方法的入参为:{}",name);
List- list = service.list(name);
return Resp.builder().
code(RespCode.List_SUCCESS_CODE)
.data(list)
.build();
}
}
create table items
(
id bigint auto_increment
primary key,
name varchar(64) null,
type varchar(64) null,
remark varchar(128) null
);
rz 命令找到自己的jar ,上传到 /opt/springboot-project
启动mysql 服务器
./mysqld
使用临时配置的方式修改端口信息
java -jar springboot-project-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --server.port=8080
目前存在问题:关闭窗口后程序停止了
以后台的方式启动
nohup java -jar springboot-project-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --server.port=8080 &
nohup (no hang up)
表示关闭终端的时候程序也能继续运行 & 来搭配
自定义日志文件名称
nohup java -jar springboot-project-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --server.port=8080 >sy.log 2>&1 &
2>&1 &
0 表示 stdin 标准输入
1 表示 stdout 标准输出
2 表示 stderr 标准错误
标准输出到文件 >filename = 1>filename 错误也要输出到文件 2>&1>filename >sy.log 2>&1 = 2>&1>sy.log
& :放到命令行结尾,表示以后台运行
常用指令(建议熟练):
linux
开放端口
杀进程
启动程序
上传包
下载包
查看日志
删除文件
解压文件