暂时未有相关云产品技术能力~
win10隐藏正在运行的程序的方法:1、按下“Win+TAB”组合键,在左上角点击“新建桌面”;2、点击新建的“桌面2”,我们将需要隐藏的程序在该新建桌面中运行;3、如果突然被遇到巡检,我们马上按下“Win+TAB”组合键切换到“桌面1”即可!
点击上面设置按钮打开后将 flatten packages 和 hidden empty middle packages勾选上,效果就和eclipse中的包一样了,不会折叠。看起来更方便一些。设置示意图:
sonar是一款代码质量管理工具,下面介绍下插件的使用方式sonar的插件名称为sonarlint.选择file→settings→plugins→输入sonarlint在安装插件的过程中很可能会安装失败,简单的处理方式如下:settings->system settings->updates下面的Use secure Connetion去掉安装完重启之后就可以了。使用sonarlint右键项目进行如下操作执行之后可以看到如下信息,如果代码中有不合理的地方会在report中显示,如果没有显示可以多试几次。点击错误的地方在右边会给出建议的修改供参考。
当查询npm版本时候报如下错误:原因是 node 版本与npm版本不相匹配,两个东西需要使用想对应的版本号cmd下输入命令:node -v 查看node版本npm -v 查看npm版本再打开https://nodejs.org/zh-cn/download/releases/ 这个地址查看本地node版本对应哪个npm版本因为我之前本地有7.5.3的npm版本了,根据下面绿色字体提示输入npm install -g npm@7.5.6命令来更新所需npm版本
关于JAVA IDE开发工具,Eclipse系列和Intelli IDEA是大部分公司的主要选择,从开发者的选择角度,Intellij IDEA似乎比Eclipse系列更受欢迎一些。当我们使用Intellij IDEA开发时,我们发现出现中文乱码问题,造成中文乱码的根本原因时开发工具和系统环境编码格式不匹配,本篇采用理论结合实际的角度,彻底解决该问题。一 Intellij IDEA乱码问题记录如下图所示,Intellij IDEA显示中文为乱码。二 解决问题(一)问题识别根据Intellij IDEA控制台输出,Tomcat Catalina Log出现乱码,因此可以将问题定位到Tomcat上。那么,我们看看Tomcat控制台是否出现乱码。果然,是Tomcat输出时出现问题。(二)解决问题1.解决Tomcat输出乱码问题用Notepad++打开Tomcat安装源码conf文件夹下的logging.properties文件。如下logging.properties文件内容,将下图标记的UTF-8改为GBK如下为更换为GBK后的文件内容2.重新启动Tomcat,乱码问题解决3.再打卡Intellij IDEA,乱码问题已解决三 拓展提供如下参考解决方法1.设置字体格式2.删除idea文件夹下的encoding.xml文件除utf-8外的所有文件3.设置Inllij idea文件编码格式,设置为UTF-8。File=>Settings=>Editor=>File Encodings4.配置Tomcat VM options值为:-Dfile.encoding=UTF-85.打卡Intellij idea安装目录,在bin目录下的idea.exe.vmoptions和idea64.exe.vmoptions两个文件结尾添加-Dfile.encoding=UTF-8
用记事本打开hosts文件C:\Windows\System32\drivers\etc\hosts添加以下几行代码并保存192.30.253.112 github.com 219.76.4.4 github-cloud.s3.amazonaws.com 151.101.185.194 github.global.ssl.fastly.net刷新DNS缓存(打开CMD,输入ipconfig /flushdns)重新打开浏览器试试~(该方法截止到本博客发布仍然有效)
1、快捷键Wind+R2、输入cmd3、输入以下代码:Netsh wlan show profile name="无线名字" key=clear4、名称为WiFi名字,关键内容即WiFi密码测试结果:
程序中为什么使用缓存? 先了解一下缓存的概念:原始意义是指访问速度比一般随机存取存储器快的一种RAM,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。对于我们编程来说,所谓的缓存,就是将程序或系统经常要调用的对象(临时数据)存在内存中,以便其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统的开销,提高效率。 对缓存有了一定的了解以后就知道了使用缓存是为了减少和数据库的交互次数,提高执行效率。那么下一个问题来了,什么样的数据能使用缓存,什么样的数据不能使用呢? 这是我们使用缓存必须要明确的事情,实际上适用于缓存的数据指:经常查询并且不经常改变的,并且数据的正确与否对最终结果影响不大的,不适用于缓存的数据:经常改变的数据,数据的正确与否对最终结果影响很大的。 Mybatis中的一级缓存和二级缓存到底缓存了什么,缓存了以后又有什么效果,缓存的数据什么时候会被清空? 一级缓存:它指的是Mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入到SqlSession中为我们提供的一块区域中,该区域的结构是一个Map,当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用,当SqlSession对象消失时,mybatis的一级缓存也就消失了,同时一级缓存是SqlSession范围的缓存,当调用SqlSession的修改、添加、删除、commit(),close等方法时,就会清空一级缓存。 二级缓存:他指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存,但是其中缓存的是数据而不是对象,所以从二级缓存再次查询出的结果对象与第一次存入的对象是不一样的。 通过简单的例子来加深理解一级缓存和二级缓存。一级缓存1.用户类public class User implements Serializable{ private Integer id; private String username; private Date birthday; private String sex; private String address; get和set方法省略..... }2.Dao层public interface UserDao { /** * 查询所有的用户 * * @return */ List<User> findAll(); /** * 根据Id查询用户 * * @return */ User findById(Integer id); /** * 更新用户 * @param user */ void updateUser(User user); }3.UserDao.xml映射文件<mapper namespace="com.example.dao.UserDao"> <select id="findAll" resultType="com.example.domain.User"> SELECT * FROM USER; </select> <select id="findById" resultType="com.example.domain.User" parameterType="INT"> SELECT * FROM USER WHERE ID = #{ID} </select> <update id="updateUser" parameterType="com.example.domain.User"> update USER <set> <if test="username != null">username=#{username},</if> <if test="password != null">birthday=#{birthday},</if> <if test="sex != null">sex=#{sex},</if> <if test="address != null">address=#{address},</if> </set> where id=#{id} </update> </mapper>在以上三步中这是mybatis的单表操作,下面通过根据用户ID查询用户的操作来观察一级缓存生效与否的区别 4.测试(1) 命中一级缓存的情况测试代码:@Test public void findByIdTest(){ session = factory.openSession(); userDao = session.getMapper(UserDao.class); //第一次获取该用户 User user1 = userDao.findById(45); System.out.println(user1); 第二次获取该用户 User user2 = userDao.findById(45); System.out.println(user2); System.out.println(user1 == user2); session.close(); }测试结果:(2)对SqlSession进行清除缓存的操作,即清楚一级缓存,然后再次进行测试。@Test public void findByIdTest(){ session = factory.openSession(); userDao = session.getMapper(UserDao.class); User user1 = userDao.findById(45); System.out.println(user1); //session.commit(); 调用SqlSession的commit方法清空缓存 user1.setUsername("更新用户"); user1.setAddress("更新地址"); userDao.updateUser(user1);//通过更新SqlSession清空缓存 User user2 = userDao.findById(45); System.out.println(user2); System.out.println(user1 == user2); session.close(); }清空缓存的操作很多,可以都试试。测试结果:二级缓存 再看一下Mybatis二级缓存是如何使用的,第一步让Mybatis框架支持二级缓存(在Mybatis的主配置文件中配置),第二步让当前的映射文件支持二级缓存(在Dao.xml映射文件中配置),第三步让当前的方法支持二级缓存(在标签中配置)。根据这个步骤将上面的查询用户的接口通过配置改造为可以支持二级缓存的方法。1.配置Mybatis框架支持二级缓存<setting name="cacheEnabled" value="true"/>2.配置UserDao.xml支持二级缓存<cache/>3.配置查询的方法支持二级缓存<select id="findById" resultType="com.example.domain.User" parameterType="INT" useCache="true"> SELECT * FROM USER WHERE ID = #{ID} </select>4.测试@Test public void findByIdTest(){ //第一次查询 并更新二级缓存 SqlSession session1 = factory.openSession(); UserDao userDao1 = session1.getMapper(UserDao.class); User user1 = userDao1.findById(45); System.out.println(user1); session1.commit(); //commit()方法提交二级缓存 同时清空一级缓存 session1.close();// //user1.setUsername("更新用户"); //user1.setAddress("更新地址"); //userDao.updateUser(user1);//通过更新SqlSession清空缓存 //第二次查找命中二级缓存 SqlSession session2 = factory.openSession(); UserDao userDao2 = session2.getMapper(UserDao.class); User user2 = userDao2.findById(45); session2.commit(); //commit()方法提交二级缓存 同时清空一级缓存 session2.close();// System.out.println(user2); System.out.println(user1 == user2); }测试结果:总结:mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。二级缓存是SqlSessionFactory级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构造对象返回。查询数据的时候,查询的流程是二级缓存>一级缓存>数据库。
1、XShell中查看tomcat报错日志:新建会话:用户名和密码:tomcat/Tomcat-dev主机:10.10.0.150,SSH协议,22端口cd /usr/local/tomcat-8.0.38/logs/tail -1000f catalina.out最新版测试环境:用户名和密码:logquery/密钥文件主机:10.200.111.155,SSH协议,5622端口2、复制和粘贴由于在linux的Shell下,Ctrl+c是中断当前指令,这个快捷键和win系统下的复制快捷键冲突,在Xshell中,提供了其它的快捷键来执行这些操作:复制:Ctrl+Insert粘贴:Shift+Insert3、将当前Shell中的内容复制到"记事本"中有时候需要把shell中的一些内容临时复制到"记事本"中,如果再打开一个记事本,再复制粘贴就显得麻烦了XShell中内置了这一功能,选中内容,鼠标右键,选择"To Notepad"/记事本,再选中’Select Area’或者’All’或者’Screen’4、快速打开Sessions(会话)对话框直接使用’Alt+O’即可打开上次打开的Sessions所在目录的对话框。5、迁移连接信息在XShel中,每个保存的Session连接信息都是保存到.xsh(就是ini文件,可以用文本编辑器打开)文件中的。它的默认路径是“%APPDATA%\NetSarang\Xshell\Sessions”即:C:\Users\用户名\AppData\Roaming\NetSarang\Xshell\Sessions,可直接拷贝这些xsh文件到新的xshell的相同目录即可使用。6、退出时关闭确认对话框选择在这:Tools->Options->Advanced(高级)->'Confirm connection close when session exits'还有一个:Tools->Options->Advanced(高级)->'Confirm connection close when XShell exits'7、快速切换打开的Tab和设置快捷键快捷键:Alt+1~9 或者Ctrl+Tab 或者Shift+Tab设置:Tools->Options->‘Menu & Short Keys’参考1
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。其实两者比较好理解,通常created使用的次数多,而mounted通常是在一些插件的使用或者组件的使用中进行操作。下面通过例子进行解释下,比如:上图红框里的数据固定值,其他数据是由上个页面带过来的数据。在代码中使用:
Spring Boot 之Spring Boot Starter依赖包及作用1、spring-boot-starter这是Spring Boot的核心启动器,包含了自动配置、日志和YAML文件2、spring-boot-starter-amqp通过spring-rabbit来支持AMQP协议(Advanced Message Queuing Protocol)3、spring-boot-starter-aop支持面向方面的编程即AOP,包括spring-aop和AspectJ4、spring-boot-starter-artemis通过Apache Artemis支持JMS的API(Java Message Service API)5、spring-boot-starter-batch支持Spring Batch,包括HSQLDB数据库6、spring-boot-starter-cache支持Spring的Cache抽象7、spring-boot-starter-cloud-connectors支持Spring Cloud Connectors,简化了在Cloud Foundry或Heroku这样的云平台上连接服务8、spring-boot-starter-data-elasticsearch支持ElasticSearch搜索和分析引擎,包括spring-data-elasticsearch9、spring-boot-starter-data-gemfire支持GemFire分布式数据存储,包括spring-data-gemfire10、spring-boot-starter-data-jpa支持JPA(Java Persistence API. ,包括spring-data-jpa、spring-orm、Hibernate11、spring-boot-starter-data-mongodb支持MongoDB数据,包括spring-data-mongodb12、spring-boot-starter-data-rest通过spring-data-rest-webmvc,支持通过REST暴露Spring Data数据仓库13、spring-boot-starter-data-solr支持Apache Solr搜索平台,包括spring-data-solr14、spring-boot-starter-freemarker支持FreeMarker模板引擎15、spring-boot-starter-groovy-templates支持Groovy模板引擎16、spring-boot-starter-hateoas通过spring-hateoas支持基于HATEOAS的RESTful Web服务17、spring-boot-starter-hornetq通过HornetQ支持JMS18、spring-boot-starter-integration支持通用的spring-integration模块19、spring-boot-starter-jdbc支持JDBC数据库20、spring-boot-starter-jersey支持Jersey RESTful Web服务框架21、spring-boot-starter-jta-atomikos通过Atomikos支持JTA分布式事务处理22、spring-boot-starter-jta-bitronix通过Bitronix支持JTA分布式事务处理23、spring-boot-starter-mail支持javax.mail模块24、spring-boot-starter-mobile支持spring-mobile25、spring-boot-starter-mustache支持Mustache模板引擎26、spring-boot-starter-redis支持Redis键值存储数据库,包括spring-redis27、spring-boot-starter-security支持spring-security28、spring-boot-starter-social-facebook支持spring-social-facebook29、spring-boot-starter-social-linkedin支持pring-social-linkedin30、spring-boot-starter-social-twitter支持pring-social-twitter31、spring-boot-starter-test支持常规的测试依赖,包括JUnit、Hamcrest、Mockito以及spring-test模块32、spring-boot-starter-thymeleaf支持Thymeleaf模板引擎,包括与Spring的集成33、spring-boot-starter-velocity支持Velocity模板引擎34、spring-boot-starter-web支持全栈式Web开发,包括Tomcat和spring-webmvc35、spring-boot-starter-websocket支持WebSocket开发36、spring-boot-starter-ws支持Spring Web ServicesSpring Boot应用启动器面向生产环境的还有2种,具体如下:37、spring-boot-starter-actuator增加了面向产品上线相关的功能,比如测量和监控38、spring-boot-starter-remote-shell增加了远程ssh shell的支持。最后,Spring Boot应用启动器还有一些替换技术的启动器,具体如下:39、spring-boot-starter-jetty引入了Jetty HTTP引擎(用于替换Tomcat)40、spring-boot-starter-log4j支持Log4J日志框架41、spring-boot-starter-logging引入了Spring Boot默认的日志框架Logback42、spring-boot-starter-tomcat引入了Spring Boot默认的HTTP引擎Tomcat43、spring-boot-starter-undertow引入了Undertow HTTP引擎(用于替换Tomcat)如果有新的依赖需要补充,可以在后台留言哦
校验令牌Get: http://localhost:40400/auth/oauth/check_token?token=响应结果:该 接 口 请 求 会 重 新 调 用 U s e r D e t a i l s S e r v i c e I m p l 类 中 的 l o a d U s e r B y U s e r n a m e 方 法 。 \color{#FF0000}{该接口请求会重新调用UserDetailsServiceImpl类中的loadUserByUsername方法。}该接口请求会重新调用UserDetailsServiceImpl类中的loadUserByUsername方法。刷新令牌刷新令牌是当令牌快过期时重新生成一个令牌,它和授权码跟密码模式生成令牌不同,刷新令牌是取授权码跟密码模式生成的令牌结果集重新生成一个令牌,只需要一个刷新令牌、客户端id和客户端密码。Post:http://localhost:40400/auth/oauth/token参数:grant_type: 固定为 refresh_tokenrefresh_token:填写申请令牌中的refresh_token字段值刷新令牌成功,会重新生成新的访问令牌和刷新令牌,令牌的有效期也比旧令牌长。刷新令牌通常是在令牌快过期时进行刷新,让客户登录时间延长,不用让用户重新登录。JWT研究传统授权方法的问题是用户每次请求资 源 服 务 \color{#FF0000}{资源服务}资源服务,资源服务都需要携带令牌访问认 证 服 务 \color{#FF0000}{认证服务}认证服务去校验令牌的合法性,并根据令牌获取用户的相关信息,性能低下。使用JWT的思路是,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。J W T 令 牌 就 是 为 了 解 决 不 用 每 次 请 求 认 证 服 务 完 成 授 权 。 \color{#FF0000}{JWT令牌就是为了解决不用每次请求认证服务完成授权。}JWT令牌就是为了解决不用每次请求认证服务完成授权。JWT令牌授权过程如下图:什么是JWT?JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。JWT令牌的优点:1、JWT基于json,非常方便解析。2、可以在令牌中自定义丰富的内容,易扩展。3、通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。4、资源服务使用JWT可不依赖认证服务即可完成授权。缺点:令牌较长,存储空间比较大令牌结构通过学习JWT令牌结构为自定义JWT令牌打好基础。JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz1、Header包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)例如:{ "alg": "HS256", "typ": "JWT" }将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。2、Payload第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比 如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。{ "sub": "1234567890", "name": "456", "admin": true }3、Signature第三部分是签名,此部分用于防止jwt内容被篡改。这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明 签名算法进行签名。HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)base64UrlEncode(header):jwt令牌的第一部分。base64UrlEncode(payload):jwt令牌的第二部分。secret:签名所使用的密钥。JWT入门本节我们使用Spring Security 提供的JwtHelper来创建JWT令牌,校验JWT令牌等操作。生成私钥和公钥JWT令牌生成采用非对称加密算法1、生成密钥证书下边命令生成密钥证书,采用RSA 算法每个证书包含公钥和私钥keytool -genkeypair -alias xckey -keyalg RSA -keypass xuecheng -keystore xc.keystore -storepass xuechengkeystore在桌面创建文件夹jwt,cmd进入该目录,输入上面指令:查询证书信息: keytool -list -keystore xc.keystore口令输入:xuechengkeystore删除别名:keytool -delete -alias xckey -keystore xc.keystore2、导出公钥openssl是一个加解密工具包,这里使用openssl来导出公钥信息。安装 openssl:http://slproweb.com/products/Win32OpenSSL.html配置openssl的path环境变量,本教程配置在D:\Soft\OpenSSL-Win64\bincmd进入xc.keystore文件所在目录执行如下命令:keytool ‐list ‐rfc ‐‐keystore xc.keystore | openssl x509 ‐inform pem ‐pubkey将上边的公钥拷贝到文本文件中,合并为一行放到publickey.txt文件中。1、生成jwt令牌执行TestJwt类中的testCreateJwt方法生成密钥:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoieGh5In0.Y5wtZJAlirAMtQ2qQaNehDDa1uBhHWjJAHeNBXYcKP48rYpdM--oMGXZJgMa56HgXJ29YUtdKJstO8NUqJXLp7GkUvXWDBwhvmlyT82Vci7pwJitgO6YCBaYcXOSUFmWHxDX6o5RrJ0ivfU0nBE07FX30k0eBvDYnxH5FVRqo19WMBR9a36bHcYBrj9ZWsinbOmMUCgLMkNnteXHXPPH7PqTTpAmn_8C5cGQS8ER3CXXlSmRrGSn8uoYQKV87W_x7mapu6lb7vYLgVyBTOH2jUduOYg7rOD4S5JC7XJFvuyEH4z1Mew1k5NqoBBx5dhsRDJFANxoqvQpIlDbwJ1gzg2、验证jwt令牌执行TestJwt类中的testVerify方法进行校验校验成功返回令牌的名字:认证接口开发用户登录的流程图如下:Redis配置1、安装Redis服务2、安装redis-desktop-manager客户端pom文件中添加redis3、redis连接配置在xc-service-ucenter-auth工程的yml文件中配置如下:spring: application: name: xc-service-ucenter-auth redis: host: ${REDIS_HOST:127.0.0.1} port: ${REDIS_PORT:6379} timeout: 5000 #连接超时 毫秒 jedis: pool: maxActive: 3 maxIdle: 3 minIdle: 1 maxWait: -1 #连接池最大等行时间 -1没有限制4、测试执行RedisTest类中的testRedis方法:返回结果,说明执行成功:认证服务1、登录接口前端post提交账号、密码等,用户身份校验通过,生成令牌,并将令牌存储到redis。 将令牌写入cookie。2、退出接口校验当前用户的身份是否合法并且为已登录状态。 将令牌从redis删除。 删除cookie中的令牌。流程:1、api中的方法:在AuthControllerApi类中添加login和logout方法;2、yml文件中配置:auth: tokenValiditySeconds: 1200 #token存储到redis的过期时间 clientId: XcWebApp clientSecret: XcWebApp cookieDomain: xuecheng.com cookieMaxAge: -13、申请令牌为了不破坏Spring Security的代码,我们在Service方法中通过RestTemplate请求Spring Security所暴露的申请令牌接口来申请令牌。执行TestClient类中的testClient方法测试;4、Dao暂时使用静态数据,待用户登录调通再连接数据库校验用户信息。5、Service调用认证服务申请令牌,并将令牌存储到 redis。1、AuthToken创建 AuthToken模型类,存储申请的令牌,包括身份令牌、刷新令牌、jwt令牌身份令牌:用于校验用户是否认证刷新令牌:jwt令牌快过期时执行刷新令牌JWT令牌:用于授权。6、Controller在AuthController中添加、saveCookie、logout方法登录url放行认证服务默认都要校验用户的身份信息,这里需要将登录url放行在WebSecurityConfig类中重写 configure(WebSecurity web)方法,如下:@Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/userlogin","/userlogout","/userjwt"); }测试认证接口:Post请求:http://localhost:40400/auth/userlogin测试结果:测试写入Cookiecookie最终会写到xuecheng.com域名下,可通过nginx代理进行认证,测试cookie是否写成功。1、配置nginx代理在server中添加配置代理路径:#认证 location ^~ /openapi/auth/ { proxy_pass http://auth_server_pool/auth/; }添加:#认证服务 upstream auth_server_pool{ server 127.0.0.1:40400 weight=10; }POST:http://ucenter.xuecheng.com/openapi/auth/userlogin观察cookie写入结果:这个value就是返回值返回的短令牌
用户认证与授权:用户身份认证:用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问。常见的用户身份认证表现形式有:用户名密码登录,指纹打卡等方式。用户授权:用户认证通过后去访问系统的资源,系统会判断用户是否拥有访问资源的权限,只允许访问有权限的系统资源,没有权限的资源将无法访问,这个过程叫用户授权。单点登录(Single Sign On):本项目包括多个子项目,为了提高用户体验性需要实现用户只认证一次便可以在多个拥有访问权限的系统中访问,这个功能叫做单点登录。第三方认证:当需要访问第三方系统资源时需要首先通过第三方系统的认证(例如:微信认证),由第三方系统对用户认证通过,并授权资源的访问权限。微信扫码登录:微信不属于本系统,本系统并没有存储微信用户的账号、密码等信息,本系统如果要获取该用户的基本信息则需要首先通过微信的认证系统(微信认证)进行认证,微信认证通过后本系统便可获取该微信用户的基本信息,从而在本系统将该微信用户的头像、昵称等信息显示出来,该用户便不用在本系统注册即可直接学习。单点登录的特点:1、认证系统为独立的系统2、各子系统通过Http或其它协议与认证系统通信,完成用户认证3、用户身份信息存储在Redis集群Oauth2认证:第三方认证技术方案最主要是解决认证协议的通用标准问题,因为要实现跨系统认证,各系统之间要遵循一定的接口协议。OAUTH协议为用户资源的授权提供了一个安全、开放而又简易的标准。同时任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的,OAUTH标准逐渐成为开放资源授权的标准。微信认证流程:1、用户点击微信登录2、页面由后端生成微信二维码3、用户扫描二维码授权登录4、微信后台接收到授权码然后认证5、后台接收到微信回调函数返回的用户信息6、验证该用户如果第一次登陆存储该用户信息,如果不是第一次登陆请求认证服务器给予权限7、后台处理用户信息将信息展示到页面后端工程搭建1、创建xc-service-ucenter-auth工程pom中导入:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>2、创建xc_user表以“oauth_”开头的表都是spring Security 自带的表。本项目中spring Security 主要使用oauth_client_details表:Oauth2授权模式:授权码模式(Authorization Code) 、隐式授权模式(Implicit) 、密码模式(Resource Owner Password Credentials) 、客户端模式(Client Credentials)其中授权码模式和密码模式应用较多,本小节介绍授权码模式3、授权码授权流程1、客户端请求第三方授权2、用户(资源拥有者)同意给客户端授权3、客户端获取到授权码,请求认证服务器申请令牌4、认证服务器向客户端响应令牌5、客户端请求资源服务器的资源,资源服务校验令牌合法性,完成授权6、资源服务器返回受保护资源启动工程,浏览器输入如下地址,请求认证服务获取授权码:localhost:40400/auth/oauth/authorize? client_id=XcWebApp&response_type=code&scop=app&redirect_uri=http://localhost参数列表如下:client_id:客户端id,和授权配置类oauth_client_details中设置的客户端id一致response_type:授权码模式固定为code,密码模式为passwordscop:客户端范围,和授权配置类中设置的scop一致redirect_uri:跳转uri,当授权码申请成功后会跳转到此地址,并在后边带上code参数(授权码)首页跳转到如下页面:输入用户名和密码后跳转http://localhost路径,网址最右侧的code即为授权码。用户名和密码都是:XcWebApp点击Authorize授权登录后跳转到首页:拿到授权码:JyJ40q接着申请令牌申请令牌利用postman请求:Post请求:http://localhost:40400/auth/oauth/token此链接需要使用 http Basic认证。响应数据:access_token:访问令牌token_type:令牌类型refresh_token:刷新令牌expires_in:令牌过期时间scope:作用范围jti:通常存储到session中资源服务授权配置资源服务拥有要访问的受保护资源,客户端携带令牌访问资源服务,如果令牌合法则可成功访问资源服务中的资源,如下图:1、配置公钥启动course工程,输入如下内容:http://localhost:31200/course/coursepic/list/297e7c7c62b888f00162b8a7dec20000无法访问,如下图所示:需要放行后才能访问,下面有解决方法。正常显示:认证服务生成令牌采用非对称加密算法,认证服务采用私钥加密生成令牌,对外向资源服务提供公钥,资源服务使用公钥来校验令牌的合法性。微 服 务 接 入 认 证 , 需 要 如 下 操 作 : \color{#FF0000}{微服务接入认证,需要如下操作:}微服务接入认证,需要如下操作:将公钥拷贝到 publickey.txt文件中,将此文件拷贝到课程服务工程的resource下2、pom中添加依赖<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>3、在config包下创建ResourceServerConfig类4、测试课程图片携带令牌查询get:http://localhost:31200/course/coursepic/list/297e7c7c62b888f00162b8a7dec20000请求时没有携带令牌则报错,如上图请求时携带令牌:在http header中添加 Authorization: Bearer+空格+令牌当输入错误的令牌也无法正常访问资源。当课程管理加了授权之后再访问swagger-ui则报错:针对swagger-ui的请求路径进行放行,修改授权配置类ResourceServerConfig的configure方法://Http安全配置,对每个到达系统的http请求链接进行校验 @Override public void configure(HttpSecurity http) throws Exception { //所有请求必须认证通过 http.authorizeRequests() //下边的路径放行 .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui", "/swagger-resources","/swagger-resources/configuration/security", "/swagger-ui.html","/webjars/**","/course/coursepic/list/**").permitAll() .anyRequest().authenticated(); }注意: 通过上边的配置虽然可以访问swagger-ui,但是无法进行接口调用,除非去掉认证的配置或在上边配置中添加所有请求均放行("/**")。此时可以访问:Oauth2密码模式授权Post请求:http://localhost:40400/auth/oauth/token参数: grant_type:密码模式授权填写passwordusername:itcastpassword:123并且此链接需要使用 http Basic认证该 接 口 请 求 首 先 调 用 U s e r D e t a i l s S e r v i c e I m p l 类 中 的 l o a d U s e r B y U s e r n a m e 方 法 。 \color{#FF0000}{该接口请求首先调用UserDetailsServiceImpl类中的loadUserByUsername方法。}该接口请求首先调用UserDetailsServiceImpl类中的loadUserByUsername方法。请求后结果:将access_token字段粘贴到Authorization一栏,请求结果:微 服 务 之 间 的 认 证 用 密 码 模 式 , 微 信 三 方 登 录 用 授 权 码 模 式 \color{#FF0000}{微服务之间的认证用密码模式,微信三方登录用授权码模式}微服务之间的认证用密码模式,微信三方登录用授权码模式
1、要安装Redis,首先要获取安装包。Windows的Redis安装包需要到以下GitHub链接找到。链接:https://github.com/MSOpenTech/redis。打开网站后,找到Release,点击前往下载页面。2、在下载网页中,找到最后发行的版本(此处是3.2.100)。找到Redis-x64-3.2.100.msi和Redis-x64-3.2.100.zip,点击下载。这里说明一下,第一个是msi微软格式的安装包,第二个是压缩包。3、双击刚下载好的msi格式的安装包(Redis-x64-3.2.100.msi)开始安装。4、选择“同意协议”,点击下一步继续。5、选择“添加Redis目录到环境变量PATH中”,这样方便系统自动识别Redis执行文件在哪里。6、端口号可保持默认的6379,并选择防火墙例外,从而保证外部可以正常访问Redis服务。7、设定最大值为100M。作为实验和学习,100M足够了。8、点击安装后,正式的安装过程开始。稍等一会即可完成。9、安装完毕后,需要先做一些设定工作,以便服务启动后能正常运行。使用文本编辑器,这里使用Notepad++,打开Redis服务配置文件。redis.windows−service.conf,而不是redis.windows.conf。后者是以非系统服务方式启动程序使用的配置文件。10、找到含有requirepass字样的地方,追加一行,输入requirepass 12345。这是访问Redis时所需的密码,一般测试情况下可以不用设定密码。不过,即使是作为本地访问,也建议设定一个密码。此处以简单的12345来演示。11、点击“开始”>右击“计算机”>选择“管理”。在左侧栏中依次找到并点击“计算机管理(本地)”>服务和应用程序>服务。再在右侧找到Redis名称的服务,查看启动情况。如未启动,则手动启动之。正常情况下,服务应该正常启动并运行了。12、最后来测试一下Redis是否正常提供服务。进入Redis的目录,cd C:\Program Files\Redis。输入redis-cli并回车。(redis-cli是客户端程序)如图正常提示进入,并显示正确端口号,则表示服务已经启动。13、使用服务前需要先通过密码验证。输入“auth 12345”并回车(12345是之前设定的密码)。返回提示OK表示验证通过。14、实际测试一下读写。输入set mykey1 "I love you all!”并回车,用来保存一个键值。再输入get mykey1,获取刚才保存的键值。15、注意事项Windows使用的这个Redis是64位版本的,32位操作系统的同学就不要折腾了。作 为 服 务 运 行 的 R e d i s 配 置 文 件 , 通 常 为 r e d i s . w i n d o w s − s e r v i c e . c o n f , 而 不 是 r e d i s . w i n d o w s . c o n f 。 小 心 不 要 选 错 了 。 \color{#FF0000}{作为服务运行的Redis配置文件,通常为redis.windows-service.conf,而不是redis.windows.conf。小心不要选错了。}作为服务运行的Redis配置文件,通常为redis.windows−service.conf,而不是redis.windows.conf。小心不要选错了。
相信很多人在使用webpack-dev-server时肯定会遇到一些问题(如下图所示)我在学习vue框架的时候因为要使用到webpack工具,但这个工具又是基于node,而我对node没有任何基础,然后每次出现问题就在网上疯狂的找啊找,在网上诸如类似这个问题的解答很多,但是每个人的情况不一样,而我相信我的情况是最复杂的那种,试过网上所有办法之后还是没有解决,最后摸索出了一套自己的万能解决办法!w e b p a c k − d e v − s e r v e r 错 误 法 则 : \color{#FF0000}{webpack-dev-server错误法则:}webpack−dev−server错误法则:前往项目根目录删除node_modules文件夹,然后在项目根目录路径下的终端运行"npm install"等待安装完之后,再次运行“npm run dev”,有些人的是马上就可以了,然而往往还会有人(譬如我)仍然报类似的错误,这个时候你只需要再次重复相同的操作即可,“一次不成再删再安装”!!!测试结果:
环境: centos7官网部署地址:https://redash.io/help/open-source/dev-guide/docker一、安装步骤1、虚拟机安装安装vmware,并安装centos72、安装dockerdocker安装手册3、安装nodejscentos下安装Nodejs4、redash安装1)、clone git repostory git clone https://github.com/getredash/redash.git 2)、Create Docker Services docker-compose up 3)、Install npm Packages npm install 4)、Create DatabaseCreate tablesdocker-compose run --rm server create_dbCreate database for testsdocker-compose run --rm postgres psql -h postgres -U postgres -c “create database tests”5、启动redashdocker-compose -f docker-compose.yml up -d6、邮箱配置参考地址:https://redash.io/help/open-source/setup/https://ithelp.ithome.com.tw/articles/10207745?sc=iThelpRhttps://www.copylian.com/technology/201.html在docker-compose.yml 中配置:复制代码REDASH_MAIL_SERVER: “smtp.163.com”REDASH_MAIL_PORT: 465REDASH_MAIL_USE_TLS: “false”REDASH_MAIL_USE_SSL: “true”REDASH_MAIL_USERNAME: “xxxx@163.com”REDASH_MAIL_PASSWORD: “xxxxxx”REDASH_MAIL_DEFAULT_SENDER: “xxxxx@163.com”复制代码邮箱测试:docker-compose run --rm server manage send_test_mail二、问题1、npm build报错处理 https://blog.csdn.net/wq18512847606/article/details/808477512、安装pip https://www.cnblogs.com/BillyYoung/p/11088470.html3、解决启动错误:(docker-entrypoint) https://www.jianshu.com/p/ffe2b5a08897让每一天过的有意义!
重新设置postgres用户的密码方法:1、关闭数据库服务2、进入数据库的工作空间目录 (如果是建库是没有另外指定,应该就是postgresql安装目录下的 data 目录)3、编辑修改文件 pg_hba.conf, 把连接权限设置的 md5 加密方式 改成 trust,两个IPV4都要修改以我的为例,原本设置是# IPv4 local connections: host all all 127.0.0.1/32 md5修改为# IPv4 local connections: host all all 127.0.0.1/32 trust 4、重新新启动postgresql数据库服务 5、可以不用密码就能用postgres用户登陆,然后执行修改用户密码的操作 alter user postgres with password 'foobar'; 6、修改 pg_hba.conf 文件,改回到 md5 方式,再重启数据库服务设置完成。
1、Docker的相关概念虚拟化:虚拟化就是将各种实体资源虚拟。镜像:一个只读的静态模板。容器:一个运行时环境,是镜像的运行状态。库:使用注册服务器存储和共享用户的镜像。容器技术可以让多个独立的用户空间运行在同一台宿主机上。2、Docker安装与启动Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的。在很多版本的CentOS中是不支持更新最新的一些补丁包的。由于我们学习的环境都使用的是CentOS,因此这里我们将Docker安装到CentOS上。注意:这里建议安装在CentOS7.x以上的版本,在CentOS6.x的版本中,安装前需要安装其他很多的环境而且Docker很多补丁不支持更新。2.1、在VMware Workstation中安装CentOS7CentOS7的下载安装教程如下:https://blog.csdn.net/yang_guang3/article/details/1006673532.2、安装Docker使用yum指令在线安装:yum install dockerAre you OK???当然是y安装完成后查看版本号验证是否安装成功:docker -v2.3、启动和停止docker由于古老的指令service docker start在init进程中是串行启动,只有前一个进程启动完,才会启动下一个进程,大大的降低了效率,所以使用到了systemctl命令,systemctl是 Systemd 的主命令,用于管理系统。根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。查看docker:systemctl status docker启动docker:systemctl start docker停止docker:systemctl stop docker重启docker:systemctl restart docker开机启动:systemctl enable docker查看docker概要信息:docker info查看docker帮助文档:docker --help输入查看docker命令后如果显示绿点,代表启动成功:3、docker镜像的安装与删除3.1、查看镜像:docker imagesrepository:镜像所在的仓库名称;tag:镜像的版本号,同一个镜像可以安装不同版本号的镜像;image id:镜像id,删除镜像时候会用到;created:镜像创建时间;size:镜像大小;这些镜像都是存储在宿主机的/var/lib/docker目录下。我们在运行同一个仓库中的不同镜像时,可以通过在仓库名后面加上一个冒号和标签名来指定该仓库中的某一具体的镜像,例如docker run --name custom_container_name –i –t docker.io/ubunto:12.04 /bin/bash,表明从镜像Ubuntu:12.04启动一个容器,而这个镜像的操作系统就是Ubuntu:12.04。在构建容器时指定仓库的标签也是一个好习惯。3.2、搜索镜像:docker search tomcatname:仓库名称;description:镜像描述;stars:用户评价,反映了一种受欢迎程度;official:是否官方;automate:自动构建,表示该镜像由Docker Hub自动构建流程创建的;3.3、拉取镜像:docker pull centos:7由于从Docker Hub拉取,属于国外下载,需要配置镜像加速器,本次使用中科大的ustc镜像加速器。编辑该文件:vi /etc/docker/daemon.json在改文件下输入以下内容:{ "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] }然后保存:esc-->:wq删除镜像:3.4、删除镜像删除指定镜像:docker rmi IMAGE_ID删除所有镜像:docker rmi 'docker images -q'4.2、创建与启动容器4.2.1、交互式容器查看正在运行的容器:docker ps查看所有的容器:docker ps -a查看最后一次运行的容器:docker ps -l查看停止的容器:docker ps -f status=exited4.2、创建与启动容器4.2.1、交互式容器创建一个容器:docker run -it --name=mycentos centos:7 /bin/bash参数解释:docker run:创建容器指令;-i:表示运行容器;-t:加入这两个参数后容器创建后就能登录进去;–name:容器名;/bin/bash:创建完成后进入容器;其他参数:-v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上;-d:在run后面加上-d参数,则会创建一个守护式容器在后台运行;-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射;这时我们通过ps命令查看,发现可以看到启动的容器,up为启动状态。使用exit命令 退出当前容器:4.2.2、守护式容器如果对于一个需要长期运行的容器来说,我们可以创建一个守护式容器。命令如下(容器名称不能重复):docker run -di --name=mycentos2 centos:7进入容器(exit退出时,容器不会停止):docker exec -it mycentos2 /bin/bash4.2.3、容器的启动与停止启动容器:docker start CONTAINER_NAME(容器的名称)停止容器:docker stop CONTAINER_NAME(容器的名称)4.2.4、查看容器的IP地址查看容器各种信息:docker inspect mycentos查看容器IP地址:docker inspect --format='{{.NetworkSettings.IPAddress}}' mycentos未启动时显示空白;4.2.5、删除容器删除指定容器:docker rm $CONTAINER_ID/NAME删除所有容器:docker rm $(docker ps -a | awk '{ print $1}' | tail -n +2)4.2.6、文件的拷贝首先进入docker的image目录:cd /var/lib/docker/image创建文件夹:mkdir file1将系统中的文件拷贝到docker容器中:docker cp file1 mycentos:usr/local然后进入该容器:docker exec -it mycentos /bin/bash进入指定的文件夹:cd usr/local将docker容器中的文件拷贝到系统中:docker cp mycentos:usr/local/games /var/lib/docker/image此处需要注意:docker命令不能在容器中执行,需要先exit后再执行命令。4.2.7、目录挂载我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器。系统和容器中的文件夹资源共享创建容器 添加-v参数,后边为宿主机目录:容器目录首先创建共享文件夹:mkdir /var/lib/docker/image/myhtml然后创建新的docker容器:docker run -di --name=mycentos3 -v /var/lib/docker/image/myhtml:/usr/local/mh --privileged=true centos:7–privileged=true:如果你共享的是多级的目录,可能会出现权限不足的提示,此命令就是为了解决该问题,释放CentOS7中的安全模块selinux的权限。该指令执行成功后,然后在myhtml文件夹下创建文件:echo aaa>file.txt创建成功后进入该容器,可以看到刚才创建的文件如图所示:5、创建Mysql容器并使用navicat连接5.1、创建mysql容器docker中不存在mysql镜像时可以先拉取该镜像:docker pull mysql拉取成功后查看镜像:docker images然后创建mysql容器:docker run -di --name cht_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql注意Linux中是区分大小写的,所以后面命令一定要大写;-p 代表端口映射,格式为 宿主机映射端口:容器运行端口-e 代表添加环境变量 MYSQL_ROOT_PASSWORD是root用户的登陆密码5.2、进入MySQL容器,登陆MySQL进入mysql容器:docker exec -it cht_mysql /bin/bash登录mysql:mysql -u root -p然后输入密码root,显示登录成功;5.3、进行配置,使外部工具可以连接由于mysql中root执行绑定在了localhost,因此需要对root进行授权,代码如下:授权mysql>: ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';刷新权限mysql>:FLUSH PRIVILEGES;然后使用navicat进行测试(注意:此处连接的是虚拟机的IP地址):6、Redis部署docker中不存在Redis镜像时可以先拉取该镜像:docker pull redis拉取成功后查看镜像:docker images然后创建Redis容器:docker run -di --name=cht_redis -p 6379:6379 redis客户端测试:在自己的本地电脑命令提示符下,用window版本redis测试:redis-cli -h 192.168.25.130然后显示如下图:7、Nginx部署docker中不存在Nginx镜像时可以先拉取该镜像:docker pull nginx拉取成功后查看镜像:docker images然后创建Nginx容器:docker run -di --name=cht_nginx -p 80:80 nginx测试Nginx:
推荐一个目前最专业的小程序商城: CRMEBwx-gesture-lock 微信小程序的手势密码WXCustomSwitch 微信小程序自定义 Switch 组件模板WeixinAppBdNovel 微信小程序demo:百度小说搜索shitoujiandaobu 小程序:石头剪刀布(附代码说明)audiodemo 微信小程序开发之视频播放器 Video 弹幕 弹幕颜色自定义star 微信小程序开发之五星评分switchCity 微信小程序开发之城市选择器 城市切换huadong_del 微信小程序滑动删除效果jianhang_menu 微信小程序开发之圆形菜单 仿建行圆形菜单xiaoxiaoxiao_lazyload 实现微信小程序图片懒加载特效kangaiduowei 微信小程序:康爱多微商城:学习界面设计tianmao_dazhuanpan 小程序实现大转盘 仿天猫抽奖 跑马灯效果(有图有源码)weapp-meirong 微信小程序学习用demo推荐:美容商城;列表,预约baisi 微信小程序仿百思不得姐weapp-one 仿 「ONE · 一个」 的微信小程序netmusic-app 仿网易云音乐APP的微信小程序a_takeaway 微信小程序的外卖demosideslip 微信小程序『侧边栏滑动』特效wx_plo 微信小程序之仿微信漂流瓶kwonWhere 微信小程序-知亦行audiodemo 微信小程序开发之视频播放 弹幕 弹幕颜色自定义wxChart 微信小程序图标插件guoku 微信小程序-果库snake 微信小程序-贪吃蛇小程序douban_movie 微信小程序-仿豆瓣电影RecordDemo 麦克风动画shishanggou 实现了包括常用组件,ajax获取数据,模板使用,路由等的使用,下拉刷新数据;jiajuzaixian 家具在线-演示如何使用下拉选项wechat-app-ipinbb 爱拼宝宝-功能非常全的电商应用TodayNews-wx 微信小程序-今日头条WXNative-bpgg 奔跑果果-微信小程序wechatapp-demo 是目前我发现的,实现实用功能较多的demo,推荐大家学习研究weapp-MatterAssistant 微信小程序-事项助手weapp-wymusic 微信小程序 仿网易云音乐weapp-wechat-nearby 微信小程序-仿找事吧app附近三公里bs 精简版百思不得姐WXBaiSi 微信小程序版 百思不得姐weapp-demo-breadtrip 基于面包旅行 API 制作的微信小程序示例html-to-wxml 小程序中将html内容转化成wxml可以显示的内容,方便用于小程序中显示kachezhijia 自卡车之家,有丰富的卡车司机和物流园区的资源,所以这个小程序可以说也是他们未来工作上的一个必将实施的项目。WxEmojiView 微信小程序Emoji展示输入组件alpha 0.1GankCamp-WechatAPP gank.io (干货集中营) 微信小程序 版本wechat-JD 微信小程序仿京东首页wechat-turntalbe-canvas 用微信小程序开发的Canvas绘制可配置的转盘抽奖。mangguoTv 微信小应用-小程序-demo-仿芒果TVwxreading 微信小程序跟读WeChatMeiZhi 微信小程序版妹纸图 API from gank.ioCountDown 微信小程序倒计时组件weapp-github 微信小程序--githubwechat-weapp-mapdemo 微信小程序开发demo-地图定位,非常简单的demo,只为了解一下微信小程序wechat-cnode 微信小程序 cnode社区版weapp-newsapp 微信小程序-公众号热门文章信息流wechat-weapp-taobao 微信小程序demo 仿手机淘宝timer 番茄时钟微信小程序版wechat-app-music 微信小程序:音乐播放器 技术栈: redux + es7 +labradorfenda-mock 使用微信小程序实现「分答」这款APP的基础功能Wa-UI 针对微信小程序整合的一套UI库wx-query 微信小程序 仿jQuery插件weapp-artand 微信小程序 ArtandWeiXin-SmallApps-Information 微信小程序-仿今日头条weapp-wechat-zhihu 微信中的知乎--微信小程序WeApp 基于微信小程序开发的仿微信demoSmallApp 微信小程序wechat-v2ex 微信小程序-v2exweipiao 微信小程序-微票DouBanBookApp 微信小程序之小豆瓣图书wxapp-calc 一个简单的微信小程序-简易计算器weapp-wechat-zhihu 模仿知乎的小程序wx-movies-demo 小程序--影讯caiquan 微信小应用,猜拳小游戏hayeah-wxapp-Breakfast 小林早厨微信小程序AppleMusic 微信小程序,仿Apple Musiccnode_wechat-webapp 用cnode社区api做的微信小应用shoppingcar 一个点餐、购物的购物车效果wechat-weapp-mall 微信小程序实现移动端商城SmallAppForQQ 高仿手机QQ应用程序zhihudaily 微信小程序-知乎日报wechat-weapp-gank 微信小程序-干货投稿应用TeamToy 调用TeamToy API 的微信小程序 Demodouban 微信小程序(应用号)示例教程(豆瓣电影)
Eclipse崩溃,错误提示:MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memory) space remains. It is strongly recommendedthat you exit and restart MyEclipse with new virtual machine memoryparamters to increase this memory. Failure to do so can result indata loss. The recommended Eclipse memory parameters are: eclipse.exe -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M1.参数的含义-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了-Xms128m JVM初始分配的堆内存-Xmx512m JVM最大允许分配的堆内存,按需分配-XX:PermSize=64M JVM初始分配的非堆内存-XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。1)堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,用来存放对象本身以及数组的。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。 可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的, 所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。 堆内存分配 JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制; 空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。 说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try...catch捕捉。 非堆内存分配 JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。(还有一说:MaxPermSize缺省值和-server -client选项相关, -server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。) 上面错误信息中的PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。还没有弄明白PermGen space是属于非堆内存,还是就是非堆内存,但至少是属于了。XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存益出。 说说为什么会内存益出: (1)这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同。 (2)GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。 这种错误常见在web服务器对JSP进行pre compile的时候。 2)JVM内存限制(最大值) 首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制, 这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动? 通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统。所以说设置VM参数导致程序无法启动主要有以下几种原因:1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。说到实际物理内存这里需要说明一点的是, 如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。3. 为何将上面的参数写入到eclipse.ini文件Eclipse没有执行对应的设置? 那为什么同样的参数在快捷方式或者命令行中有效而在eclipse.ini文件中是无效的呢?这是因为我们没有遵守eclipse.ini文件的设置规则:参数形如“项 值”这种形式,中间有空格的需要换行书写,如果值中有空格的需要用双引号包括起来。比如我们使用-vm C:/Java/jre1.6.0/bin/javaw.exe参数设置虚拟机,在eclipse.ini文件中要写成这样:-vm C:/Java/jre1.6.0/bin/javaw.exe -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M 实际运行的结果可以通过Eclipse中“Help”-“About Eclipse SDK”窗口里面的“Configuration Details”按钮进行查看。另外需要说明的是,Eclipse压缩包中自带的eclipse.ini文件内容是这样的:-showsplash org.eclipse.platform --launcher.XXMaxPermSize 256m -vmargs -Xms40m -Xmx256m 其中–launcher.XXMaxPermSize(注意最前面是两个连接线)跟-XX:MaxPermSize参数的含义基本是一样的,我觉得唯一的区别就是前者是eclipse.exe启动的时候设置的参数,而后者是eclipse所使用的JVM中的参数。其实二者设置一个就可以了,所以这里可以把–launcher.XXMaxPermSize和下一行使用#注释掉。4. 其他的启动参数。 如果你有一个双核的CPU,也许可以尝试这个参数:-XX:+UseParallelGC让GC可以更快的执行。(只是JDK 5里对GC新增加的参数)补充: 如果你的WEB APP下都用了大量的第三方jar,其大小超过了服务器jvm默认的大小,那么就会产生内存益出问题了。解决方法: 设置MaxPermSize大小 可以在myelipse里选中相应的服务器比如tomcat5,展开里面的JDK子项页面,来增加服务器启动的JVM参数设置:-Xms128m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m或者手动设置MaxPermSize大小,比如tomcat,修改TOMCAT_HOME/bin/catalina.bat,在echo "Using CATALINA_BASE: $CATALINA_BASE"上面加入以下行: JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存
Redis目前支持5种数据类型,分别是:String(字符串)List(列表)Hash(字典)Set(集合)Sorted Set(有序集合)下面就分别介绍这五种数据类型及其相应的操作命令。1. String(字符串)String是简单的 key-value 键值对,value 不仅可以是 String,也可以是数字。String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。应用场景String是最常用的一种数据类型,普通的key/value存储都可以归为此类,这里就不所做解释了。相关命令SET key value 设置key=value GET key 或者键key对应的值 GETRANGE key start end 得到字符串的子字符串存放在一个键 GETSET key value 设置键的字符串值,并返回旧值 GETBIT key offset 返回存储在键位值的字符串值的偏移 MGET key1 [key2..] 得到所有的给定键的值 SETBIT key offset value 设置或清除该位在存储在键的字符串值偏移 SETEX key seconds value 键到期时设置值 SETNX key value 设置键的值,只有当该键不存在 SETRANGE key offset value 覆盖字符串的一部分从指定键的偏移 STRLEN key 得到存储在键的值的长度 MSET key value [key value...] 设置多个键和多个值 MSETNX key value [key value...] 设置多个键多个值,只有在当没有按键的存在时 PSETEX key milliseconds value 设置键的毫秒值和到期时间 INCR key 增加键的整数值一次 INCRBY key increment 由给定的数量递增键的整数值 INCRBYFLOAT key increment 由给定的数量递增键的浮点值 DECR key 递减键一次的整数值 DECRBY key decrement 由给定数目递减键的整数值 APPEND key value 追加值到一个键其中用于操作管理键的命令有:DEL key 如果存在删除键 DUMP key 返回存储在指定键的值的序列化版本 EXISTS key 此命令检查该键是否存在 EXPIRE key seconds 指定键的过期时间 EXPIREAT key timestamp 指定的键过期时间。在这里,时间是在Unix时间戳格式 PEXPIRE key milliseconds 设置键以毫秒为单位到期 PEXPIREAT key milliseconds-timestamp 设置键在Unix时间戳指定为毫秒到期 KEYS pattern 查找与指定模式匹配的所有键 MOVE key db 移动键到另一个数据库 PERSIST key 移除过期的键 PTTL key 以毫秒为单位获取剩余时间的到期键。 TTL key 获取键到期的剩余时间。 RANDOMKEY 从Redis返回随机键 RENAME key newkey 更改键的名称 RENAMENX key newkey 重命名键,如果新的键不存在 TYPE key 返回存储在键的数据类型的值。使用示例redis 127.0.0.1:6379> set baidu http://www.baidu OK redis 127.0.0.1:6379> append baidu .com (integer) 20 redis 127.0.0.1:6379> get baidu "http://www.baidu.com" redis 127.0.0.1:6379> set visitors 0 OK redis 127.0.0.1:6379> incr visitors (integer) 1 redis 127.0.0.1:6379> incr visitors (integer) 2 redis 127.0.0.1:6379> get visitors "2" redis 127.0.0.1:6379> incrby visitors 100 (integer) 102 redis 127.0.0.1:6379> get visitors "102" redis 127.0.0.1:6379> type baidu string redis 127.0.0.1:6379> type visitors string redis 127.0.0.1:6379> ttl baidu (integer) -1 redis 127.0.0.1:6379> rename baidu baidu-site OK redis 127.0.0.1:6379> get baidu (nil) redis 127.0.0.1:6379> get baidu-site "http://www.baidu.com"2. List(列表)Redis列表是简单的字符串列表,可以类比到C++中的std::list,简单的说就是一个链表或者说是一个队列。可以从头部或尾部向Redis列表添加元素。列表的最大长度为2^32 - 1,也即每个列表支持超过40亿个元素。Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。应用场景Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表、粉丝列表等都可以用Redis的list结构来实现,再比如有的应用使用Redis的list类型实现一个简单的轻量级消息队列,生产者push,消费者pop/bpop。相关命令BLPOPBLPOP key1 [key2 ] timeout 取出并获取列表中的第一个元素,或阻塞,直到有可用BRPOPBRPOP key1 [key2 ] timeout 取出并获取列表中的最后一个元素,或阻塞,直到有可用BRPOPLPUSHBRPOPLPUSH source destination timeout 从列表中弹出一个值,它推到另一个列表并返回它;或阻塞,直到有可用LINDEXLINDEX key index 从一个列表其索引获取对应的元素LINSERTLINSERT key BEFORE|AFTER pivot value 在列表中的其他元素之后或之前插入一个元素LLENLLEN key 获取列表的长度LPOPLPOP key 获取并取出列表中的第一个元素LPUSHLPUSH key value1 [value2] 在前面加上一个或多个值的列表LPUSHXLPUSHX key value 在前面加上一个值列表,仅当列表中存在LRANGELRANGE key start stop 从一个列表获取各种元素LREMLREM key count value 从列表中删除元素LSETLSET key index value 在列表中的索引设置一个元素的值LTRIMLTRIM key start stop 修剪列表到指定的范围内RPOPRPOP key 取出并获取列表中的最后一个元素RPOPLPUSHRPOPLPUSH source destination 删除最后一个元素的列表,将其附加到另一个列表并返回它RPUSHRPUSH key value1 [value2] 添加一个或多个值到列表RPUSHXRPUSHX key value 添加一个值列表,仅当列表中存在使用示例> lpush list1 redis (integer) 1 redis 127.0.0.1:6379> lpush list1 hello (integer) 2 redis 127.0.0.1:6379> rpush list1 world (integer) 3 redis 127.0.0.1:6379> llen list1 (integer) 3 redis 127.0.0.1:6379> lrange list1 0 3 1) "hello" 2) "redis" 3) "world" redis 127.0.0.1:6379> lpop list1 "hello" redis 127.0.0.1:6379> rpop list1 "world" redis 127.0.0.1:6379> lrange list1 0 3 1) "redis"3. Hash(字典,哈希表)类似C#中的dict类型或者C++中的hash_map类型。Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。应用场景假设有多个用户及对应的用户信息,可以用来存储以用户ID为key,将用户信息序列化为比如json格式做为value进行保存。相关命令HDELHDEL key field[field...] 删除对象的一个或几个属性域,不存在的属性将被忽略HEXISTSHEXISTS key field 查看对象是否存在该属性域HGETHGET key field 获取对象中该field属性域的值HGETALLHGETALL key 获取对象的所有属性域和值HINCRBYHINCRBY key field value 将该对象中指定域的值增加给定的value,原子自增操作,只能是integer的属性值可以使用HINCRBYFLOATHINCRBYFLOAT key field increment 将该对象中指定域的值增加给定的浮点数HKEYSHKEYS key 获取对象的所有属性字段HVALSHVALS key 获取对象的所有属性值HLENHLEN key 获取对象的所有属性字段的总数HMGETHMGET key field[field...] 获取对象的一个或多个指定字段的值HSETHSET key field value 设置对象指定字段的值HMSETHMSET key field value [field value ...] 同时设置对象中一个或多个字段的值HSETNXHSETNX key field value 只在对象不存在指定的字段时才设置字段的值HSTRLENHSTRLEN key field 返回对象指定field的value的字符串长度,如果该对象或者field不存在,返回0.HSCANHSCAN key cursor [MATCH pattern] [COUNT count] 类似SCAN命令使用示例127.0.0.1:6379> hset person name jack (integer) 1 127.0.0.1:6379> hset person age 20 (integer) 1 127.0.0.1:6379> hset person sex famale (integer) 1 127.0.0.1:6379> hgetall person 1) "name" 2) "jack" 3) "age" 4) "20" 5) "sex" 6) "famale" 127.0.0.1:6379> hkeys person 1) "name" 2) "age" 3) "sex" 127.0.0.1:6379> hvals person 1) "jack" 2) "20" 3) "famale"4. Set(集合)可以理解为一堆值不重复的列表,类似数学领域中的集合概念,且Redis也提供了针对集合的求交集、并集、差集等操作。set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。应用场景Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。相关命令SADDSADD key member [member ...] 添加一个或者多个元素到集合(set)里SACRDSCARD key 获取集合里面的元素数量SDIFFSDIFF key [key ...] 获得队列不存在的元素SDIFFSTORESDIFFSTORE destination key [key ...] 获得队列不存在的元素,并存储在一个关键的结果集SINTERSINTER key [key ...] 获得两个集合的交集SINTERSTORESINTERSTORE destination key [key ...] 获得两个集合的交集,并存储在一个集合中SISMEMBERSISMEMBER key member 确定一个给定的值是一个集合的成员SMEMBERSSMEMBERS key 获取集合里面的所有keySMOVESMOVE source destination member 移动集合里面的一个key到另一个集合SPOPSPOP key [count] 获取并删除一个集合里面的元素SRANDMEMBERSRANDMEMBER key [count] 从集合里面随机获取一个元素SREMSREM key member [member ...] 从集合里删除一个或多个元素,不存在的元素会被忽略SUNIONSUNION key [key ...] 添加多个set元素SUNIONSTORESUNIONSTORE destination key [key ...] 合并set元素,并将结果存入新的set里面SSCANSSCAN key cursor [MATCH pattern] [COUNT count] 迭代set里面的元素使用示例redis> SADD myset "Hello" (integer) 1 redis> SADD myset "World" (integer) 1 redis> SMEMBERS myset 1) "World" 2) "Hello" redis> SADD myset "one" (integer) 1 redis> SISMEMBER myset "one" (integer) 1 redis> SISMEMBER myset "two" (integer) 0使用集合数据结构的典型用例是朋友名单的实现:redis 127.0.0.1:6379> sadd friends:leto ghanima paul chani jessica (integer) 4 redis 127.0.0.1:6379> sadd friends:duncan paul jessica alia (integer) 3 redis 127.0.0.1:6379> sismember friends:leto jessica (integer) 1 #不管一个用户有多少个朋友,我们都能高效地(O(1)时间复杂度)识别出用户X是不是用户Y的朋友 redis 127.0.0.1:6379> sismember friends:leto vladimir (integer) 0 redis 127.0.0.1:6379> sinter friends:leto friends:duncan #我们可以查看两个或更多的人是不是有共同的朋友 1) "paul" 2) "jessica" redis 127.0.0.1:6379> sinterstore friends:leto_duncan friends:leto friends:duncan # 可以在一个新的关键字里存储结果 (integer) 25. Sorted Set(有序集合)Redis有序集合类似Redis集合,不同的是增加了一个功能,即集合是有序的。一个有序集合的每个成员带有分数,用于进行排序。Redis有序集合添加、删除和测试的时间复杂度均为O(1)(固定时间,无论里面包含的元素集合的数量)。列表的最大长度为2^32- 1元素(4294967295,超过40亿每个元素的集合)。Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。使用场景Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。又比如用户的积分排行榜需求就可以通过有序集合实现。还有上面介绍的使用List实现轻量级的消息队列,其实也可以通过Sorted Set实现有优先级或按权重的队列。相关命令ZADDZADD key score1 member1 [score2 member2] 添加一个或多个成员到有序集合,或者如果它已经存在更新其分数ZCARDZCARD key 得到的有序集合成员的数量ZCOUNTZCOUNT key min max 计算一个有序集合成员与给定值范围内的分数ZINCRBYZINCRBY key increment member 在有序集合增加成员的分数ZINTERSTOREZINTERSTORE destination numkeys key [key ...] 多重交叉排序集合,并存储生成一个新的键有序集合。ZLEXCOUNTZLEXCOUNT key min max 计算一个给定的字典范围之间的有序集合成员的数量ZRANGEZRANGE key start stop [WITHSCORES] 由索引返回一个成员范围的有序集合(从低到高)ZRANGEBYLEXZRANGEBYLEX key min max [LIMIT offset count]返回一个成员范围的有序集合(由字典范围)ZRANGEBYSCOREZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 返回有序集key中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员,有序集成员按 score 值递增(从小到大)次序排列ZRANKZRANK key member 确定成员的索引中有序集合ZREMZREM key member [member ...] 从有序集合中删除一个或多个成员,不存在的成员将被忽略ZREMRANGEBYLEXZREMRANGEBYLEX key min max 删除所有成员在给定的字典范围之间的有序集合ZREMRANGEBYRANKZREMRANGEBYRANK key start stop 在给定的索引之内删除所有成员的有序集合ZREMRANGEBYSCOREZREMRANGEBYSCORE key min max 在给定的分数之内删除所有成员的有序集合ZREVRANGEZREVRANGE key start stop [WITHSCORES] 返回一个成员范围的有序集合,通过索引,以分数排序,从高分到低分ZREVRANGEBYSCOREZREVRANGEBYSCORE key max min [WITHSCORES] 返回一个成员范围的有序集合,以socre排序从高到低ZREVRANKZREVRANK key member 确定一个有序集合成员的索引,以分数排序,从高分到低分ZSCOREZSCORE key member 获取给定成员相关联的分数在一个有序集合ZUNIONSTOREZUNIONSTORE destination numkeys key [key ...] 添加多个集排序,所得排序集合存储在一个新的键ZSCANZSCAN key cursor [MATCH pattern] [COUNT count] 增量迭代排序元素集和相关的分数使用示例redis 127.0.0.1:6379> zadd dbs 100 redis (integer) 1 redis 127.0.0.1:6379> zadd dbs 98 memcached (integer) 1 redis 127.0.0.1:6379> zadd dbs 99 mongodb (integer) 1 redis 127.0.0.1:6379> zadd dbs 99 leveldb (integer) 1 redis 127.0.0.1:6379> zcard dbs (integer) 4 redis 127.0.0.1:6379> zcount dbs 10 99 (integer) 3 redis 127.0.0.1:6379> zrank dbs leveldb (integer) 1 redis 127.0.0.1:6379> zrank dbs other (nil) redis 127.0.0.1:6379> zrangebyscore dbs 98 100 1) "memcached" 2) "leveldb" 3) "mongodb" 4) "redis"
1、安装下载直接下官方正版的就好了eclipse->help->eclipse marketplace 搜索JRebel然后按步骤一步步安好安装好记得重启2、注册这东西在搞活动好像是,可以直接免费买一个,好像还没时间限制,攻略:http://jingyan.baidu.com/article/647f01159d32e77f2048a85d.html3、配置先到JRebel Configuration中把你的Tomcat勾上,顺便去隔壁的projects中勾上你的项目打开Tomcat的overview然后点击open launch configuration在Arguments中配置以下内容-noverify-javaagent:你的eclipse路径\plugins\org.zeroturnaround.eclipse.embedder_7.0.14.RELEASE\jrebel\jrebel.jar(可能是别的版本)-Drebel.dirs= 你需要部署的项目实际路径(可以先不急着配这个)-Drebel.spring_plugin=true 使用spring插件时设为true-Drebel.struts2-plugin=true 使用struts2插件时设为true同时到tomcat的Moudles中点击Edit点掉这个按钮,使你的项目不会被tomcat本身热部署先在你的项目上右击然后到JRebel->add JRebel Nature然后在你的项目根目录会生出一个Rebel.xml这里面的俩配置分别是你的项目编译文件的存储路径和你的网站根路径在开启Tomcat的时候只要网站根路径的东西被重新编译,JRebel就会启动,进行热部署之后开启tomcat,会有JRebel的一些提示,如果服务器成功启动(出熟悉的8080了)JRebel就配置成功了三个小地方需要注意:1、web目录的路径问题,rebel.xml中web的路径必须和以下这个路径一致,因为JRebel只会监听自己配置的目录,只有这两者一致,在你保存文件的时候JRebel才会发现,并进行热部署2、中文路径问题包括JRebel的路径,项目路径,web服务器的路径,都不要使用中文,不然这个参数进不去(在rebel.xml中或者在Argurments中配都是一样的,不能有中文路径)被这个问题折磨了一下午3、重载时间问题这个地方调整重载的时间(也就是你项目变更后,JRebel要等待多少秒再去热加载项目)默认很长自己适当调整稍微留一点可以减少一些不必要的重载大概就这些
#nginx进程,一般设置为和cpu核数一样worker_processes 4; #错误日志存放目录error_log /data1/logs/error.log crit; #运行用户,默认即是nginx,可不设置user nginx #进程pid存放位置pid /application/nginx/nginx.pid; #Specifies the value for maximum file descriptors that can be opened by this process.#最大文件打开数(连接),可设置为系统优化后的ulimit -HSn的结果worker_rlimit_nofile 51200;cpu亲和力配置,让不同的进程使用不同的cpuworker_cpu_affinity 0001 0010 0100 1000 0001 00100100 1000;#工作模式及连接数上限events{ use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能 worker_connections 1024; #;单个后台worker process进程的最大并发链接数}###################################################http{include mime.types; #文件扩展名与类型映射表default_type application/octet-stream; #默认文件类型#limit模块,可防范一定量的DDOS攻击#用来存储session会话的状态,如下是为session分配一个名为one的10M的内存存储区,限制了每秒只接受一个ip的一次请求 1r/s limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; limit_conn_zone $binary_remote_addr zone=addr:10m; include mime.types; default_type application/octet-stream;#第三方模块lua防火墙 lua_need_request_body on; #lua_shared_dict limit 50m; lua_package_path "/application/nginx/conf/waf/?.lua"; init_by_lua_file "/application/nginx/conf/waf/init.lua"; access_by_lua_file "/application/nginx/conf/waf/access.lua"; #设定请求缓存 server_names_hash_bucket_size 128; client_header_buffer_size 512k; large_client_header_buffers 4 512k; client_max_body_size 100m; #隐藏响应header和错误通知中的版本号 server_tokens off; #开启高效传输模式 sendfile on; #激活tcp_nopush参数可以允许把httpresponse header和文件的开始放在一个文件里发布, 积极的作用是减少网络报文段的数量 tcp_nopush on; #激活tcp_nodelay,内核会等待将更多的字节组成一个数据包,从而提高I/O性能 tcp_nodelay on;tcp_nopush官方:tcp_nopushSyntax: tcp_nopush on | offDefault: offContext: httpserverlocationReference: tcp_nopushThis directive permits or forbids the use of thesocket options TCP_NOPUSH on FreeBSD or TCP_CORK on Linux. This option is onlyavailable when using sendfile.Setting this option causes nginx to attempt to sendit’s HTTP response headers in one packet on Linux and FreeBSD 4.xYou can read more about the TCP_NOPUSH and TCP_CORKsocket options here.linux 下是tcp_cork,上面的意思就是说,当使用sendfile函数时,tcp_nopush才起作用,它和指令tcp_nodelay是互斥的。tcp_cork是linux下tcp/ip传输的一个标准了,这个标准的大概的意思是,一般情况下,在tcp交互的过程中,当应用程序接收到数据包后马上传送出去,不等待,而tcp_cork选项是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞,已经是默认了。也就是说tcp_nopush = on 会设置调用tcp_cork方法,这个也是默认的,结果就是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞。以快递投递举例说明一下(以下是我的理解,也许是不正确的),当快递东西时,快递员收到一个包裹,马上投递,这样保证了即时性,但是会耗费大量的人力物力,在网络上表现就是会引起网络堵塞,而当快递收到一个包裹,把包裹放到集散地,等一定数量后统一投递,这样就是tcp_cork的选项干的事情,这样的话,会最大化的利用网络资源,虽然有一点点延迟。对于nginx配置文件中的tcp_nopush,默认就是tcp_nopush,不需要特别指定,这个选项对于www,ftp等大文件很有帮助View Codetcp_nodelayTCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。 John Nagle是Nagle算法的发明人,后者就是用他的名字来命名的,他在1984年首次用这种方法来尝试解决福特汽车公司的网络拥塞问题(欲了解详情请参看IETF RFC 896)。他解决的问题就是所谓的silly window syndrome,中文称“愚蠢窗口症候群”,具体含义是,因为普遍终端应用程序每产生一次击键操作就会发送一个包,而典型情况下一个包会拥有一个字节的数据载荷以及40个字节长的包头,于是产生4000%的过载,很轻易地就能令网络发生拥塞,。 Nagle化后来成了一种标准并且立即在因特网上得以实现。它现在已经成为缺省配置了,但在我们看来,有些场合下把这一选项关掉也是合乎需要的。 现在让我们假设某个应用程序发出了一个请求,希望发送小块数据。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。如果我们马上发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的TCP_NODELAY = on 选项来完成,这样就禁用了Nagle 算法。 另外一种情况则需要我们等到数据量达到最大时才通过网络一次发送全部数据,这种数据传输方式有益于大量数据的通信性能,典型的应用就是文件服务器。应用 Nagle算法在这种情况下就会产生问题。但是,如果你正在发送大量数据,你可以设置TCP_CORK选项禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK和 TCP_NODELAY是互相排斥的)。</span></pre> View Code------------------------------------------------------------------------------------- #FastCGI相关参数:为了改善网站性能:减少资源占用,提高访问速度mfastcgi_connect_timeout 300;fastcgi_send_timeout 300;fastcgi_read_timeout 300;fastcgi_buffer_size 64k;fastcgi_buffers 4 64k;fastcgi_busy_buffers_size 128k;fastcgi_temp_file_write_size 128k;#连接超时时间,单位是秒 keepalive_timeout 60; #开启gzip压缩功能 gzip on; #设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取。默认值是0,表示不管页面多大都进行压缩。建议设置成大于1K。如果小于1K可能会越压越大。 gzip_min_length 1k;#压缩缓冲区大小。表示申请4个单位为16K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。 gzip_buffers 4 16k;#压缩版本(默认1.1,前端为squid2.5时使用1.0)用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可。 gzip_http_version 1.0;#压缩比率。用来指定GZIP压缩比,1压缩比最小,处理速度最快;9压缩比最大,传输速度快,但处理最慢,也比较消耗cpu资源。 gzip_comp_level 9;#用来指定压缩的类型,“text/html”类型总是会被压缩 gzip_types text/plain application/x-javascript text/css application/xml; #vary header支持。该选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用Squid缓存经过Nginx压缩的数据。gzip_vary off;#开启ssi支持,默认是off ssi on; ssi_silent_errors on;#设置日志模式 log_format access '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for';#反向代理负载均衡设定部分#upstream表示负载服务器池,定义名字为backend_server的服务器池upstream backend_server { server 10.254.244.20:81 weight=1 max_fails=2 fail_timeout=30s; server 10.254.242.40:81 weight=1 max_fails=2 fail_timeout=30s; server 10.254.245.19:81 weight=1 max_fails=2 fail_timeout=30s; server 10.254.243.39:81 weight=1 max_fails=2 fail_timeout=30s; #设置由 fail_timeout 定义的时间段内连接该主机的失败次数,以此来断定 fail_timeout 定义的时间段内该主机是否可用。默认情况下这个数值设置为 1。零值的话禁用这个数量的尝试。设置在指定时间内连接到主机的失败次数,超过该次数该主机被认为不可用。#这里是在30s内尝试2次失败即认为主机不可用! }####################基于域名的虚拟主机 server {#监听端口 listen 80; server_name www.abc.com abc.com; index index.html index.htm index.php; #首页排序 root /data0/abc; #站点根目录,即网站程序存放目录 error_page 500 502 404 /templates/kumi/phpcms/404.html; #错误页面#伪静态 将www.abc.com/list....html的文件转发到index.php。。。#rewrite ^/list-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /index.php?m=content&c=index&a=lists&catid=$1&types=$2&country=$3&language=$4&age=$5&startDate=$6&typeLetter=$7&type=$8&page=$9 last;#location 标签,根目录下的.svn目录禁止访问 location ~ /.svn/ { deny all; } location ~ \.php$ { #符合php扩展名的请求调度到fcgi server fastcgi_pass 127.0.0.1:9000; #抛给本机的9000端口 fastcgi_index index.php; #设定动态首页 include fcgi.conf; } allow 219.237.222.30 ; #允许访问的ip allow 219.237.222.31 ; allow 219.237.222.32 ; allow 219.237.222.33 ; allow 219.237.222.34 ; allow 219.237.222.35 ; allow 219.237.222.61 ; allow 219.237.222.28 ; deny all; #禁止其他ip访问 } location ~ ^/admin.php { location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; } allow 219.237.222.30 ; allow 219.237.222.31 ; allow 219.237.222.32 ; allow 219.237.222.33 ; allow 219.237.222.34 ; allow 219.237.222.35 ; allow 219.237.222.61; allow 219.237.222.28; deny all; }#将符合js,css文件的等设定expries缓存参数,要求浏览器缓存。location~ .*\.(js|css)?$ { expires 30d; #客户端缓存上述js,css数据30天 }##add by 20140321#######nginx防sql注入#############start####if ( $query_string ~* ".*[\;'\<\>].*" ){ return 444; }if ($query_string ~* ".*(insert|select|delete|update|count|\*|%|master|truncate|declare|\'|\;|and|or||||exec).* ") { return 444; }if ($request_uri ~* "(cost)|(concat\()")return444;if($requesturi ∗"[+|()|(concat\()")return444;if($requesturi ∗"[+|(") {set $block_common_exploits 1;}if ($block_common_exploits = 1) {return 444;}set $block_spam 0;if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") {set $block_spam 1;}if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") {set $block_spam 1;}if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") {set $block_spam 1;}if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") {set $block_spam 1;}if ($block_spam = 1) {return 444;}set $block_user_agents 0;if ($http_user_agent ~ "Wget") { set $block_user_agents 1;}# Disable Akeeba Remote Control 2.5 and earlierif ($http_user_agent ~ "Indy Library") {set $block_user_agents 1;}# Common bandwidth hoggers and hacking tools.if ($http_user_agent ~ "libwww-perl") {set $block_user_agents 1;}if ($http_user_agent ~ "GetRight") {set $block_user_agents 1;}if ($http_user_agent ~ "GetWeb!") {set $block_user_agents 1;}if ($http_user_agent ~ "Go!Zilla") {set $block_user_agents 1;}if ($http_user_agent ~ "Download Demon") {set $block_user_agents 1;}if ($http_user_agent ~ "Go-Ahead-Got-It") {set $block_user_agents 1;}if ($http_user_agent ~ "TurnitinBot") {set $block_user_agents 1;}if ($http_user_agent ~ "GrabNet") {set $block_user_agents 1;}if ($block_user_agents = 1) {return 444;}###end#### location ~ ^/list { #如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。 proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_cache cache_one; #对不同的HTTP状态码设置不同的缓存时间 proxy_cache_valid 200 301 302 304 1d; #proxy_cache_valid any 1d; #以域名、URI、参数组合成Web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内 proxy_cache_key $host$uri$is_args$args; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie"; #proxy_ignore_headers Set-Cookie; #proxy_hide_header Set-Cookie; proxy_pass http://backend_server; add_header Nginx-Cache "$upstream_cache_status from km"; expires 1d; } access_log /data1/logs/abc.com.log access; #nginx访问日志 }-----------------------ssl(https)相关------------------------------------server { listen 13820; #监听端口 server_name localhost; charset utf-8; #gbk,utf-8,gb2312,gb18030 可以实现多种编码识别 ssl on; #开启ssl ssl_certificate /ls/app/nginx/conf/mgmtxiangqiankeys/server.crt; #服务的证书 ssl_certificate_key /ls/app/nginx/conf/mgmtxiangqiankeys/server.key; #服务端key ssl_client_certificate /ls/app/nginx/conf/mgmtxiangqiankeys/ca.crt; #客户端证书 ssl_session_timeout 5m; #session超时时间 ssl_verify_client on; # 开户客户端证书验证 ssl_protocols SSLv2 SSLv3 TLSv1; #允许SSL协议 ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; #加密算法 ssl_prefer_server_ciphers on; #启动加密算法 access_log /lw/logs/nginx/dataadmin.test.com.ssl.access.log access ; #日志格式及日志存放路径 error_log /lw/logs/nginx/dataadmin.test.com.ssl.error.log; #错误日志存放路径}
思路:1、根据提问或者需求分析想要的结果是什么Select XXXXX2、确定想要得到XXXXX的话需要涉及到哪些表Select XXX from YYYY3、分析是否需要条件 where > ,< ,= ,<> , >=, <=,in,between,and,orSelect XXX from YYY where ZZZZ4、是否需要函数时间函数,数学函数5、分组看到(“每个??”)一般情况下都需要group by.6、如果想要的结果不能一步到位需要多个步骤的,那么此时我们使用的就是子查询,子查询我们可以按照单个步骤进行查询,然后把多个步骤组装起来7、表连接,关联查询,联合查询。明显特征:结果集中的列涉及到多张表。表连接去除笛卡尔积中的错误数据1.需求2.表格3.条件4.函数5.分组6.步骤7.关联问题:1.创建student和score表2.为student表和score表增加记录3.查询student表的所有记录4.查询student表的第2条到4条记录5.从student表查询所有学生的学号(id)、姓名(name)和院系(department)的信息6.从student表中查询计算机系和英语系的学生的信息7.从student表中查询年龄18~35岁的学生信息8.查询每个院系有多少人9.查询每个科目的最高分10.查询李四的考试科目(c_name)和考试成绩(grade)11.所有学生的信息和考试信息12.计算每个学生的总成绩13.计算每个考试科目的平均成绩14.查询计算机成绩低于95的学生信息15.查询同时参加计算机和英语考试的学生的信息16.将计算机考试成绩按从高到低进行排序17.查询姓张或者姓王的同学的姓名、院系和考试科目及成绩18.查询都是湖南的学生的姓名、年龄、院系和考试科目及成绩Mysql练习 (select)------学生资料与成绩查询1.创建student和score表DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` char(20) NOT NULL, `sex` char(20) DEFAULT NULL, `birth` year(4) DEFAULT NULL, `department` char(10) DEFAULT NULL, `address` char(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;创建score表。SQL代码如下:DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` int(10) NOT NULL AUTO_INCREMENT, `stu_id` int(10) NOT NULL, `c_name` char(20) DEFAULT NULL, `grade` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `score_ibfk_1` (`stu_id`), CONSTRAINT `score_ibfk_1` FOREIGN KEY (`stu_id`) REFERENCES `student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;2.为student表和score表增加记录向student表插入记录的INSERT语句如下:insert into `student`(`id`,`name`,`sex`,`birth`,`department`,`address`) values (1,'张老大','男',1985,'计算机系','北京市海淀区'); insert into `student`(`id`,`name`,`sex`,`birth`,`department`,`address`) values (2,'张老二','男',1986,'中文系','北京市昌平区'); insert into `student`(`id`,`name`,`sex`,`birth`,`department`,`address`) values (3,'张三','女',1990,'中文系','湖南省永州市'); insert into `student`(`id`,`name`,`sex`,`birth`,`department`,`address`) values (4,'李四','男',1990,'英语系','辽宁省阜新市'); insert into `student`(`id`,`name`,`sex`,`birth`,`department`,`address`) values (5,'王五','女',1991,'英语系','福建省厦门市'); insert into `student`(`id`,`name`,`sex`,`birth`,`department`,`address`) values (6,'王六','男',1988,'计算机系','湖南省衡阳市');向score表插入记录的INSERT语句如下:insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (1,1,'计算机',98); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (2,1,'英语',80); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (3,2,'计算机',65); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (4,2,'中文',88); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (5,3,'中文',95); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (6,3,'计算机',70); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (7,4,'计算机',70); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (8,4,'英语',92); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (9,5,'英语',94); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (10,5,'计算机',90); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (11,6,'计算机',90); insert into `score`(`id`,`stu_id`,`c_name`,`grade`) values (12,6,'英语',85);3.查询student表的所有记录SELECT * FROM student;4.查询student表的第2条到4条记录SELECT * FROM student LIMIT 1,3;5.从student表查询所有学生的学号(id)、姓名(name)和院系(department)的信息SELECT id,NAME,department FROM student;6.从student表中查询计算机系和英语系的学生的信息SELECT * FROM student WHERE department IN('计算机系','英语系');7.从student表中查询年龄在18~35岁的学生信息SELECT * FROM student WHERE YEAR(NOW())-birth BETWEEN 18 AND 35;8.查询每个院系有多少人SELECT department,COUNT(department) counts FROM student GROUP BY department;9.查询每个科目的最高分SELECT c_name,MAX(grade) maxgrade FROM score GROUP BY c_name;10.查询李四的考试科目(c_name)和考试成绩(grade)SELECT c_name,grade FROM score WHERE stu_id =(SELECT id FROM student WHERE NAME='李四');11.所有学生的信息和考试信息SELECT * FROM student s,score sc WHERE s.`id`=sc.`stu_id`; SELECT s.`id`,NAME,sex,birth,department,address,grade FROM student s,score sc WHERE s.`id`=sc.`s12.计算每个学生的总成绩SELECT NAME,SUM(grade) FROM student s,score sc WHERE s.`id`=sc.`stu_id` GROUP BY NAME;13.计算每个考试科目的平均成绩计算每个学生的平均成绩???SELECT c_name,AVG(grade) FROM score GROUP BY c_name;14.查询计算机成绩低于95的学生信息SELECT * FROM student WHERE id IN(SELECT stu_id FROM score WHERE c_name='计算机' AND grade<15.查询每个学科的平均成绩SELECT c_name,AVG(grade) FROM score GROUP BY c_name;16.将计算机考试成绩降序排列SELECT c_name,grade FROM score WHERE c_name='计算机' ORDER BY grade DESC;17.查询姓张或者姓王的同学的姓名、院系和考试科目及成绩SELECT NAME,department,c_name,grade FROM student s,score sc WHERE s.`id`=sc.stu_id AND N18.查询都是湖南的学生的姓名、年龄、院系和考试科目及成绩SELECT NAME,address,YEAR(NOW())-birth,department,c_name,grade FROM student INNER JOIN sc19.查询出每门课程都大于80分的学生姓名类似于这个题目:查询所有成绩都及格的学生SELECT st.`name`,MIN(s.grade) mi FROM student st LEFT JOIN score s ON s.`stu_id`=st.`id` GROUP BY st.`name` HAVING mi>80;20.查询平均分最高的科目名字SELECT c_name,MAX(avgs.av) FROM (SELECT AVG(grade) AS av,c_name FROM score GROUP BY c_name) AS avgs21.查询语文成绩比张三高的学生的信息提示:先查询张三的语文成绩;再查询语文成绩成绩大于a的学生信息;SELECT * FROM student st LEFT JOIN score s ON s.`stu_id`=st.`id` WHERE s.c_name="中文" AND s.grade > (SELECT s.grade FROM student st LEFT JOIN score s ON s.`stu_id`=st.`id` WHERE s.c_name="中文" AND st.name="张三")22.查询同时参加计算机和英语考试的学生的信息SELECT * FROM student WHERE id IN ( SELECT stu_id FROM score WHERE c_name='计算机' AND stu_id IN ( SELECT stu_id FROM score WHERE c_name ='英语' ))23.有如下三个表:DROP TABLE IF EXISTS `project`; CREATE TABLE `project` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `contract`; CREATE TABLE `contract` ( `id` int(11) NOT NULL AUTO_INCREMENT, `project_id` int(5) DEFAULT NULL, `money` int(5) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `pay`; CREATE TABLE `pay` ( `id` int(5) NOT NULL AUTO_INCREMENT, `contract_id` int(5) DEFAULT NULL, `money` int(5) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;插入数据:insert into `project`(`id`,`name`) values (1,'Java'),(2,'C语言'); insert into `contract`(`id`,`project_id`,`money`) values (1,1,10),(2,1,10),(3,2,10),(4,2,10); insert into `pay`(`id`,`contract_id`,`money`) values (1,1,10),(2,1,10),(3,2,10),(4,2,10),(5,3,10),(6,3,10),(7,4,10),(8,4,10);一个项目有多个合同,每个合同会分几次付款;1.查询各个项目的合同总金额SELECT p.name,SUM(c.money) FROM project p LEFT JOIN contract c ON p.id =c.project_id GROUP BY p.name2.查询id为1的项目所有已经付款的记录SELECT c.id contract_id,p.id pay_id,p.money FROM contract c, pay p WHERE c.id = p.contract_id AND c.project_id =1或者:SELECT p.id project_id,c.id contract_id,py.id pay_id,py.money FROM project p LEFT JOIN contract c LEFT JOIN pay py ON c.id=py.contract_id ON p.id =c.project_id WHERE p.id=13.查询所有已经有付款记录的合同及对应的项目SELECT * FROM project p, contract c WHERE c.project_id = p.id AND c.id IN (SELECT contract_id FROM pay)
2023年02月