源生的Servlet、Listener、Filter:
首先需要一个@WebServlet
注解然后再SpringBootapplication注解上加上@ServletComponentScan(basePackages = "cqupt.boot")//将servlet扫描进去
这个注解(这个对于下面的监听器和过滤器同理),这两个一起用就达到源生servlet的效果了。
@WebServlet(urlPatterns = "/my")//servlet的访问地址
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("666");
}
}
Filter
@Slf4j
@WebFilter(urlPatterns = {"/css/*","/images/*"})//过滤器 servlet是单星写法,双星是spring写法
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化完成");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("MyFilter工作");
}
@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
Listener
@Slf4j
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("监听到项目销毁");
}
}
可以将以上的注解都不要,通过配置Configuration来往容器中添加组件来实现。
//proxyBeanMethods =true 保证依赖的组件始终是单实例的
@Configuration
public class MyRegisterConfig {
// //注册Servlet
@Bean
public ServletRegistrationBean myServlet(){
MyServlet myservlet=new MyServlet();
return new ServletRegistrationBean(myservlet,"/my","/my2");
}
@Bean
public FilterRegistrationBean myListener(){
MyFilter myFilter=new MyFilter();
FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/my2"));
return filterRegistrationBean;
// return new FilterRegistrationBean(myFilter,myServlet());//拦截myServlet的路径,他是啥路径就拦截什么
}
@Bean
public ServletListenerRegistrationBean mylistener(){
MyServletContextListener myServletContextListener=new MyServletContextListener();
return new ServletListenerRegistrationBean(myServletContextListener);
}
}
数据库
数据库所需依赖添加。注意!!,虽然Spring Boot有版本仲裁,但是mysql的版本不要高于本机所安装的版本。
第一种直接引入依赖的具体版本。(利用的Maven的就近依赖原则)
<!-- jdbc开发-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql数据库 本机是8.0.21-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
第二种。
重新声明版本号,通过ctrl+spring-boot-starter-parent和ctrl+spring-boot-dependencies进去查看它的命名属性。例如mysql就是<mysql.version>8.0.21</mysql.version>,所以我们把这个重新声明即可。(利用的是Maven的就近优先原则)
<properties>
<mysql.version>8.0.21</mysql.version>
</properties>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Spring Boot底层配置了Hikari的。
在.yaml文件中配置。(mysql8.0以上)
# 配置数据库
spring:
datasource:
url: jdbc:mysql://localhost:3306/xxxxxx?useSSL=false&serverTimezone=UTC
username: xxxxxxx
password: xxxxxxxx
driver-class-name: com.mysql.cj.jdbc.Driver
#开启sql监控和防火墙
filters: stat,wall
测试是否与数据库连接上了,查询一下数据库中该表记录条数。
Long length= jdbcTemplate.queryForObject("select count(*) from city",Long.class);
System.out.println(length);
Druid
设置监控页面登录信息,监控Web的监控数据
@Configuration
public class MyDataSourceConfig implements WebMvcConfigurer {
/**
* 配置servlet的监控页
* 添加监控页的登录信息
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
StatViewServlet statViewServlet = new StatViewServlet();
ServletRegistrationBean<StatViewServlet> servletRegistrationBean=
new ServletRegistrationBean<StatViewServlet>(statViewServlet,"/druid/*");
//添加登录页面的登录名和密码
servletRegistrationBean.addInitParameter("loginUsername","syf");
servletRegistrationBean.addInitParameter("loginPassword","123456");
return servletRegistrationBean;
}
//给容器中放一个我们的数据源,以及配置属性
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource Druid() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
//开启监控功能 和 防火墙功能
// druidDataSource.setFilters("stat,wall");
// druidDataSource.setUsername("root");
// druidDataSource.setPassword("19980605");
// druidDataSource.setDriver(new Driver());
// druidDataSource.setUrl("jdbc:mysql://localhost:3306/syfwfl?useSSL=false&serverTimezone=UTC");
return druidDataSource;
}
/**
* 配置WebStatFilter,用于采集web-jdbc关联监控的数据。
* @return
*/
@Bean
public FilterRegistrationBean DruidWebStatFilter(){
WebStatFilter webStatFilter=new WebStatFilter();
FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean(webStatFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
servlet访问测试,访问界面为localhost:端口号/druid
@Autowired
JdbcTemplate jdbcTemplate;
@ResponseBody//响应出去,就不跳转页面
@GetMapping("/sql")
public String sql(){
Long length= jdbcTemplate.queryForObject("select count(*) from city",Long.class);
assert length != null;
return length.toString();
}
以上都可在.yaml配置文件中设置,简化操作。
# 配置数据库
spring:
datasource:
url: jdbc:mysql://localhost:3306/syfwfl?useSSL=false&serverTimezone=UTC
username: root
password: 19980605
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
#开启监控和防火墙
filters: stat,wall # 底层开启功能,监控和防火墙
#监控这个包下的所有东西
aop-patterns: cqupt.boot.* #监控SpringBean
stat-view-servlet: #配置监控功能
#默认是false所以需要自己打开
enabled: true
#监控页面的登录名和密码
login-username: admin
login-password: admin
#重置按钮
reset-enable: false
web-stat-filter: #监控web
enabled: true
url-pattern: /*
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
filter:
stat: #对上面的filters详细配置
#是否记录慢sql语句
log-slow-sql: true
slow-sql-millis: 1000
enabled: true
wall: #对上面的filters详细配置
enabled: true
config:
#相当于所有的更新数据库的操作全都会被拦截
update-allow: false
整合Mybatis
1、引入依赖
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
2、编写mapper接口
3、编写sql映射文件并绑定mapper接口
4、在application.yaml指定mapper配置文件的位置,以及指定全局配置文件的信息(建议不写全局配置文件,直接在application.yaml的mybatis.configuration中配置)
注意:在实现里面加mapper的,在用到sql的地方加实现的@Autowire
可以通过注解也可以用mapper,混合使用。不用配置文件时,在方法上标注@Service
mapper
@Mapper
public interface CityMapper {
@Select("select*from city where id=#{id}")
@Option(useGeneratedKeys=true,keyProperty="id")//返回自增主键,相当于mapper里面的功能属性
City Select(long id);
}
实现
@Service
public class CityImpl{
@Autowired
CityMapper cityMapper;
public City Select(long id) {
return cityMapper.Select(id);
}
}
用
@Autowired
CityImpl city;
@ResponseBody
@RequestMapping("/acc")
public City getById(@RequestParam("id")long id){
return city.Select(id);
}
#配置mybatis规则
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置
mapper-locations: classpath:mybatis/mapper/*.xml #sql映射文件位置
#可以不写全局配置文件,所有的全局配置文件都放在configuration里面
#configuration和上面的这两个不能同时存在
configuration:
map-underscore-to-camel-case: true
Redis
依赖
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
redis的yaml文件配置
#redis
redis:
#redis连接设置 举例 user:用户名 password:密码 exacple.com:公网地址 63379:端口号
url: redis://user:password@exacple.com:63379
#不用上面的这种方式,还可以以这种方式
host: exacple.com
port: 63379
password: user:password
单元测试
如果在测试单元标注了@Transactional
标签,在测试完成后会自动回滚。在测试单元需要用到类,直接定义了之后@Autowire
就行。
/**
* SpringBootTest这个注解能让测试也拿到容器中的组件
* ExtendWith(SpringExtension.class) 想用外部的
*/
@SpringBootTest
@DisplayName("junit5功能测试类")
public class Mytest {
/**
* @Disabled/ 使当前这个方法不运行
* @DisplayName 设置这个测试的名字
*/
@Disabled
@Test
@DisplayName("测试DisplayName")
void DisplayName(){
System.out.println(1);
}
/**
* 每个方法执行之前
*/
@BeforeEach
void testBeforeEach(){
System.out.println("打印就要开始了");
}
/**
* 每个方法执行完之后
*/
@AfterEach
void testAfterEach(){
System.out.println("打印结束了");
}
/**
* 所有执行完之前
*/
@BeforeAll
static void testBeforeAll(){
System.out.println("所有都要开始了");
}
/**
* 所有执行完之后
*/
@AfterAll
static void testAfterAll(){
System.out.println("所有都要结束了");
}
/**
* 规定方法超时间
* @throws InterruptedException
*/
@Timeout(value = 1000,unit = TimeUnit.MILLISECONDS)
@Test
void testTimeout() throws InterruptedException {
Thread.sleep(1001);
}
/**
* 重复测试5次
*/
@RepeatedTest(5)
@Test
void testMany(){
System.out.println("haha");
}
}
断言测试
/**
* 测试简单断言
* 前面断言失败,后面的代码都不会实现
*/
@Test
@DisplayName("断言")
void testSimpleAssertions(){
int cal=jisuan(1,5);
Assertions.assertEquals(6,cal,"业务逻辑失败");
Object obj1=new Object();
Object obj2=new Object();
Assertions.assertEquals(obj1,obj2,"不是一个对象");
}//模拟业务
int jisuan(int i,int j){
return i+j;
}
@Test
@DisplayName("断言")
void array(){
Assertions.assertEquals(new int[]{1,2},new int[]{1,2},"数组不相同");
}//模拟业务
/**
* 组合断言
*/
@Test
@DisplayName("组合断言")
void All(){
assertAll("test",()-> assertTrue(true&true),
()-> assertEquals(1,2));
}
/**
* 异常断言
*/
@Test
@DisplayName("异常断言")
void exception(){
//断言要抛异常,成功断言了就没有异常,否则抛异常
assertThrows(ArithmeticException.class,()->{int i=10/2;},"业务居然正常?");
}
/**
* 快速失败
*/
@Test
@DisplayName("快速失败")
void testFail(){
if (true)
fail("测试失败");
}
前置条件
/**
* 测试前置条件
* 如果失败直接跳过当前要执行的
*/
@DisplayName("测试假设是否为true")
@Test
void testassumption(){
Assumptions.assumeTrue(false,"不为true");
System.out.println("真的是");
}
嵌套测试
外层的test不能驱动内层的BeforeEach/AfterEach还有all这种。
内层的test可以驱动外层的。
参数化测试
/**
* 参数化测试
* 直接给参数
*/
@ParameterizedTest//表示当前为参数化测试
@DisplayName("参数化测试")
@ValueSource(ints = {1,2,3,4,5,6})//传值
void testParameter(int num){
System.out.print(num);
}
/**
* 从方法中得到参数
* @param num
*/
@ParameterizedTest//表示当前为参数化测试
@DisplayName("参数化测试")
@MethodSource("stringProvider")//从方法中获得参数
void testParameter2(String num){
System.out.print(num);
}
static Stream<String> stringProvider(){
return Stream.of("apple","banana","cqupt");
}
Actuator
# actuator management是所有actuator的配置
# 访问路径 http://localhost:8081/actuator/*,改变*可以看相应的
# 例如:http://localhost:8081/actuator/beans
management:
endpoints:
enabled-by-default: true # 默认就是true
web:
exposure:
#默认是info 和 health
include: '*' # 以web方式暴露所有端点
Profile
可以选择对应的场景进行文件配置
server.port=8081
#激活生产环境,有同名项时,就看激活的配置文件里面的内容
#打包成jar包后还可以通过命令行修改
#java -jar xxx.jar --spring.profiles.active=test --person.name=haha就能直接修改启动
#spring.profiles.active=test #指定这个配置文件生效 test为 application-test.yaml的-后面的内容
#也可以创组设定环境 每次启动就启动这个组别,以下就是启动myprod这个组,group后面那个为组名
spring.profiles.active=myprod
spring.profiles.group.myprod[0]=prod
spring.profiles.group.myprod[1]=syf
spring.profiles.group.mytest[0]=test
profile也可直接获取系统变量也是直接通过${}获得。
程序可通过这个代码查看:
ConfigurableApplicationContext run = SpringApplication.run(ComBootProfileApplication.class, args);
ConfigurableEnvironment environment=run.getEnvironment();
Map<String,Object> systemEnvironment= environment.getSystemEnvironment();
Map<String,Object> systemProperties= environment.getSystemProperties();
System.out.println(systemEnvironment);
System.out.println(systemProperties);