快速从零开始整合SSM,小白包会(1)
整合SSM,关键就是几个xml的配置.
准备:
1. Idea(配置好tomcat,可以安装插件freeMybatis,提高效率,安装插件不难,百度经验就有)
2. 下载好数据库MySql,以及可视化管理软件
3. 一双手,宝贵的半个小时
4. 对SSM,有认识,后面我会继续写有关这三个框架的内容.
开始:
首先,明确我们这里的工作:
建立一个通用的SSM项目,或者知道快速建立它的方法,以便于后面有什么项目,分析完可以直接就上手,避免在初始化项目,整合框架时耗费时间.
工作目标:
待会如果我们将存储在数据库里面表的信息在控制台打印出来了,那么Spring与MyBatis整合成功,如果在前端页面显示了数据库的数据,那么可以说三个框架整合成功.
提示:成功一次之后,可以反反复复多建几次,到达熟练,也可以保存模板,后面直接用.我就是从零开始边建项目边写这个博客,我都完成了,你照着来应该不会错.
毒鸡汤:在这个过程中,可能会遇到很多麻烦,但大部分都可以百度解决,也有可能被误导,但不管怎么样结果是一定成功的,毕竟它具有可预测性和有限性,而只要成功一次就可以保证成功无数次.
我还是个小白,第一次写博客(马上要期末考试了,哈哈),希望以这种方式来记录一下自己踩过的坑,都是自己慢慢摸出来的,不科学也不规范,我也希望大佬们可以多多指导.
第一步,在Idea上面新建一个项目:
此时项目应该是白的,这个样子:
我们下面建几个包和配置文件:
在config下面建立这些配置文件(这其实就是核心的配置,文件内容先不管,后面直接复制):
下面导入jar包,可以选择自动下载,或者直接使用Maven项目来添加,这里我们手动添加:
把自己的准备Jar包统统导进来即可.
再做一点小手脚,标识一下文件(test包是刚刚建的,就是一个普通的包,所以没有截图):
项目就是这个样子了:
至此, 第一步初始化项目完成,已经完成70%了.
第二步:使项目可以跑起来,在前端页面可以看到数据库的存储的信息.
1. 配置tomcat,把刚刚的建的配置文件加上内容.
2. 在数据库里面新加一表,插入一条测试数据,并为该表建立mapper文件,和接口(可以使用插件完成).
3.简单的编写一下,开始测试.
1.配置Tomcat,比较简单,就不步步展示了.后面放假了可以详细的写一下.
2.各个配置文件的内容:
applicationContext.xml :


1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xmlns:tx="http://www.springframework.org/schema/tx"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans.xsd
8 http://www.springframework.org/schema/context
9 https://www.springframework.org/schema/context/spring-context.xsd
10 http://www.springframework.org/schema/tx
11 http://www.springframework.org/schema/tx/spring-tx.xsd">
12 <!--配置数据源-->
13 <context:property-placeholder location="classpath:config/db.properties"/>
14 <context:component-scan base-package="service"/>
15 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
16 <property name="driverClassName" value="${jdbc.driver}"/>
17 <property name="url" value="${jdbc.url}"/>
18 <property name="username" value="${jdbc.username}"/>
19 <property name="password" value="${jdbc.password}"/>
20 <property name="maxIdle" value="${jdbc.maxIdle}"/>
21 <property name="initialSize" value="${jdbc.initialSize}"/>
22 </bean>
23
24 <!--mybatis-->
25 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
26 <property name="basePackage" value="mapper"/>
27 </bean>
28 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
29 <property name="dataSource" ref="dataSource"/>
30 <property name="configLocation" value="classpath:config/Mybatis-config.xml"/>
31 </bean>
32
33 <!--事务管理-->
34 <bean id="myTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
35 <property name="dataSource" ref="dataSource"/>
36 </bean>
37 <tx:annotation-driven transaction-manager="myTransactionManager"/>
38 <!-- <aop:aspectj-autoproxy proxy-target-class="true"/>-->
39 </beans>
db.properties(要根据自己的数据库更改) :


1 jdbc.driver=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://localhost:3308/exam?useUnicode=true&characterEncoding=utf8&useSSL=false
3 jdbc.username=root
4 jdbc.password=123456
5 jdbc.maxTotal=30
6 jdbc.maxIdle=10
7 jdbc.initialSize=5
log4j.properties :


1 # Global logging configuration
2 log4j.rootLogger=ERROR, stdout
3 # MyBatis logging configuration...
4 log4j.logger.org.mybatis.example.BlogMapper=DEBUG
5 # Console output...
6 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
7 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
mybatis-config.xml :


1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE configuration
3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
5 <configuration>
6 <typeAliases>
7 <package name="po"/>
8 </typeAliases>
9 </configuration>
springmvc-config.xml :


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="controller"/>
<mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--Spring-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!--编码过滤器-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping> <!--spring Mvc-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> </web-app>
3.在数据库里面建表,插入一条数据.
4.使用插件生成这个测试表的mapper文件和dao接口
最后生成的项目结构:
生成具体的代码(这都是插件自动生成的,省事):
UserDao接口 :


package mapper; import org.springframework.transaction.annotation.Transactional;
import po.User; @Transactional
public interface UserDao {
int deleteByPrimaryKey(Integer id); int insert(User record); int insertSelective(User record); User selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(User record); int updateByPrimaryKey(User record);
}
UserDao.xml :


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserDao">
<resultMap id="BaseResultMap" type="po.User">
<id column="user_id" jdbcType="INTEGER" property="id" />
<result column="user_userName" jdbcType="VARCHAR" property="userName" />
<result column="user_passWord" jdbcType="VARCHAR" property="passWord" />
<result column="user_phone" jdbcType="VARCHAR" property="phone" />
<result column="user_realName" jdbcType="VARCHAR" property="realName" />
<result column="user_sex" jdbcType="VARCHAR" property="sex" />
<result column="user_address" jdbcType="VARCHAR" property="address" />
<result column="user_email" jdbcType="VARCHAR" property="email" />
</resultMap>
<sql id="Base_Column_List">
user.id as user_id, user.userName as user_userName, user.`passWord` as `user_passWord`,
user.phone as user_phone, user.realName as user_realName, user.sex as user_sex, user.address as user_address,
user.email as user_email
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user user
where user.id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from user
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="po.User" useGeneratedKeys="true">
insert into user (userName, `passWord`, phone,
realName, sex, address,
email)
values (#{userName,jdbcType=VARCHAR}, #{passWord,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR},
#{realName,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, #{address,jdbcType=VARCHAR},
#{email,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="po.User" useGeneratedKeys="true">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userName != null">
userName,
</if>
<if test="passWord != null">
`passWord`,
</if>
<if test="phone != null">
phone,
</if>
<if test="realName != null">
realName,
</if>
<if test="sex != null">
sex,
</if>
<if test="address != null">
address,
</if>
<if test="email != null">
email,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userName != null">
#{userName,jdbcType=VARCHAR},
</if>
<if test="passWord != null">
#{passWord,jdbcType=VARCHAR},
</if>
<if test="phone != null">
#{phone,jdbcType=VARCHAR},
</if>
<if test="realName != null">
#{realName,jdbcType=VARCHAR},
</if>
<if test="sex != null">
#{sex,jdbcType=VARCHAR},
</if>
<if test="address != null">
#{address,jdbcType=VARCHAR},
</if>
<if test="email != null">
#{email,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="po.User">
update user
<set>
<if test="userName != null">
userName = #{userName,jdbcType=VARCHAR},
</if>
<if test="passWord != null">
`passWord` = #{passWord,jdbcType=VARCHAR},
</if>
<if test="phone != null">
phone = #{phone,jdbcType=VARCHAR},
</if>
<if test="realName != null">
realName = #{realName,jdbcType=VARCHAR},
</if>
<if test="sex != null">
sex = #{sex,jdbcType=VARCHAR},
</if>
<if test="address != null">
address = #{address,jdbcType=VARCHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="po.User">
update user
set userName = #{userName,jdbcType=VARCHAR},
`passWord` = #{passWord,jdbcType=VARCHAR},
phone = #{phone,jdbcType=VARCHAR},
realName = #{realName,jdbcType=VARCHAR},
sex = #{sex,jdbcType=VARCHAR},
address = #{address,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
User类 :


package po; import java.io.Serializable; /**
* user
* @author
*/ public class User implements Serializable {
/**
* id,主键
*/
private Integer id; /**
* 账户
*/
private String userName; /**
* 密码
*/
private String passWord; /**
* 手机号码
*/
private String phone; /**
* 真实姓名
*/
private String realName; /**
* 性别
*/
private String sex; /**
* 地址(收货)
*/
private String address; /**
* 电子邮件
*/
private String email; private static final long serialVersionUID = 1L; @Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
User other = (User) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName()))
&& (this.getPassWord() == null ? other.getPassWord() == null : this.getPassWord().equals(other.getPassWord()))
&& (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
&& (this.getRealName() == null ? other.getRealName() == null : this.getRealName().equals(other.getRealName()))
&& (this.getSex() == null ? other.getSex() == null : this.getSex().equals(other.getSex()))
&& (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress()))
&& (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()));
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public String getPassWord() {
return passWord;
} public void setPassWord(String passWord) {
this.passWord = passWord;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
} public String getRealName() {
return realName;
} public void setRealName(String realName) {
this.realName = realName;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public static long getSerialVersionUID() {
return serialVersionUID;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode());
result = prime * result + ((getPassWord() == null) ? 0 : getPassWord().hashCode());
result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
result = prime * result + ((getRealName() == null) ? 0 : getRealName().hashCode());
result = prime * result + ((getSex() == null) ? 0 : getSex().hashCode());
result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode());
result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
return result;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", userName=").append(userName);
sb.append(", passWord=").append(passWord);
sb.append(", phone=").append(phone);
sb.append(", realName=").append(realName);
sb.append(", sex=").append(sex);
sb.append(", address=").append(address);
sb.append(", email=").append(email);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}
5.测试Spring与Mybatis的基本整合
1.在test包下面建一个Test类,用来测试 :
其内容分别为:
Test类 :


import mapper.UserDao;
import org.springframework.context.ApplicationContext;
import util.SpringUtil; /**
* test
*
* @author Mr.green
* @date 2021/11/21 17:27
*/
public class Test { @org.junit.jupiter.api.Test
void test(){
ApplicationContext applicationContext= SpringUtil.getApplicationContext();
System.out.println(applicationContext.getBean(UserDao.class).selectByPrimaryKey(1));
}
}
SpringUtil类:


1 package util;
2
3 import org.springframework.context.ApplicationContext;
4 import org.springframework.context.support.ClassPathXmlApplicationContext;
5
6 /**
7 * Spring
8 *
9 * @author Mr.green
10 * @date 2021/11/21 17:28
11 */
12 public class SpringUtil {
13 /*获取spring上下文解析器*/
14 static public ApplicationContext getApplicationContext(){
15 return new ClassPathXmlApplicationContext("config/applicationContext.xml");
16 }
17
18
19 }
直接开始测试 :
Nice,Spring与Mybatis整合成功.
6.测试Sping,Mybatis,SpringMvc的整合
1.建一个jsp页面,用来显示数据库的数据
2.建一个controller响应处理前端的请求
1: 建一个jsp页面
a.jsp的内容:
<%--
Created by IntelliJ IDEA.
User: Philosohy
Date: 2021/11/22
Time: 13:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${user.id}<br>
${user.userName}<br>
${user.passWord}<br>
</body>
</html>
2 .建一个controller:
其内容:
package controller; import util.SpringUtil;
import mapper.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; /**
* test
*
* @author Mr.green
* @date 2021/11/21 18:23
*/
@Controller
public class TestController { @RequestMapping("/test")
public String test(Integer id, Model model){
ApplicationContext applicationContext= SpringUtil.getApplicationContext();
model.addAttribute("user",applicationContext.getBean(UserDao.class).selectByPrimaryKey(1)); return "a";
}
}
3.开始测试,启动项目,在跳出来的网页后面加上test :
这不就飞起了!!!!
快速从零开始整合SSM,小白包会(1)的更多相关文章
- 快速搭建springboot框架以及整合ssm+shiro+安装Rabbitmq和Erlang、Mysql下载与配置
1.快速搭建springboot框架(在idea中): file–>new project–>Spring Initializr–>next–>然后一直下一步. 然后复制一下代 ...
- SSM(SpringMVC+Spring+MyBatis)三大框架使用Maven快速搭建整合(实现数据库数据到页面进行展示)
本文介绍使用SpringMVC+Spring+MyBatis三大框架使用Maven快速搭建一个demo,实现数据从数据库中查询返回到页面进行展示的过程. 技术选型:SpringMVC+Spring+M ...
- 整合SSM框架必备基础—SpringMVC(下)
在上一篇文章<整合SSM框架必备基础-SpringMVC(上)>中,胖达介绍了关于SpringMVC的诞生.优势以及执行流程等理论知识点,这篇文章打算在实操中加深一下对SpringMVC的 ...
- IDEA+Maven 整合SSM框架实现简单的增删改查(新手入门,傻瓜操作)
原博客地址:https://blog.csdn.net/khxu666/article/details/79851070 选用SSM框架的原因在目前的企业级Java应用中,Spring框架是必须的.S ...
- shiro权限控制(一):shiro介绍以及整合SSM框架
shiro安全框架是目前为止作为登录注册最常用的框架,因为它十分的强大简单,提供了认证.授权.加密和会话管理等功能 . shiro能做什么? 认证:验证用户的身份 授权:对用户执行访问控制:判断用户是 ...
- 从零开始写一个npm包及上传
最近刚好自己需要写公有npm包及上传,虽然百度上资料都能找到,但是都是比较零零碎碎的,个人就来整理下,如何从零开始写一个npm包及上传. 该篇文件只记录一个大概的流程,一些细节没有记录. tips: ...
- 使用SpringBoot整合ssm项目
SpringBoot是什么? Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程. Spring Boot 现在已经成为Java ...
- Spring Boot 2.0 教程 | 快速集成整合消息中间件 Kafka
欢迎关注个人微信公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site ...
- SpringBoot整合SSM(代码实现Demo)
SpringBoot整合SSM 如图所示: 一.数据准备: 数据库文件:数据库名:saas-export,表名:ss_company 创建表语句: DROP TABLE IF EXISTS ss_co ...
随机推荐
- Pandas 数据的一些基本操作
一个很偶然的机会,主动出击挑战一个之前没有尝试过的新东西,在做的过程中需要处理一些csv文件的数据,以下是我总结的一些小方法,希望对和我一样的新手朋友们有所帮助,初次尝试,望路过的朋友有更好的方法可以 ...
- 洛谷3973 TJOI2015线性代数(最小割+思维)
感觉要做出来这个题,需要一定的线代芝士 首先,我们来观察这个柿子. 我们将\(B\)的权值看作是收益的话,\(C\)的权值就是花费. 根据矩阵乘法的原理,只有当\(a[i]和a[j]\)都为\(1\) ...
- 2021.7.27--Benelux Algorithm Programming Contest 2020 补提
I Jigsaw 题目内容: 链接:https://ac.nowcoder.com/acm/contest/18454/I 来源:牛客网 You have found an old jigsaw pu ...
- Docker--harbor私有仓库部署与管理
目录 一.Harbor简介 二.Harbor 部署 三.维护管理Harbor 一.Harbor简介 1.什么是Harbor ? Harbor 是 VMware 公司开源的企业级 Docker Re ...
- 【UE4 设计模式】组件模式 Components Pattern
概述 描述 在单一实体跨越了多个领域时,为了保持领域之间相互解耦,可以将每部分代码放入各自的组件类中,将实体简化为组件的容器. 套路 参考 UE4中的 Componet 组件使用方式 使用场景 有一个 ...
- AtCoder Beginner Contest 224
AtCoder Beginner Contest 224 A - Tires 思路分析: 判断最后一个字符即可. 代码如下: #include <bits/stdc++.h> using ...
- [火星补锅] 水题大战Vol.2 T1 && luogu P1904 天际线 题解 (线段树)
前言: 当时考场上并没有想出来...后来也是看了题解才明白 解析: 大家(除了我)都知道,奇点和偶点会成对出现,而出现的前提就是建筑的高度突然发生变化.(这个性质挺重要的,我之前没看出来) 所以就可以 ...
- mybatis竟然报"Invalid value for getInt()"
目录 背景 场景 初探 再探 结局 背景 使用mybatis遇到一个非常奇葩的问题,错误如下: Cause: org.apache.ibatis.executor.result.ResultMapEx ...
- webRTC中语音降噪模块ANS细节详解(三)
上篇(webRTC中语音降噪模块ANS细节详解(二))讲了ANS的处理流程和语音在时域和频域的相互转换.本篇开始讲语音降噪的核心部分,首先讲噪声的初始估计以及基于估计出来的噪声算先验信噪比和后验信噪比 ...
- 近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控
最近,业务增长的很迅猛,对于我们后台这块也是一个不小的挑战,这次遇到的核心业务接口的性能瓶颈,并不是单独的一个问题导致的,而是几个问题揉在一起:我们解决一个之后,发上线,之后发现还有另一个的性能瓶颈问 ...