热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

koa2+vue+mysql全栈开辟纪录

koa2+vue2+mysql全栈开辟纪录基于想要本身制造一个个人项目为由,因而有了这么一个开辟纪录(梳理开辟历程也是一个学问稳固的历程)koa2+vue2+mysql个人的一个通
koa2+vue2+mysql 全栈开辟纪录

基于想要本身制造一个个人项目为由,因而有了这么一个开辟纪录(梳理开辟历程也是一个学问稳固的历程)

koa2+vue2+mysql 个人的一个通用DEMO(本篇文章的范例)

koa2+vue2+mysql GITHUB地点

前端东西

  • vue
  • vue-router
  • vuex
  • axios
  • element ui 页面UI组件
  • echartsjs 百度壮大的图表展现
  • vue-admin-template 花裤衩大佬的一个有用治理背景模版 配套教程
  • vue-i18n 国际化
  • scss

后端东西

  • koa
  • koa-bodyparser 剖析 PUT / POST 要求中的 body
  • koa-convert
  • koa-json
  • koa-jwt jwt鉴权
  • koa-logger
  • koa-mysql-session
  • koa-onerror
  • koa-router
  • koa-session-minimal
  • koa-static
  • koa-views
  • koa2-cors 处置惩罚跨域
  • md5 加密
  • moment 时刻处置惩罚
  • mysql

前端篇

前端这边实在没什么好写的,主假如在
vue-admin-template基础上做了一些修正

src/utils/request.js的修正

  • request拦截器

// request拦截器
service.interceptors.request.use(
cOnfig=> {
if (store.getters.token) {
// config.headers['X-Token'] = getToken()
// 由于是jwt体式格局鉴权 所以在header头中改成以下写法
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每一个要求照顾自定义token 请依据实际情况自行修正
}
return config
},
error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}
)

  • response 拦截器

// response 拦截器
service.interceptors.response.use(
respOnse=> {
/**
* code为非0是抛错 可连系本身营业举行修正
*/
const res = response.data
if (res.code !== 0) { // 由于背景返回值为0则是胜利,所以将本来的20000改成了0
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})
// 70002:不法的token; 50012:其他客户端登录了; 50014:Token 逾期了;
if (res.code === 70002 || res.code === 50012 || res.code === 50014) {
MessageBox.confirm(
'你已被登出,能够作废继承留在该页面,或许从新登录',
'肯定登出',
{
confirmButtonText: '从新登录',
cancelButtonText: '作废',
type: 'warning'
}
).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了从新实例化vue-router对象 防止bug
})
})
}
return Promise.reject('error')
} else {
return response.data
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)

封装了一个Echart组件

  • 详细参考我的别的一个文章 vue中运用echarts 运用纪录

后端篇

构建项目目次

  • 经由过程项目天生器天生koa-generator
  1. npm install -g koa-generator
  2. koa2 /server && cd /server
  3. npm install
  • 装置组件
  1. npm i jsonwebtoken koa-jwt koa-mysql-session koa-session-minimal koa2-cors md5 moment mysql save --save
  • 设置app.js

const Koa = require('koa')
const jwt = require('koa-jwt')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const Onerror= require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
const cOnvert= require('koa-convert');
var session = require('koa-session-minimal')
var MysqlStore = require('koa-mysql-session')
var cOnfig= require('./config/default.js')
var cors = require('koa2-cors')
const users = require('./routes/users')
const account = require('./routes/account')
// error handler
onerror(app)
// 设置jwt毛病返回
app.use(function(ctx, next) {
return next().catch(err => {
if (401 == err.status) {
ctx.status = 401
ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.INVALID_TOKEN)
// ctx.body = {
// // error: err.originalError ? err.originalError.message : err.message
// }
} else {
throw err
}
})
})
// Unprotected middleware
app.use(function(ctx, next) {
if (ctx.url.match(/^\/public/)) {
ctx.body = 'unprotected\n'
} else {
return next()
}
})
// Middleware below this line is only reached if JWT token is valid
app.use(
jwt({ secret: config.secret, passthrough: true }).unless({
path: [/\/register/, /\/user\/login/]
})
)
// middlewares
app.use(convert(bodyparser({
enableTypes:['json', 'form', 'text']
})))
app.use(convert(json()))
app.use(convert(logger()))
app.use(require('koa-static')(__dirname + '/public'))
app.use(views(__dirname + '/views', {
extension: 'pug'
}))
// logger
app.use(async (ctx, next) => {
const start = new Date()
await next()
const ms = new Date() - start
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})
// cors
app.use(cors())
// routes
app.use(users.routes(), users.allowedMethods())
app.use(account.routes(), account.allowedMethods())
// error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
module.exports = app

  • 新建config文件夹用于寄存数据库衔接等操纵

default.js

// 数据库设置
const cOnfig= {
port: 3000,
database: {
DATABASE: 'xxx', //数据库
USERNAME: 'root', //用户
PASSWORD: 'xxx', //暗码
PORT: '3306', //端口
HOST: '127.0.0.1' //效劳ip地点
},
secret: 'jwt_secret'
}
module.exports = config

数据库相干(mysql)

createTables.js 一个简朴的用户角色权限表
用户、角色、权限表的关联(mysql)

// 数据库表格建立
const createTable = {
users: `CREATE TABLE IF NOT EXISTS user_info (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '(自增进)',
user_id VARCHAR ( 100 ) NOT NULL COMMENT '账号',
user_name VARCHAR ( 100 ) NOT NULL COMMENT '用户名',
user_pwd VARCHAR ( 100 ) NOT NULL COMMENT '暗码',
user_head VARCHAR ( 225 ) COMMENT '头像',
user_mobile VARCHAR ( 20 ) COMMENT '手机',
user_email VARCHAR ( 64 ) COMMENT '邮箱',
user_creatdata TIMESTAMP NOT NULL DEFAULT NOW( ) COMMENT '注册日期',
user_login_time TIMESTAMP DEFAULT NOW( ) COMMENT '登录时刻',
user_count INT COMMENT '登录次数'
) ENGINE = INNODB charset = utf8;`,
role: `CREATE TABLE IF NOT EXISTS role_info (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '(自增进)',
role_name VARCHAR ( 20 ) NOT NULL COMMENT '角色名',
role_description VARCHAR ( 255 ) DEFAULT NULL COMMENT '形貌'
) ENGINE = INNODB charset = utf8;`,
permission: `CREATE TABLE IF NOT EXISTS permission_info (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '(自增进)',
permission_name VARCHAR ( 20 ) NOT NULL COMMENT '权限名',
permission_description VARCHAR ( 255 ) DEFAULT NULL COMMENT '形貌'
) ENGINE = INNODB charset = utf8;`,
userRole: `CREATE TABLE IF NOT EXISTS user_role (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '(自增进)',
user_id INT NOT NULL COMMENT '关联用户',
role_id INT NOT NULL COMMENT '关联角色',
KEY fk_user_role_role_info_1 ( role_id ),
KEY fk_user_role_user_info_1 ( user_id ),
CONSTRAINT fk_user_role_role_info_1 FOREIGN KEY ( role_id ) REFERENCES role_info ( id ) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_user_role_user_info_1 FOREIGN KEY ( user_id ) REFERENCES user_info ( id ) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = INNODB charset = utf8;`,
rolePermission: `CREATE TABLE IF NOT EXISTS role_permission (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '(自增进)',
role_id INT NOT NULL COMMENT '关联角色',
permission_id INT NOT NULL COMMENT '关联权限',
KEY fk_role_permission_role_info_1 ( role_id ),
KEY fk_role_permission_permission_info_1 ( permission_id ),
CONSTRAINT fk_role_permission_role_info_1 FOREIGN KEY ( role_id ) REFERENCES role_info ( id ) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_role_permission_permission_info_1 FOREIGN KEY ( permission_id ) REFERENCES permission_info ( id ) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = INNODB charset = utf8;`
}
module.exports = createTable

  • 建立lib文件夹 用于存储数据库查询语句

mysql.js

const mysql = require('mysql')
const cOnfig= require('../config/default')
const createTables = require('../config/createTables.js')
var pool = mysql.createPool({
host: config.database.HOST,
user: config.database.USERNAME,
password: config.database.PASSWORD,
database: config.database.DATABASE
})
let query = function(sql, values) {
return new Promise((resolve, reject) => {
pool.getConnection(function(err, connection) {
if (err) {
resolve(err)
} else {
connection.query(sql, values, (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
connection.release()
})
}
})
})
}
let createTable = function(sql) {
return query(sql, [])
}
// 建表
// createTable(createTables.users)
// createTable(createTables.role)
// createTable(createTables.permission)
// createTable(createTables.userRole)
// createTable(createTables.rolePermission)
// 查询用户是不是存在
let findUser = async function(id) {
let _sql = `
SELECT * FROM user_info where user_id="${id}" limit 1;
`
let result = await query(_sql)
if (Array.isArray(result) && result.length > 0) {
result = result[0]
} else {
result = null
}
return result
}
// 查询用户以及用户角色
let findUserAndRole = async function(id) {
let _sql = `
SELECT u.*,r.role_name FROM user_info u,user_role ur,role_info r where u.id=(SELECT id FROM user_info where user_id="${id}" limit 1) and ur.user_id=u.id and r.id=ur.user_id limit 1;
`
let result = await query(_sql)
if (Array.isArray(result) && result.length > 0) {
result = result[0]
} else {
result = null
}
return result
}
// 更新用户登录次数和登录时刻
let UpdataUserInfo = async function(value) {
let _sql =
'UPDATE user_info SET user_count = ?, user_login_time = ? WHERE id = ?;'
return query(_sql, value)
}
module.exports = {
//暴露要领
createTable,
findUser,
findUserAndRole,
UpdataUserInfo,
getShopAndAccount
}

koa 路由设置

  • 接口报错信息一致要领 建立error文件夹

ApiErrorNames.js

/**
* API毛病称号
*/
var ApiErrorNames = {};
ApiErrorNames.UNKNOW_ERROR = "UNKNOW_ERROR";
ApiErrorNames.SUCCESS = "SUCCESS";
/* 参数毛病:10001-19999 */
ApiErrorNames.PARAM_IS_INVALID = 'PARAM_IS_INVALID';
ApiErrorNames.PARAM_IS_BLANK = 'PARAM_IS_BLANK';
ApiErrorNames.PARAM_TYPE_BIND_ERROR = 'PARAM_TYPE_BIND_ERROR';
ApiErrorNames.PARAM_NOT_COMPLETE = 'PARAM_NOT_COMPLETE';
/* 用户毛病:20001-29999*/
ApiErrorNames.USER_NOT_LOGGED_IN = 'USER_NOT_LOGGED_IN';
ApiErrorNames.USER_LOGIN_ERROR = 'USER_LOGIN_ERROR';
ApiErrorNames.USER_ACCOUNT_FORBIDDEN = 'USER_ACCOUNT_FORBIDDEN';
ApiErrorNames.USER_NOT_EXIST = 'USER_NOT_EXIST';
ApiErrorNames.USER_HAS_EXISTED = 'USER_HAS_EXISTED';
/* 营业毛病:30001-39999 */
ApiErrorNames.SPECIFIED_QUESTIONED_USER_NOT_EXIST = 'SPECIFIED_QUESTIONED_USER_NOT_EXIST';
/* 体系毛病:40001-49999 */
ApiErrorNames.SYSTEM_INNER_ERROR = 'SYSTEM_INNER_ERROR';
/* 数据毛病:50001-599999 */
ApiErrorNames.RESULE_DATA_NOnE= 'RESULE_DATA_NONE';
ApiErrorNames.DATA_IS_WROnG= 'DATA_IS_WRONG';
ApiErrorNames.DATA_ALREADY_EXISTED = 'DATA_ALREADY_EXISTED';
/* 接口毛病:60001-69999 */
ApiErrorNames.INTERFACE_INNER_INVOKE_ERROR = 'INTERFACE_INNER_INVOKE_ERROR';
ApiErrorNames.INTERFACE_OUTTER_INVOKE_ERROR = 'INTERFACE_OUTTER_INVOKE_ERROR';
ApiErrorNames.INTERFACE_FORBID_VISIT = 'INTERFACE_FORBID_VISIT';
ApiErrorNames.INTERFACE_ADDRESS_INVALID = 'INTERFACE_ADDRESS_INVALID';
ApiErrorNames.INTERFACE_REQUEST_TIMEOUT = 'INTERFACE_REQUEST_TIMEOUT';
ApiErrorNames.INTERFACE_EXCEED_LOAD = 'INTERFACE_EXCEED_LOAD';
/* 权限毛病:70001-79999 */
ApiErrorNames.PERMISSION_NO_ACCESS = 'PERMISSION_NO_ACCESS';
ApiErrorNames.INVALID_TOKEN = 'INVALID_TOKEN';
/**
* API毛病称号对应的毛病信息
*/
const error_map = new Map();
error_map.set(ApiErrorNames.SUCCESS, { code: 0, message: '胜利' });
error_map.set(ApiErrorNames.UNKNOW_ERROR, { code: -1, message: '未知毛病' });
/* 参数毛病:10001-19999 */
error_map.set(ApiErrorNames.PARAM_IS_INVALID, { code: 10001, message: '参数无效' });
error_map.set(ApiErrorNames.PARAM_IS_BLANK, { code: 10002, message: '参数为空' });
error_map.set(ApiErrorNames.PARAM_TYPE_BIND_ERROR, { code: 10003, message: '参数范例毛病' });
error_map.set(ApiErrorNames.PARAM_NOT_COMPLETE, { code: 10004, message: '参数缺失' });
/* 用户毛病:20001-29999*/
error_map.set(ApiErrorNames.USER_NOT_LOGGED_IN, { code: 20001, message: '用户未登录' });
error_map.set(ApiErrorNames.USER_LOGIN_ERROR, { code: 20002, message: '账号不存在或暗码毛病' });
error_map.set(ApiErrorNames.USER_ACCOUNT_FORBIDDEN, { code: 20003, message: '账号已被禁用' });
error_map.set(ApiErrorNames.USER_NOT_EXIST, { code: 20004, message: '用户不存在' });
error_map.set(ApiErrorNames.USER_HAS_EXISTED, { code: 20005, message: '用户已存在' });
/* 营业毛病:30001-39999 */
error_map.set(ApiErrorNames.SPECIFIED_QUESTIONED_USER_NOT_EXIST, { code: 30001, message: '某营业出现问题' });
/* 体系毛病:40001-49999 */
error_map.set(ApiErrorNames.SYSTEM_INNER_ERROR, { code: 40001, message: '体系忙碌,请稍后重试' });
/* 数据毛病:50001-599999 */
error_map.set(ApiErrorNames.RESULE_DATA_NONE, { code: 50001, message: '数据未找到' });
error_map.set(ApiErrorNames.DATA_IS_WRONG, { code: 50002, message: '数据有误' });
error_map.set(ApiErrorNames.DATA_ALREADY_EXISTED, { code: 50003, message: '数据已存在' });
/* 接口毛病:60001-69999 */
error_map.set(ApiErrorNames.INTERFACE_INNER_INVOKE_ERROR, { code: 60001, message: '内部体系接口挪用非常' });
error_map.set(ApiErrorNames.INTERFACE_OUTTER_INVOKE_ERROR, { code: 60002, message: '外部体系接口挪用非常' });
error_map.set(ApiErrorNames.INTERFACE_FORBID_VISIT, { code: 60003, message: '该接口制止接见' });
error_map.set(ApiErrorNames.INTERFACE_ADDRESS_INVALID, { code: 60004, message: '接口地点无效' });
error_map.set(ApiErrorNames.INTERFACE_REQUEST_TIMEOUT, { code: 60005, message: '接口要求超时' });
error_map.set(ApiErrorNames.INTERFACE_EXCEED_LOAD, { code: 60006, message: '接口负载太高' });
/* 权限毛病:70001-79999 */
error_map.set(ApiErrorNames.PERMISSION_NO_ACCESS, { code: 70001, message: '无接见权限' });
error_map.set(ApiErrorNames.INVALID_TOKEN, { code: 70002, message: '无效token' });
//依据毛病称号猎取毛病信息
ApiErrorNames.getErrorInfo = (error_name) => {
var error_info;
if (error_name) {
error_info = error_map.get(error_name);
}
//假如没有对应的毛病信息,默许'未知毛病'
if (!error_info) {
error_name = UNKNOW_ERROR;
error_info = error_map.get(error_name);
}
return error_info;
}
//返回准确信息
ApiErrorNames.getSuccessInfo = (data) => {
var success_info;
let name = 'SUCCESS';
success_info = error_map.get(name);
if (data) {
success_info.data = data
}
return success_info;
}
module.exports = ApiErrorNames;

  • 建立controller文件夹

对路由users举行逻辑编写

const mysqlModel = require('../lib/mysql') //引入数据库要领
const jwt = require('jsonwebtoken')
const cOnfig= require('../config/default.js')
const ApiErrorNames = require('../error/ApiErrorNames.js')
const moment = require('moment')
/**
* 一般登录
*/
exports.login = async (ctx, next) => {
const { body } = ctx.request
try {
const user = await mysqlModel.findUser(body.username)
if (!user) {
// ctx.status = 401
ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.USER_NOT_EXIST)
return
}
let bodys = await JSON.parse(JSON.stringify(user))
// 婚配暗码是不是相称
if ((await user.user_pwd) === body.password) {
let data = {
user: user.user_id,
// 天生 token 返回给客户端
token: jwt.sign(
{
data: user.user_id,
// 设置 token 逾期时刻
exp: Math.floor(Date.now() / 1000) + 60 * 60 // 60 seconds * 60 minutes = 1 hour
},
config.secret
)
}
ctx.body = ApiErrorNames.getSuccessInfo(data)
} else {
ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.USER_LOGIN_ERROR)
}
} catch (error) {
ctx.throw(500)
}
}
/**
* 猎取用户信息
*/
exports.info = async (ctx, next) => {
const { body } = ctx.request
// console.log(body)
try {
const token = ctx.header.authorization
let payload
if (token) {
payload = await jwt.verify(token.split(' ')[1], config.secret) // 解密,猎取payload
const user = await mysqlModel.findUserAndRole(payload.data)
if (!user) {
ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.USER_NOT_EXIST)
} else {
let cOnt= user.user_count + 1
let updateInfo = [
cont,
moment().format('YYYY-MM-DD HH:mm:ss'),
user.id
]
await mysqlModel
.UpdataUserInfo(updateInfo)
.then(res => {
let data = {
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: user.user_id,
// roles: [user.user_admin === 0 ? 'admin' : '']
roles: [user.role_name]
}
ctx.body = ApiErrorNames.getSuccessInfo(data)
})
.catch(err => {
ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.DATA_IS_WRONG)
})
}
} else {
ctx.body = ApiErrorNames.getErrorInfo(ApiErrorNames.INVALID_TOKEN)
}
} catch (error) {
ctx.throw(500)
}
}
/**
* 退出登录
*/
exports.logout = async (ctx, next) => {
try {
// ctx.status = 200
ctx.body = ApiErrorNames.getSuccessInfo()
} catch (error) {
ctx.throw(500)
}
}

routes中的users.js

const router = require('koa-router')() //引入路由函数
const userCOntrol= require('../controller/users') //引入逻辑
// const cOnfig= require('../config/default.js')
router.get('/', async (ctx, next) => {
'use strict'
ctx.redirect('/user/login')
})
// 路由中心间,页面路由到/,就是端口号的时刻,(网址),页面指引到//user/login
router.get('/user/info', userControl.info)
router.post('/user/logout', userControl.logout)
router.post('/user/login', userControl.login)
module.exports = router
//将页面暴露出去

备注

ctx.request 猎取post要求中的body
ctx.query.xx 猎取get要求中的参数
router.prefix('/account') 给router实例增加前缀


推荐阅读
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 众筹商城与传统商城的区别及php众筹网站的程序源码
    本文介绍了众筹商城与传统商城的区别,包括所售产品和玩法不同以及运营方式不同。同时还提到了php众筹网站的程序源码和方维众筹的安装和环境问题。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
author-avatar
个阖家团圆
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有