Spring Boot微操

一、创建Spring Boot项目

  1. 创建maven项目
  2. 添加springboot的parent
  3. 添加web的启动依赖
  4. 设置一个引导类
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
// 引导类不能放在根目录下
@SpringBootApplication
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        // 启动Spring boot 需要指定引导类
        // 为了能使用虚拟机指令启动,要将args传入run中
        SpringApplication.run( SpringBootDemoApplication.class, args );
    }
}
  1. 设置用maven插件启动
  <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>

        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
  1. 整合mybatis
	<dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
  1. 创建实体类、mapper和mapper.xml
  2. 创建application.properties或application.yml文件(默认会找一个application的文件)
  3. junit测试
	<dependency>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-test</artifactId>
	</dependency>
	<dependency>
	    <groupId>org.junit.platform</groupId>
	    <artifactId>junit-platform-launcher</artifactId>
	    <scope>test</scope>
	</dependency>
	<dependency>
	    <groupId>junit</groupId>
	    <artifactId>junit</artifactId>
	    <scope>test</scope>
	</dependency>

二、切换配置文件

1) yml 配置Bean注入

  1. 导入配置文件处理器:
<!--导入配置文件处理器,这样在对bean用properties或yml文件进行绑定的时候就会有提示-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
 </dependency>
  1. 创建一个Bean对象:
@Component // 将Person放入容器中
@ConfigurationProperties(prefix="person") // 必须具备Get Set方法
public class Person {
    private String name;
    private int age;
    private Date date;
    private String[] hobby;
    private Set<String> gfs;
    private Map<String, String> maps;
    private Dog dog;
    private List<Dog> dogs;
    // Getter & Setter
    // 重写toString()
}
class Dog {
    private String name;
    // Getter & Setter
    // 重写toString()
}

或者

@Component // 将Person放入容器中
public class Person {
	@Value("${person.name}")
    private String name;
    // Getter
    // 重写toString
}
  1. 创建一个yml文件
person:
  name: jack
  age: 25
  date: 2020/11/21 00:44:02
  hobby: [game,music]
  gfs: [a,b,c]
  maps:
    key1: value1
    key2: value2
  dog:
    name: 阿黄
  dogs:
    - name: 阿花
    - name: 阿云
  1. Test
//@RunWith(SpringRunner.class)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes= SpringBootDemoApplication.class)
public class BootTest {
    @Autowired
    private Person person;

    @Test
    public void test() {
        System.out.println(person.toString());
    }
}

2) 切换配置文件

  1. 配置文件的命名:配置文件的命名
  2. 指定要使用的配置文件:

1. 通过application.yml指定要使用application-uat.yml配置文件

spring:
  profiles:
    active: uat

2. 不创建默认的application.yml,而是在运行过程中通过参数来指定要使用的配置文件

  • 项目打包:
mvn clean package -Dmaven.test.skip=true 跳过test进行打包
  • 通过Java虚拟机参数:
java -jar -D--spring.profiles.active=dev SpringBootDemo-1.0-SNAPSHOT.jar
  • 通过SpringBoot参数指定:
java -jar SpringBootDemo-1.0-SNAPSHOT.jar --spring.profiles.active=dev

三、常见配置项

# ----------------------------------------
# WEB PROPERTIES
# ----------------------------------------

# EMBEDDED SERVER CONFIGURATION (ServerProperties)
server.port=8080 # server.port=8080
server.servlet.context-path= # Context path of the application.
# HTTP encoding (HttpEncodingProperties)
spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses.Added to the "Content-Type" header if not set explicitly.
# JACKSON (JacksonProperties)
spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance, `yyyy-MM-dd HH:mm:ss`.
# SPRING MVC (WebMvcProperties)
spring.mvc.servlet.load-on-startup=-1 # Load on startup priority of the dispatcher servlet.
spring.mvc.static-path-pattern=/** # Path pattern used for static resources.
spring.mvc.view.prefix= # Spring MVC view prefix.
spring.mvc.view.suffix= # Spring MVC view suffix.
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
spring.datasource.password= # Login password of the database.
spring.datasource.url= # JDBC URL of the database.
spring.datasource.username= # Login username of the database.

参考官网:Spring Boot Reference Guide

四、Spring Boot中使用Redis

<dependency>
  <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 转换格式 -->
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.46</version>
</dependency>
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Autowired
    private StringRedisTemplate template;

    @Override
    public List<User> selectAll() {
        // 将用户列表存入redis
        String userList = template.opsForValue().get("userList");
        List<User> listUser = new ArrayList<>();
        if (userList == null || "".equals(userList)) {
            listUser = userMapper.selectUserList();
            String userJson = JSONObject.toJSONString(listUser);
            template.opsForValue().set("userList",userJson);
        } else {
            listUser = (List<User>) JSONObject.parse(userList);
        }

        return listUser;
    }
}

五、日志

1. 默认日志

Spring Boot默认使用Logback,通过slf4j做进一步封装,之后底层日志换成log4j代码也无需改动。

public class
private Logger logger = LoggerFactory.getLogger(getClass());
---
---
logger.debug("访问了****");

application.yml

logging:
  level:
    root: info #不让控制台输出太多没用的信息
    com.ttc.controller: debug #只让controller输出debug级别的日志
  file:
  	# path: 
    name: ../../appdata/log/SpringBootDemo.log
    #path: 指定path时 名字默认为spring.log
    #name: 指定name可以同时指定目录
    max-size: 1MB #到达1MB切换文件

2. 切换至log4j

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--找到起步依赖 排除logback-->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
     <exclusions>
         <exclusion>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-logging</artifactId>
         </exclusion>
     </exclusions>
 </dependency>

log4j2.xml

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="INFO" monitorInterval="30">
    <Properties>
        <Property name="LOG_HOME">../../appdata/log</Property>
        <Property name="FILE_NAME">SpringBootDemo</Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d [%t] %-5p %c -%m%n"/>
        </Console>
        <!--滚动日志配置-->
        <RollingRandomAccessFile name="RollingAppender"
                                 fileName="${LOG_HOME}/${FILE_NAME}.log"
                                 filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i.log">
            <PatternLayout pattern="%d [%t] %-5p [%c] - %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="1 MB"/>
            </Policies>
            <!--同一文件夹下最多20个文件-->
            <DefaultRolloverStrategy max="20"/>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <!--info级别的日志打印到控制台-->
            <AppenderRef ref="Console"/>
        </Root>
        <Logger name="com.ttc.controller" level="debug">
            <!--debug级别的日志打印到日志文件-->
            <AppenderRef ref="RollingAppender"/>
        </Logger>
    </Loggers>
</Configuration>

六、Hanler(天坑!!!!)

实现功能:判断前台是否第一次登录,有无Cookie,无跳转到登录,有CooKie判断redis缓存中Cookie是否超时,超时跳转到登录。

这里真的是天坑SpringBoot的拦截器注入问题!!!
上代码:
handler

public class LoginInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private StringRedisTemplate template;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.debug("拦截器执行"+ request.getRequestURI() +"。。。");
        if (request.getRequestURI().contains("login")){
            logger.debug("拦截器放开。。。");
            return true;
        }
        User user = new User();
        String userInfo;
        // 获取cookie
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            logger.debug("用户未登录,跳转到登陆页面。。。");
            response.sendRedirect("/login.html");
            return false;
        }
        for (Cookie cookie: cookies) {
            if ("SESSION_ID".equals(cookie.getName())) {
                logger.debug("获取redis中的Session信息");
                if (cookie.getValue()==null || "".equals(cookie.getValue())) {
                    // 删除cookie
                    logger.debug("删除cookie。。。");
                    cookie.setMaxAge(0); // 删除cookie
                    response.sendRedirect("/login.html");
                    return false;
                }
                userInfo = template.opsForValue().get(cookie.getValue());
                if (userInfo == null || "".equals(userInfo)) {
                    logger.debug("cookie中"+cookie.getValue());
                    // 删除cookie
                    logger.debug("redis中"+userInfo);
                    logger.debug("删除cookie。。。");
                    cookie.setMaxAge(0); // 删除cookie
                    response.sendRedirect("/login.html");
                    return false;
                }
                logger.debug("userInfo from redis " + userInfo);
                user = JSON.parseObject(userInfo, User.class);
                break;
            }
        }

        if (user == null) {
            logger.debug("用户未登录,跳转到登陆页面。。。");
            response.sendRedirect("/login.html");
            return false;
        } else {
            return true;
        }
    }
}

注册类
在这里插入图片描述

要使用Handler还要把注册Handler,这里才是天坑!!!!
网上说解决拦截器注入失败的原因,要注册Bean或者配置启动类里面的包扫描器的,真的理解原理了才知道,到底是怎么回事。

  • 首先,启动类的问题,启动类不会扫描他的父类包,所以启动类一定放在所有类的最外层。

方法:
如果启动类所在的包为:com.ttc,则只会扫描com.ttc包及其所有子包,如果service或dao所在包不在com.ttc及其子包下,则不会被扫描!
只要在启动类前面加上:
@SpringBootApplication(scanBasePackages = “com.*”)

  • 其次,要使拦截器中能够注入,一定要在注册类中把拦截器注入到容器中。

方法两点:

  1. 手动创建Bean,用loginInterceptor()方法返回的拦截器放在注册器中
  2. 在拦截器上加@Component,并在注册器中@Autowired
    目的:无外乎就是保证整个容器中单例并已经被注入到容器中

七、异常处理

通过AOP实现异常捕捉统一处理:

/**
 * 通过AOP切面监听全局的错误信息,进行统一的错误处理
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    //指定该ExceptionHandler能处理的类型
    @ExceptionHandler(value = TtcException.class)
    public String handler(TtcException e, Model model) {
        logger.error(e.getMessage());
        model.addAttribute("errCode", e.getErrCode());
        model.addAttribute("errMsg", e.getErrMsg());
        return "error";
    }
}

八、整合dubbo

  1. 创建空的maven项目和子项目
    maven项目和子项目
  • 说明:
    SpringBoot_Dubbo:作为整个项目
    common:存放Service等公共类
    consumer:作为服务消费方
    provider:作为服务提供方
  • pom:
    在consumer和provider中引入common:
    pom
  1. common中创建公共Service 在这里插入图片描述
  • 定义接口:
public interface UserService {
    String getNameById(int id);
}
  1. provider
  • 创建文件:
    在这里插入图片描述
  • 实现接口:
@Service // org.apache.dubbo.config.annotation.Service包下的注解
public class UserServiceImpl implements UserService {
    @Override
    public String getNameById(int id) {
        if (id == 1) {
            return "jerry";
        }
        if (id == 2) {
            return "tom";
        }
        return "error";
    }
}
  • 服务注册:
    ProviderApplication.java
@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.ttc.service.impl")
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
  • 配置文件:
    application.yml
dubbo:
  application:
    name: user-service # 服务提供方的名字
    qos-enable: false
  registry:
    protocol: zookeeper
    address: 192.168.1.214:2181
  protocol:
    name: dubbo
    port: 28888
  1. consumer
  • 创建文件:
    在这里插入图片描述
  • Controller:
    UserController.java
@RestController
public class UserController {

    @Reference //org.apache.dubbo.config.annotation.Reference;
    private UserService userService;

    @RequestMapping("/user/{id}")
    public String getNameById(@PathVariable int id) {
        String name = userService.getNameById(id);
        return name;
    }
}
  • 启动类:
    ConsumerApplication.java
@SpringBootApplication
// 这里面不用注册服务,消费方要访问服务
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}
  • 配置文件:
dubbo:
  application:
    name: user-service # 服务提供方的名字
    qos-enable: false
  registry:
    protocol: zookeeper
    address: 192.168.1.214:2181
    #集群写法 address: zookeeper: //192.168.1.214:2181?backup=192.168.1.215,192.168.1.216

!注意:

如果报错连接失败,可能是zookeeper中的配置有问题,也可能是依赖的jar包默认的超时时间有问题
解决方案:

  1. 在zoo.cfg中修改tickTime=20000
  2. 在yml中增加:
dubbo:
	registry:
		timeout: 20000
	config-center:
		timeout: 20000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值