总结
面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。
我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
面试题及解析总结
大厂面试场景
知识点总结
创建`com.service.impl.UserServiceImpl` 类,实现`IUserService` 接口:
package com.service.impl;
import com.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service(“userService”)
public class UserServiceImpl implements IUserService {
private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
@Override
public boolean login(String username, String password) {
logger.info("用户登录:[username:{}, password:{}]", username, password);
if (username != null && password != null && username.equals(password)) {
logger.info("用户校验通过。[username:{}]", username);
return true;
}
logger.info("用户校验失败![username:{}]", username);
return false;
}
}
创建 `Spring` 配置文件,配置注解扫描 `com.service.impl` 包,并引入 `spring-provider.xml` 文件:
<?xml version="1.0" encoding="UTF-8"?>
**注意: 这里不要写成 `com.service.impl`.否则无法成功扫描!**
创建 `spring-provider.xml` 文件,它是 `dubbo` 的主要配置文件。
<?xml version="1.0" encoding="UTF-8"?>
可以看到这里有几个关键参数:`application`、`registry`、`protocol`、`service`。
* `application` 指当前应用名称,主要用来给`zookeeper`注册中心计算应用间依赖关系。
* `registry` 用来声明一个注册中心,这里声明了一个id 为dubbodemo的注册中心,地址是本地服务器的 `2181` 端口(这里要与 `zookeeper` 配置文件的 `clientPort` 属性值一致)。
* `protocol` 指该应用使用 `dubbo` 协议在 `28080` 端口暴露服务,其他应用可以通过这个接口调用服务。
* `service` 用来声明需要暴露的服务接口,这里暴露了IUserService 接口,并将接口注册到 id 为 dubbodemo 的注册中心,它引用了 `Spring` 中名为 userService 的类,超时时间为 3 秒。
到这里 `provider` 提供者的配置基本上完成,但我们还需要写一个启动类将 `provider` 启动起来提供服务。
创建`com.util.BeanFactoryUtil.java`,是加载 `Spring` 的工具类:
package com.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanFactoryUtil {
private static ApplicationContext ctx_producer = null;
public final static String ApplicationContextRoot = “”;
public final static String ApplicationContextPath = ApplicationContextRoot + “applicationContext.xml”;
public static void init() {
if (ctx_producer == null) {
synchronized (BeanFactoryUtil.class) {
if(ctx_producer == null){
String[] configLocations = new String[]{ApplicationContextPath};
ctx_producer = new ClassPathXmlApplicationContext(configLocations);
}
}
}
}
public static ApplicationContext getContext() {
init();
return ctx_producer;
}
}
创建`com.chanshuyi.util.SystemDetails.java`,用于输出系统信息:
package com.util;
import java.text.SimpleDateFormat;import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class SystemDetails {
/**
* 输出系统基本信息
*/
public static void outputDetails() {
timeZone();
currentTime();
os();
}
/\*\*
* 输出系统时区
*/
private static void timeZone() {
Calendar cal = Calendar.getInstance();
TimeZone timeZone = cal.getTimeZone();
System.out.println(“系统时区:” + timeZone.getDisplayName());
}
/\*\*
* 输出系统时间
*/
private static void currentTime() {
String fromFormat = “yyyy-MM-dd HH:mm:ss”;
SimpleDateFormat format = new SimpleDateFormat(fromFormat);
Date myDate = new Date();
System.out.println(“系统时间:” + format.format(myDate));
}
/\*\*
* 输出系统基本配置
*/
private static void os() {
String osName = System.getProperty(“os.name”); //操作系统名称
System.out.println(“当前系统:” + osName);
String osArch = System.getProperty(“os.arch”); //操作系统构架
System.out.println(“当前系统架构” + osArch);
String osVersion = System.getProperty(“os.version”); //操作系统版本
System.out.println(“当前系统版本:” + osVersion);
}
}
创建`com.Launcher.java`,用于启动 `provider` 服务,是启动入口:
package com;
import com.util.BeanFactoryUtil;
import com.util.SystemDetails;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Launcher {
private static Log logger = LogFactory.getLog(Launcher.class);
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(“=“);
System.out.println(” Core包启动 “);
SystemDetails.outputDetails();
System.out.println(”=”);
getLocalip();
// 初始化spring
logger.info("开始初始化core服务");
BeanFactoryUtil.init();
try{
System.in.read();
} catch (Exception e) {
e.printStackTrace();
}
}
/\*\*
* 取得本机ip地址 注意:Spring RmiServiceExporter取得本机ip的方法:InetAddress.getLocalHost()
*/
private static void getLocalip() {
try {
System.out.println("服务暴露的ip: "
+ java.net.InetAddress.getLocalHost().getHostAddress());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
到这里 `provider` 模块配置结束。我们运行 Launcher.main() 方法启动服务,并打开 `zookeeper` 注册中心,启动 `provider` 服务。
接下来我们编写 `consumer` 代码。
在 `consumer` 的 `pom.xml` 中导入 `Spring`、`dubbo`、`interface` 模块依赖。
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>3.8.1</junit.version>
<springframework.version>4.1.6.RELEASE</springframework.version>
<commonsLogging.version>1.2</commonsLogging.version>
<dependencies>
<!-- \*\*\*\*\*\*\*\*\*\*\*\*\* Spring 依赖 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\* -->
<!-- 添加Spring-core包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-tx包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring ORM 相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-jdbc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--添加spring-web包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- 添加spring-context包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commonsLogging.version}</version>
</dependency>
<!--添加aspectjweaver包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<!-- \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* /Spring 依赖 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* -->
<!-- \*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Dubbo 依赖 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.3</version>
<exclusions>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!-- \*\*\*\*\*\*\*\*\*\*\*\*\* /Dubbo 依赖 \*\*\*\*\*\*\*\*\*\*\*\*\* -->
<!-- \*\*\*\*\*\*\*\*\*\*\*\*\*\*\* interface 依赖 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* -->
<dependency>
<groupId>com.chanshuyi.DubboDemo</groupId>
<artifactId>interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* /interface 依赖 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* -->
创建类 `com.UserServiceConsumer.java`
package com;
import com.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by Administrator on 2016/1/19.
*/public class UserServiceConsumer {
private static Logger logger = LoggerFactory.getLogger(UserServiceConsumer.class);
public static void main(String args[]) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserService userService = (IUserService) ctx.getBean("userService");
logger.info("执行结果:" + userService.login("hello", "hello"));
}
}
配置 `applicationContext.xml` 文件以及 `spring-consumer.xml` 文件:
<?xml version="1.0" encoding="UTF-8"?>
`spring-consumer.xml` 配置
<?xml version="1.0" encoding="UTF-8"?>
`spring-consumer.xml` 的配置大致与 `spring-provider.xml` 相同,只是 `dubbo:service` 节点换成 `dubbo:reference` 节点。`<dubbo:reference>` 节点表示引用一个服务,其中 id 表示该服务的唯一标识,可以用该 id 实现 `IOC` 注入,`interface` 表示引用的服务接口。
到这里 `consumer` 模块配置基本结束。我们运行UserServiceConsumer.main()方法调用 `provider`服务(`provider` 服务要开启),成功之后会打印出是否调用成功。
![这里写图片描述](https://img-blog.csdn.net/20180429093659367?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bmh1YXFpYW5nMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![这里写图片描述](https://img-blog.csdn.net/20180429093708205?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bmh1YXFpYW5nMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
如果这样就表示成功调用了。可以看到 `Dubbo` 框架是在 `Spring` 的基础上加上一个简单的配置文件即可把一个服务暴露出去。
`Dubbo` 配置文件基本有 `application`、`registry`、`protocol` 3个公共参数分别告诉了 `Dubbo` 以及 `zookeeper` 注册中心:`我是谁?我向谁注册?怎么调用我的服务?`通过这 3 个配置,其他消费者就可以找到对应服务。
### 2. `properties` 配置文件方式
`Dubbo`在读取配置的时候会先读取 `XML`文件中的配置,如果没找到就会默认去读取`resources`目录下的 `dubbo.properties` 文件。而 `dubbo.properties` 的配置方式与 `XML`配置方式一样,只不过是换了种写法而已。
要换成 `dubbo.properties` 配置,你只需把 `spring-provider.xml` 里关于 `application`、`registry`、`protocol` 里的配置注释掉,然后加上对应的 `dubbo.properties` 文件即可。上面例子的 spring-provider.xml 换成 `properties` 文件的写法是这样的:
应用名
dubbo.application.name=dubbodemo-provider
注册中心地址
dubbo.registry.address=zookeeper://localhost:2181
调用协议地址
dubbo.protocol.name=dubbo
dubbo.protocol.port=28080
spring-consumer.xml 换成 `properties` 文件写法是这样的:
应用名
dubbo.application.name = dubbodemo-consumer
注册中心地址
dubbo.registry.address = zookeeper://localhost:2181
调用协议地址
dubbo.protocol.name = dubbo
dubbo.protocol.port = 28080
此时 spring-provider.xml 和 spring-consumer.xml 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
spring-consumer.xml配置
<?xml version="1.0" encoding="UTF-8"?>
最后:学习总结——MyBtis知识脑图(纯手绘xmind文档)
学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)
除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!
,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)
[外链图片转存中…(img-xz7sJWxC-1715283027781)]
除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!