diff --git "a/notes/github\345\234\250\347\272\277\347\211\210.txt" "b/notes/github\345\234\250\347\272\277\347\211\210.txt" new file mode 100644 index 0000000..61a74f8 --- /dev/null +++ "b/notes/github\345\234\250\347\272\277\347\211\210.txt" @@ -0,0 +1 @@ +https://github.com/coding-technology/JavaCore.git \ No newline at end of file diff --git a/notes/netty/netty.assets/1596880013533.png b/notes/netty/netty.assets/1596880013533.png new file mode 100644 index 0000000..5e7a913 Binary files /dev/null and b/notes/netty/netty.assets/1596880013533.png differ diff --git a/notes/netty/netty.assets/1596880060937.png b/notes/netty/netty.assets/1596880060937.png new file mode 100644 index 0000000..1e9ad9d Binary files /dev/null and b/notes/netty/netty.assets/1596880060937.png differ diff --git a/notes/netty/netty.assets/1597652263171.png b/notes/netty/netty.assets/1597652263171.png new file mode 100644 index 0000000..28a3ca1 Binary files /dev/null and b/notes/netty/netty.assets/1597652263171.png differ diff --git a/notes/netty/netty.assets/1598257901806.png b/notes/netty/netty.assets/1598257901806.png new file mode 100644 index 0000000..08b1d82 Binary files /dev/null and b/notes/netty/netty.assets/1598257901806.png differ diff --git a/notes/netty/netty.assets/1598860295543.png b/notes/netty/netty.assets/1598860295543.png new file mode 100644 index 0000000..444917b Binary files /dev/null and b/notes/netty/netty.assets/1598860295543.png differ diff --git a/notes/netty/netty.assets/1598860500419.png b/notes/netty/netty.assets/1598860500419.png new file mode 100644 index 0000000..7e2066a Binary files /dev/null and b/notes/netty/netty.assets/1598860500419.png differ diff --git a/notes/netty/netty.assets/1598860966092.png b/notes/netty/netty.assets/1598860966092.png new file mode 100644 index 0000000..4438d1d Binary files /dev/null and b/notes/netty/netty.assets/1598860966092.png differ diff --git a/notes/netty/netty.assets/1598863051468.png b/notes/netty/netty.assets/1598863051468.png new file mode 100644 index 0000000..ddcd18f Binary files /dev/null and b/notes/netty/netty.assets/1598863051468.png differ diff --git a/notes/netty/netty.assets/1599466437487.png b/notes/netty/netty.assets/1599466437487.png new file mode 100644 index 0000000..f63f46a Binary files /dev/null and b/notes/netty/netty.assets/1599466437487.png differ diff --git a/notes/netty/netty.assets/1599467032397.png b/notes/netty/netty.assets/1599467032397.png new file mode 100644 index 0000000..e3d35c3 Binary files /dev/null and b/notes/netty/netty.assets/1599467032397.png differ diff --git a/notes/netty/netty.assets/1599469946932.png b/notes/netty/netty.assets/1599469946932.png new file mode 100644 index 0000000..f5d1322 Binary files /dev/null and b/notes/netty/netty.assets/1599469946932.png differ diff --git a/notes/netty/netty.md b/notes/netty/netty.md new file mode 100644 index 0000000..bce9f70 --- /dev/null +++ b/notes/netty/netty.md @@ -0,0 +1,926 @@ +# netty + +前置课程:NIO + +重要性: + +hadoop spark dubbo 等众多知名的框架,阿里巴巴、facebook、twtitter等知名公司都使用到了netty作为底层框架。 + +稳定性:netty4.x + +netty.io + +jboss公司的项目 + +核心:netty是一个异步的、基于事件驱动模式的网络应用框架。 + + + +## 搭建netty开发环境 + +1.安装Jdk + +2.下载安装gradle + +(1)下载gradle-5.3-all.zip + +(2)环境变量: GRADLE_HOME :上一步gradle解压后的根目录 + +(3)PATH: %GRADLE_HOME%\bin + +(4)curl: 下载windows版curl,只需要将curl.exe所在目录配置到path中即可。 + +3.创建netty工程 + +4.增加netty依赖 + +build.gradle + +```xml +plugins { + id 'java' +} + +group 'com.yanqun' +version '1.0-SNAPSHOT' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { +// mavenCentral() + maven{ url 'http://maven.aliyun.com/nexus/content/groups/public'} +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' + compile group: 'io.netty', name: 'netty-all', version: '4.1.50.Final' +} + +``` + +## 第一个netty的hello world + +模板化代码:类似JDBC + +具体的模板流程(以服务端为例) + + - 入口类/主程序类 + + - 配置一些参数 + + - 内置初始化器(处理器) + + - 调用一些内置的类 + + - 自定义初始化器(处理器) + + - 编写一些自定义的类 + +netty强大的核心: + +​ netty内部提供了非常强大的类库(内置初始化器),每个初始化器都可以完成一个 小的功能。因此,以后在开发时,我们第一步需要先将 需要完成的功能 分解成若干部;第二步 只需要在netty类库中寻找,看哪些已有类能够帮助我们直接实现; 第三步,如果某个功能netty没有提供,则编写自定义初始化器 + +总结: 分解功能 ->在类库中找 ->如果还些找不到,自定义编写 + + + +实现: + +第一步:入口类 + +```java +package helloworld; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/* + * Created by 颜群 + */ +public class NettyServerTest {//入口类 + + public static void main(String[] args) { + + //创建事件循环组 (master -slaver) + EventLoopGroup bossGroup = new NioEventLoopGroup() ;//接收客户端连接,并分发给workerGroup + EventLoopGroup workerGroup = new NioEventLoopGroup() ;//真正的处理连接 + //启动 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + try { + ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) + + //综合(内置+自定义)初始化器 + .childHandler(new NettyServerInit()) + + .bind(8888) + .sync(); + channelFuture.channel().closeFuture().sync() ; + } catch (InterruptedException e) { + e.printStackTrace(); + }finally{ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully() ; + } + + } + +} + +``` + +第二步:编写综合初始化器(内置+自定义的) + +```java +package helloworld; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObject; +import io.netty.handler.codec.http.HttpServerCodec; + +/* + * Created by 颜群 + */ +//综合(内置+自定义)初始化器 +public class NettyServerInit extends ChannelInitializer { + //当连接注册到channel时,执行此方法 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + //内置初始化器 (编码初始化器:HttpServerCodec) + pipeline.addLast( "HttpServerCodec",new HttpServerCodec() ) ; + + //自定义初始化器(NettyServerHandler) + pipeline.addLast("NettyServerHandler",new NettyServerHandler()); + } +} + +``` + +第三步:编写自定义初始化器 + +```java +package helloworld; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; + +/* + * Created by 颜群 + */ +public class NettyServerHandler extends SimpleChannelInboundHandler { + //doGet doPost + @Override + protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { + if(msg instanceof HttpRequest){ + //定义响应内容 + ByteBuf content = Unpooled.copiedBuffer("welcome netty family...", CharsetUtil.UTF_8); + //封装响应对象 + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); + response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain") ; + response.headers().set(HttpHeaderNames.CONTENT_LENGTH , content.readableBytes() ) ;//不是content.readByte() + + ctx.writeAndFlush(response) ; + + } + } +} + +``` + +流程 + +![1596880013533](netty.assets/1596880013533.png) + +​ + +![1596880060937](netty.assets/1596880060937.png) + + + +步骤: + +​ Test -Init + Handler + +说明:浏览器在发起请求时,会默认请求图标favicon.ico文件,因此会比curl多发出一次请求。 + + + +分析: + +自定义处理器依次继承: + +SimpleChannelInboundHandler->ChannelInboundHandlerAdapter->ChannelInboundHandler->ChannelHandler + +另一条继承链:ChannelHandler<- ChannelOutboundHandler + +![1597652263171](netty.assets/1597652263171.png) + +继承链中的各个方法 + +netty遵循了事件回调机制:类似于ajax/javascript/html:在不同的阶段,会自动的执行一些方法,生命周期方法。 + + + +通过curl请求netty服务端,多次的请求结果是一致的 + + + +2次请求: + +正常请求内容:浏览器会保存请求状态。 + +​ 初始化和销毁工作只执行一次(Http1.1,Keep-alive持续连接机制,第一次访问结束后 并不会立刻关闭连接) + +请求favicon.ico: + + - 第二次请求时,会结束上次一对favicon.ico的请求。 + - 每次请求 都是一个完整的回路 + + + +## 案例:点对点聊天 + +![1598257901806](netty.assets/1598257901806.png) + + + +服务端 + +1.入口类 + +```.java +package dot2dot; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/* + * Created by 颜群 + * 入口类->初始化器 ->自定义处理器 + */ +public class MyNettyServerTest { + + public static void main(String[] args) { + + //创建事件循环组 (master -slaver) + EventLoopGroup bossGroup = new NioEventLoopGroup() ;//接收客户端连接,并分发给workerGroup + EventLoopGroup workerGroup = new NioEventLoopGroup() ;//真正的处理连接 + //启动 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + try { + ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + + //综合(内置+自定义)初始化器 + .childHandler(new MyNettyServerInit()) + + .bind(8888) + .sync(); + channelFuture.channel().closeFuture().sync() ; + } catch (InterruptedException e) { + e.printStackTrace(); + }finally{ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully() ; + } + + } + +} + +``` + +2.初始化器 + +```java +package dot2dot; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.util.CharsetUtil; + +/* + * Created by 颜群 + * + * netty自带类库解决 + */ +public class MyNettyServerInit extends ChannelInitializer { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + + //合并、解码 + + ChannelPipeline pipeline = ch.pipeline(); + //解码 + pipeline.addLast("LengthFieldBasedFrameDecoder",new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,8,0,8 )) ; + //合并 + pipeline.addLast("LengthFieldPrepender", new LengthFieldPrepender(8)) ; + + //统一乱码 + pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8)); + pipeline.addLast("StringEncoder",new StringEncoder(CharsetUtil.UTF_8)); + + pipeline.addLast("MyNettyServerHandler",new MyNettyServerHandler()) ; + + + } +} + +``` + +3.自定义处理器 + +```java +package dot2dot; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.util.Scanner; + +/* + * Created by 颜群 + * 自定义功能:聊天 + */ +public class MyNettyServerHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { + //接收消息 + System.out.println("服务端 接收到了"+ctx.channel().remoteAddress()+",消息是:"+msg); + + //发送消息 + System.out.println("请输入内容:"); + String send = new Scanner(System.in).nextLine() ; + ctx.channel().writeAndFlush(send) ; + } +} + +``` + + + +客户端 + +1.入口类 + +```java +package dot2dot; + +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; + +/* + * Created by 颜群 + * 入口类->初始化器 ->自定义处理器 + */ +public class MyNettyClientTest { + + public static void main(String[] args) { + + //创建事件循环组 + EventLoopGroup eventLoopGroup = new NioEventLoopGroup() ; + + //启动 + Bootstrap bootstrap = new Bootstrap(); + try { + bootstrap.group(eventLoopGroup) + .channel(NioSocketChannel.class) + //综合(内置+自定义)初始化器 + .handler(new MyNettyClientInit()); + + ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8888).sync(); + channelFuture.channel().closeFuture().sync() ;//future模式 + + } catch (InterruptedException e) { + e.printStackTrace(); + }finally{ + eventLoopGroup.shutdownGracefully(); + } + + } + +} + +``` + + + +2.初始化器 + +```java +package dot2dot; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.util.CharsetUtil; + +/* + * Created by 颜群 + */ +public class MyNettyClientInit extends ChannelInitializer { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + + //合并、解码 + ChannelPipeline pipeline = ch.pipeline(); + //解码 + pipeline.addLast("LengthFieldBasedFrameDecoder",new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,8,0,8 )) ; + //合并 + pipeline.addLast("LengthFieldPrepender", new LengthFieldPrepender(8)) ; + + //统一乱码 + pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8)); + pipeline.addLast("StringEncoder",new StringEncoder(CharsetUtil.UTF_8)); + + pipeline.addLast("MyNettyClientHandler",new MyNettyClientHandler()) ; + + + + } +} + +``` + + + +3.自定义处理器 + +```java + package dot2dot; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.util.Scanner; + +/* + * Created by 颜群 + */ +public class MyNettyClientHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { + + //接收消息 + System.out.println("客户端 接收到了"+ctx.channel().remoteAddress()+",消息是:"+msg); + + //发送消息 + System.out.println("请输入内容:"); + String send = new Scanner(System.in).nextLine() ; + ctx.channel().writeAndFlush(send) ; + } + + //为了 避免 客户端和服务端 都在等待对方发送第一条消息,就需要 有人(客户端)主动发送第一条消息 + + + //当连接成功时,会触发channelActive()方法 + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush("开始聊天吧...") ; + } +} + +``` + +案例:点对多点/点对端/ 聊天室 + +Netty - NIO + +参照:**亿级流量Java高并发与网络编程实战** + +只看代码:扫码,在公众号回复“资料” + +![1598860966092](netty.assets/1598860966092.png) + +端口冲突的处理办法: + +查看端口冲突的PID: netstat -ano|findstr 8888 ,结果18484 + +结束进程taskkill /pid 18484 /f + + + +## 使用netty实现心跳机制 + +![1598860295543](netty.assets/1598860295543.png) + +在弱网环境中,事件驱动的机制 会失效。使用心跳机制解决。 + +![1598860500419](netty.assets/1598860500419.png) + +心跳机制:远端的双方,每隔一段时间 会1接收对方的消息 2给对方法消息;如果一方长时间 接收不到 对方的消息,就可以认为对方处于异常环境,此时就可以切断对方的连接 + +netty提供的心跳机制处理器:IdleStateHandler + +服务端代码 + +入口类 + +```java +package heartbeat; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/* + * Created by 颜群 + * 入口类->初始化器 ->自定义处理器 + */ +public class MyNettyServerTest { + + public static void main(String[] args) { + + //创建事件循环组 (master -slaver) + EventLoopGroup bossGroup = new NioEventLoopGroup() ;//接收客户端连接,并分发给workerGroup + EventLoopGroup workerGroup = new NioEventLoopGroup() ;//真正的处理连接 + //启动 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + try { + ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + + //综合(内置+自定义)初始化器 + .childHandler(new MyNettyServerInit()) + + .bind(8888) + .sync(); + channelFuture.channel().closeFuture().sync() ; + } catch (InterruptedException e) { + e.printStackTrace(); + }finally{ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully() ; + } + + } + +} + +``` + +初始化器 + +```java +package heartbeat; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.CharsetUtil; + +/* + * Created by 颜群 + * + */ +public class MyNettyServerInit extends ChannelInitializer { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + + + ChannelPipeline pipeline = ch.pipeline(); + //netty自带的处理器 + //三个参数:readerIdleTimeSeconds、writerIdleTimeSeconds、allIdleTimeSeconds + pipeline.addLast( "", new IdleStateHandler(30,5,7)); + //自定义处理器 + pipeline.addLast("MyNettyServerHandler",new MyNettyServerHandler()) ; + + + } +} + +``` + +自定义处理器 + +```java +package heartbeat; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.timeout.IdleStateEvent; + +import java.util.Scanner; + +/* + * Created by 颜群 + * 自定义功能:聊天 + */ +public class MyNettyServerHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { + //接收客户端 主动发来的消息 + } + + //可以用于处理心跳机制的方法 + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + //用于心跳机制的 数据类型 + if(evt instanceof IdleStateEvent){ + String eventType = null ; + IdleStateEvent event = (IdleStateEvent)evt ; + //获取具体的超时事件 + switch (event.state() ){ + case READER_IDLE: + eventType = "读空闲" ; + break ; + case WRITER_IDLE: + eventType = "写空闲" ; + break ; + case ALL_IDLE: + eventType = "读写空闲" ; + break ; + } + System.out.println( ctx.channel().remoteAddress() +"超时事件:【"+ eventType+"】"); + ctx.channel().close() ; + + } + } +} + +``` + +客户单通过curl模拟 + +![1598863051468](netty.assets/1598863051468.png) + +## 使用Netty实现websocket通信 + +传统的http请求: + +1.客户端发起请求,服务端接收并作出响应。每次请求,都是由客户端发起的,是**单向请求** + +2.物理层、数据链路层 、*网络层* 、传输层(TCP协议) 、会话层 、表示层 、应用层(http协议) + +TCP协议 连接是经过三次握手,关闭是经过四次握手。 + +每一次客户端向服务端发起请求,然后交互,都会经过三次握手 和四次握手。每次客户端与服务端通信,都必须 建立连接、通信、关闭连接 + + + +webscoket优点: + +1.支持客户端 和服务端的双向通信 (全双工通信) + +![1599466437487](netty.assets/1599466437487.png) + +2.支持长连接通信:第一次通信时需要建立连接,之后在一定时间内如果再次通信,则无需重新建立建立。 + +流程示意图 + +重点:客户端和服务端是等价的,二者的功能相同 + +![1599467032397](netty.assets/1599467032397.png) + +如何实现? + +入口类 - 初始化器 - 自定处理器 + +netty难在哪?难在积累 + +​ 看官方API文档 + +​ 看书籍《netty实战》等 + +初始化器 (使用Netty内置类)- 自定处理器(自己编码) + +一个功能:分解成5个小功能 = 3个netty自带的类 + 2个自定义类 + +netty端 + +```java +package ws.dot2dot; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/* + * Created by 颜群 + * 入口类->初始化器 ->自定义处理器 + */ +public class MyNettyServerTest { + + public static void main(String[] args) { + + //创建事件循环组 (master -slaver) + EventLoopGroup bossGroup = new NioEventLoopGroup() ;//接收客户端连接,并分发给workerGroup + EventLoopGroup workerGroup = new NioEventLoopGroup() ;//真正的处理连接 + //启动 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + try { + ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + + //综合(内置+自定义)初始化器 + .childHandler(new MyNettyServerInit()) + + .bind(8888) + .sync(); + channelFuture.channel().closeFuture().sync() ; + } catch (InterruptedException e) { + e.printStackTrace(); + }finally{ + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully() ; + } + + } + +} + +``` + + + +```java +package ws.dot2dot; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.codec.LengthFieldPrepender; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.util.CharsetUtil; + +/* + * Created by 颜群 + * + * netty自带类库解决 + */ +public class MyNettyServerInit extends ChannelInitializer { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + + //netty自带的类 + ChannelPipeline pipeline = ch.pipeline(); + //服务端解析器 + pipeline.addLast("HttpServerCodec", new HttpServerCodec()) ; + //组装工具类:可以将多个请求、响应进行组装的工具类 + pipeline.addLast("HttpObjectAggregator", new HttpObjectAggregator(4096)) ; + //localhost:8888/myWebsocket + pipeline.addLast("WebSocketServerProtocolHandler",new WebSocketServerProtocolHandler("/myWebsocket")); + + //自定义 + pipeline.addLast("MyNettyServerHandler",new MyNettyServerHandler()) ; + + + } +} + +``` + +自定义处理器 + +```java +package ws.dot2dot; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.Scanner; + +/* + * Created by 颜群 + * 自定义功能:聊天 + */ +public class MyNettyServerHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { + //接收消息 + System.out.println("server接收到的客户端消息:" + msg.text()); + //向客户端发出响应 + ctx.channel().writeAndFlush(new TextWebSocketFrame("hello client...")) ; + } + + + //监听是否有客户端链接上了 + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + System.out.println("有客户端连接上了:"+ctx.channel().id()); + } + + //监听是否有客户端断开了 + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + System.out.println("有客户端断开了:"+ctx.channel().id()); + } +} + +``` + + + +js端 + +```js + + + + + Title + + + + + + + +
+ + + +
+ + +
+ + +``` + + + +![1599469946932](netty.assets/1599469946932.png) + + + +三大步:难点 就在于 寻找一些 netty自带的工具类。 + +如果能找到: netty自带工具类 + 自定义类 + +如果找不到: 相当于 没用netty + +找到一部分: netty自带的一些工具类 + 自定义类 \ No newline at end of file diff --git "a/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1594024091872.png" "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1594024091872.png" new file mode 100644 index 0000000..ee2167c Binary files /dev/null and "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1594024091872.png" differ diff --git "a/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1594027935455.png" "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1594027935455.png" new file mode 100644 index 0000000..5a984b9 Binary files /dev/null and "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1594027935455.png" differ diff --git "a/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1595211856571.png" "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1595211856571.png" new file mode 100644 index 0000000..94839b4 Binary files /dev/null and "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.assets/1595211856571.png" differ diff --git "a/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.md" "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.md" index bc00238..d64df26 100644 --- "a/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.md" +++ "b/notes/\345\276\256\346\234\215\345\212\241/\345\276\256\346\234\215\345\212\241.md" @@ -826,51 +826,301 @@ public class JWTClient { System.out.println("payload:"+claims.getIssuedAt()); System.out.println("payload:"+claims.getExpiration()); System.out.println("payload:"+claims.getAudience()); - System.out.println("signature:"+jws.getSignature()); + System.out.println(jws.getSignature().equals(token.split("\\.")[2])); + } + + public static void main(String[] args) { + visitServer(); + } + +} +``` + Spring Boot整合jwt - System.out.println(jws.getSignature().equals(token.split("\\.")[2])); +为了让所有的功能模块 都能拥有 分布式校验功能(jwt),需要将这个校验功能 放到通用模块中。micro_commom: + +1.引入jwt依赖 + +```xml + + io.jsonwebtoken + jjwt + 0.9.1 + + + + org.springframework.boot + spring-boot-configuration-processor + true + +``` + +2.配置 + +```xml +省略 +``` + + + +3.编码 + +```java +package util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.Date; +/* + * Created by 颜群 + */ +@ConfigurationProperties("jwt.config") +public class JwtUtil { + private String key ; + private long ttl ; + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public long getTtl() { + return ttl; } - public static void main(String[] args) { - visitServer(); + public void setTtl(long ttl) { + this.ttl = ttl; + } + + //服务端生成jwt-token的方法 (JWTServer) + public String createJWT(String id, String subject,String roles){ + Date now = new Date() ; + long nowMillis = System.currentTimeMillis() ; + + return Jwts.builder().setId(id) + .setSubject(subject) + .setIssuedAt( now ) + .setExpiration( new Date( nowMillis + ttl ) ) + .signWith( SignatureAlgorithm.HS256, key ) + .claim("roles",roles).compact() ;//token } + + //客户单发送jwt-token时进行的校验方法 (JWTClient) + public Claims parseJWT(String token){ + return Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody() ; + } } + ``` +微服务的校验逻辑:第一登录时 获取token;以后再操作时,需要拿着token去访问。 +![1594024091872](微服务.assets/1594024091872.png) +登录工程: +micro_people +PeopleController.java +```java + //用户名:username + //密码:password + @PostMapping(value="/login") + public Message login(@RequestBody Map login){ + //controller -sercice -dao 模拟操作 + String uname = login.get("username") ; + String upwd = login.get("password") ; + //findUserByUsernameAndPassword + //zs/abc -> 返回这个人的全部信息 User(zs/abc,id(1001).....) + + System.out.println("1111"); + //假设数据库中的zs/abc (并且:假设这个人的id1001,这个人是管理员权限admin ) + if(uname.equals("zs") && upwd.equals("abc")){ + //登录成功,服务端生成token + //String id, String subject,String roles + String token = jwtUtil.createJWT("1001", "zs", "admin"); + + Map map = new HashMap() ; + map.put("token",token) ; + map.put("username",uname) ; + + System.out.println("登录成功"); + //登录成功:返回token\用户名 + return new Message(true,StatusCode.OK,map) ; + }else{ + System.out.println("登录失败"); + return new Message(false,StatusCode.ERROR) ; + } + } +``` + +xml + +``` +jwt: config: + key: yanqun + ttl: 1800 +``` + +![1594027935455](微服务.assets/1594027935455.png) + + + +sb方式的解析: + +客户端校验token - 服务端token + +客户端如何 携带 token去校验? 自定义请求头 Header +key-value +key: authentication +value: yanqun-token +在需要校验的操作上,增加jwt解析: + +```java + + @DeleteMapping("deleteById/{id}") + public Message deleteById( @PathVariable("id") Integer id){ + + //删除之前 先通过jwt进行权限校验 + /* + 已经存在生成jwt + + 现在:解析jwt + 1.客户端将jwt 传递给服务端 (postman模拟) + 2.解析jwt + */ + //假设此时,客户端postman已经将jwt(token)传递过来了 + String authentication = request.getHeader("authentication"); + if(authentication == null) {//请求时(postman)时,并没有携带jwt + return new Message(false,StatusCode.ERROR,"权限不足!") ; + } + + String token = authentication.substring(7);//从yanqun-token截取出token + Claims claims = jwtUtil.parseJWT(token); + String roles = (String)claims.get("roles"); + System.out.println(roles+"roles"); + if(!roles.equals("admin")){ + return new Message(false,StatusCode.ERROR,"权限不足!") ; + } + + + boolean result =cityService.deleteById(id) ; + return new Message(true, StatusCode.OK, result ); + } +``` + +![1595211856571](微服务.assets/1595211856571.png) +为了减少代码的冗余量,建议 将解析操作 放到拦截器中。一个微服务,一个拦截器。 +定义拦截器 +```java +package com.yanqun.micro_city.interceptor; + +import io.jsonwebtoken.Claims; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import util.JwtUtil; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +/* + * Created by 颜群 + */ +@Component +public class JwtInterceptor extends HandlerInterceptorAdapter { + //请求 ->拦截器(pre) -> 增删改 + @Autowired + private JwtUtil jwtUtil ; + @Autowired + private HttpServletRequest request ; + + + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("jwt拦截器..."); + String authentication = request.getHeader("authentication"); + if(authentication != null && authentication.startsWith("yanqun-")) { + String token = authentication.substring(7); + Claims claims = jwtUtil.parseJWT(token); + String roles = (String)claims.get("roles"); + if(roles.equals("admin")){ + request.setAttribute("claims",claims); + } + } + return true; + } +} + +``` + +配置拦截器规则 + +```java +@Configuration +public class JwtConfig extends WebMvcConfigurationSupport { + + @Autowired + private JwtInterceptor jwtInterceptor; + + @Override + protected void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**") + .excludePathPatterns("/**/login"); //假设city项目中的登录映射叫 login,则排除登录 + } +} + +``` + +使用拦截器 + +```java + @DeleteMapping("deleteById/{id}") + public Message deleteById( @PathVariable("id") Integer id){ + //如果拦截器 判断权限足够,则会在request中 放入一个claims参数;否则,没有claims参数 + Claims claims = (Claims)request.getAttribute("claims"); + if(claims == null){ + return new Message(false,StatusCode.ERROR,"权限不足") ; + } + + boolean result =cityService.deleteById(id) ; + return new Message(true, StatusCode.OK, result ); + } + +``` diff --git "a/notes/\351\235\242\350\257\225\351\242\230/1.JAVA\345\237\272\347\241\200\351\235\242\350\257\225\351\242\2301-50.md" "b/notes/\351\235\242\350\257\225\351\242\230/1.JAVA\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" similarity index 100% rename from "notes/\351\235\242\350\257\225\351\242\230/1.JAVA\345\237\272\347\241\200\351\235\242\350\257\225\351\242\2301-50.md" rename to "notes/\351\235\242\350\257\225\351\242\230/1.JAVA\345\237\272\347\241\200\351\235\242\350\257\225\351\242\230.md" diff --git a/sources/NettyProject/.gradle/5.3/executionHistory/executionHistory.bin b/sources/NettyProject/.gradle/5.3/executionHistory/executionHistory.bin new file mode 100644 index 0000000..4cf89e8 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/executionHistory/executionHistory.bin differ diff --git a/sources/NettyProject/.gradle/5.3/executionHistory/executionHistory.lock b/sources/NettyProject/.gradle/5.3/executionHistory/executionHistory.lock new file mode 100644 index 0000000..05b9446 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/executionHistory/executionHistory.lock differ diff --git a/sources/NettyProject/.gradle/5.3/fileChanges/last-build.bin b/sources/NettyProject/.gradle/5.3/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/fileChanges/last-build.bin differ diff --git a/sources/NettyProject/.gradle/5.3/fileContent/fileContent.lock b/sources/NettyProject/.gradle/5.3/fileContent/fileContent.lock new file mode 100644 index 0000000..2634bad Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/fileContent/fileContent.lock differ diff --git a/sources/NettyProject/.gradle/5.3/fileHashes/fileHashes.bin b/sources/NettyProject/.gradle/5.3/fileHashes/fileHashes.bin new file mode 100644 index 0000000..d5b3bdd Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/fileHashes/fileHashes.bin differ diff --git a/sources/NettyProject/.gradle/5.3/fileHashes/fileHashes.lock b/sources/NettyProject/.gradle/5.3/fileHashes/fileHashes.lock new file mode 100644 index 0000000..87f9653 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/fileHashes/fileHashes.lock differ diff --git a/sources/NettyProject/.gradle/5.3/gc.properties b/sources/NettyProject/.gradle/5.3/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/sources/NettyProject/.gradle/5.3/javaCompile/classAnalysis.bin b/sources/NettyProject/.gradle/5.3/javaCompile/classAnalysis.bin new file mode 100644 index 0000000..ab16240 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/javaCompile/classAnalysis.bin differ diff --git a/sources/NettyProject/.gradle/5.3/javaCompile/javaCompile.lock b/sources/NettyProject/.gradle/5.3/javaCompile/javaCompile.lock new file mode 100644 index 0000000..d8ea118 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/javaCompile/javaCompile.lock differ diff --git a/sources/NettyProject/.gradle/5.3/javaCompile/taskHistory.bin b/sources/NettyProject/.gradle/5.3/javaCompile/taskHistory.bin new file mode 100644 index 0000000..681aeb3 Binary files /dev/null and b/sources/NettyProject/.gradle/5.3/javaCompile/taskHistory.bin differ diff --git a/sources/NettyProject/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/sources/NettyProject/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..1dea2f3 Binary files /dev/null and b/sources/NettyProject/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/sources/NettyProject/.gradle/buildOutputCleanup/cache.properties b/sources/NettyProject/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..d02950a --- /dev/null +++ b/sources/NettyProject/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Mon Aug 03 18:35:56 CST 2020 +gradle.version=5.3 diff --git a/sources/NettyProject/.gradle/buildOutputCleanup/outputFiles.bin b/sources/NettyProject/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..35c3289 Binary files /dev/null and b/sources/NettyProject/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/sources/NettyProject/.gradle/vcs-1/gc.properties b/sources/NettyProject/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/sources/NettyProject/.idea/gradle.xml b/sources/NettyProject/.idea/gradle.xml new file mode 100644 index 0000000..4cf50c3 --- /dev/null +++ b/sources/NettyProject/.idea/gradle.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/sources/NettyProject/.idea/misc.xml b/sources/NettyProject/.idea/misc.xml new file mode 100644 index 0000000..bc8d0a3 --- /dev/null +++ b/sources/NettyProject/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/sources/NettyProject/.idea/uiDesigner.xml b/sources/NettyProject/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/sources/NettyProject/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/NettyProject/.idea/workspace.xml b/sources/NettyProject/.idea/workspace.xml new file mode 100644 index 0000000..b87a434 --- /dev/null +++ b/sources/NettyProject/.idea/workspace.xml @@ -0,0 +1,804 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/sources/microservice/.idea/compiler.xml b/sources/microservice/.idea/compiler.xml index dfc93c7..b2279c2 100644 --- a/sources/microservice/.idea/compiler.xml +++ b/sources/microservice/.idea/compiler.xml @@ -12,8 +12,8 @@ + - @@ -22,7 +22,7 @@ - + diff --git a/sources/microservice/.idea/workspace.xml b/sources/microservice/.idea/workspace.xml index cc01b6d..04ee040 100644 --- a/sources/microservice/.idea/workspace.xml +++ b/sources/microservice/.idea/workspace.xml @@ -2,14 +2,8 @@ - - - - - - - + @@ -52,28 +46,11 @@ - - - - - - - - - - - - - - - + - - - - - + + @@ -90,11 +67,6 @@ - select - queryCities - cityService - par - findByNameOrderByAgeDesc sec * ele @@ -120,6 +92,11 @@ findCityById findCityById2 queryCityBiId + jwt + config + size + 10 + Comsu 100000 @@ -137,24 +114,6 @@ @@ -213,8 +190,7 @@ - - +
-
@@ -284,7 +446,7 @@ - + @@ -308,11 +470,11 @@ + + - - @@ -333,17 +495,17 @@ - - - @@ -555,11 +721,10 @@ - - @@ -568,10 +733,10 @@ - + - - + + @@ -579,18 +744,18 @@ - + - + - - + + - + @@ -606,10 +771,10 @@ - + - - + + @@ -617,18 +782,18 @@ - + - + - - + + - + @@ -641,319 +806,373 @@ - - - - + + + + + + - - - - - - - + - - + + - + - - + + + + + + + + + - + - - + + - + - - + + + + + - + - - + + + + + - + - - + + - + - - + + - - + + - + - - + + - + - - + + - + - - - - - + + - + - - + + - + - - - - - + + - - - - + - - + + - + - - + + - - - - - + + + + + + - - + + + + + + - + - - + + - + - - + + - + - - - - - + + - + - - + + - + - + - + - - - - - + + - - + + + + + + - + - - + + - + - - + + + + + + + + + - - + + + + - + + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - + - + - - + + - + - - + + - + - - + + - + - - + + - + + - - + + - + - + - + - - + + - + - - - - - - - + + - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1007,7 +1226,7 @@ - micro_city + micro_people
\ No newline at end of file diff --git a/sources/microservice/micro_common/src/main/java/util/JwtUtil.java b/sources/microservice/micro_common/src/main/java/util/JwtUtil.java new file mode 100644 index 0000000..1ddb016 --- /dev/null +++ b/sources/microservice/micro_common/src/main/java/util/JwtUtil.java @@ -0,0 +1,60 @@ +package util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/* + * Created by 颜群 + */ + +@Component +@ConfigurationProperties("jwt.config") + +@PropertySource("classpath:application.yml") +public class JwtUtil { + private String key ; + private long ttl ; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public long getTtl() { + return ttl; + } + + public void setTtl(long ttl) { + this.ttl = ttl; + } + + //服务端生成jwt-token的方法 (JWTServer) + //约定:roles有两个值 normal/admin + public String createJWT(String id, String subject,String roles){ + Date now = new Date() ; + long nowMillis = System.currentTimeMillis() ; + + return Jwts.builder().setId(id) + .setSubject(subject) + .setIssuedAt( now ) + .setExpiration( new Date( nowMillis + ttl ) ) + .signWith( SignatureAlgorithm.HS256, key ) + .claim("roles",roles).compact() ;//token + } + + + //客户单发送jwt-token时进行的校验方法 (JWTClient) + public Claims parseJWT(String token){ + return Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody() ; + } +} + diff --git a/sources/microservice/micro_people/pom.xml b/sources/microservice/micro_people/pom.xml index a5dfbb0..666857d 100644 --- a/sources/microservice/micro_people/pom.xml +++ b/sources/microservice/micro_people/pom.xml @@ -18,17 +18,18 @@ com.yanqun 1.0-SNAPSHOT - - - mysql - mysql-connector-java - - - - - org.springframework.boot - spring-boot-starter-data-jpa - + diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/MicroPeopleApplication.java b/sources/microservice/micro_people/src/main/java/com/yanqun/MicroPeopleApplication.java index 452497c..dd5de36 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/MicroPeopleApplication.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/MicroPeopleApplication.java @@ -2,6 +2,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import util.JwtUtil; @SpringBootApplication public class MicroPeopleApplication { @@ -10,4 +12,9 @@ public static void main(String[] args) { SpringApplication.run(MicroPeopleApplication.class, args); } + + @Bean + public JwtUtil jwtUtil(){ + return new JwtUtil() ; + } } diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/controller/AddressControler.java b/sources/microservice/micro_people/src/main/java/com/yanqun/controller/AddressControler.java index 7711714..df23215 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/controller/AddressControler.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/controller/AddressControler.java @@ -1,10 +1,10 @@ package com.yanqun.controller; -import com.yanqun.entity.Message; -import com.yanqun.entity.StatusCode; import com.yanqun.service.AddressService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /* * Created by 颜群 @@ -17,24 +17,24 @@ public class AddressControler { private AddressService addressService ; - @GetMapping(value="/jpa4/findAddressNamesAndCount") - public Message findAddressNamesAndCount(){ - return new Message(true, StatusCode.OK,addressService.findAddressNamesAndCount()) ; - } - - @PostMapping(value="/jpa4/addAddress/{id}/{name}") - public Message addAddress(@PathVariable Integer id ,@PathVariable String name){ - return new Message(true,StatusCode.OK, addressService.addAddress(id,name) ) ; - } - - @DeleteMapping(value="/jpa4/deleteAddress/{id}") - public Message deleteAddress(@PathVariable Integer id){ - return new Message(true,StatusCode.OK, addressService.deleteAddressById(id) ) ; - } - - @PutMapping(value="/jpa4/updateAddress/{id}/{name}") - public Message updateAddress(@PathVariable String name, @PathVariable Integer id){ - return new Message(true,StatusCode.OK, addressService.updateAddress(name,id) ) ; - } +// @GetMapping(value="/jpa4/findAddressNamesAndCount") +// public Message findAddressNamesAndCount(){ +// return new Message(true, StatusCode.OK,addressService.findAddressNamesAndCount()) ; +// } +// +// @PostMapping(value="/jpa4/addAddress/{id}/{name}") +// public Message addAddress(@PathVariable Integer id ,@PathVariable String name){ +// return new Message(true,StatusCode.OK, addressService.addAddress(id,name) ) ; +// } +// +// @DeleteMapping(value="/jpa4/deleteAddress/{id}") +// public Message deleteAddress(@PathVariable Integer id){ +// return new Message(true,StatusCode.OK, addressService.deleteAddressById(id) ) ; +// } +// +// @PutMapping(value="/jpa4/updateAddress/{id}/{name}") +// public Message updateAddress(@PathVariable String name, @PathVariable Integer id){ +// return new Message(true,StatusCode.OK, addressService.updateAddress(name,id) ) ; +// } } diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/controller/PeopleController.java b/sources/microservice/micro_people/src/main/java/com/yanqun/controller/PeopleController.java index acd0717..cec7cd8 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/controller/PeopleController.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/controller/PeopleController.java @@ -1,13 +1,13 @@ package com.yanqun.controller; import com.yanqun.entity.Message; -import com.yanqun.entity.People; import com.yanqun.entity.StatusCode; import com.yanqun.service.PeopleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import util.JwtUtil; -import java.util.List; +import java.util.HashMap; import java.util.Map; /* @@ -17,105 +17,148 @@ @RestController @RequestMapping("/people") public class PeopleController { + @Autowired + private JwtUtil jwtUtil ; @Autowired private PeopleService peopleService ; //localhost:8885/people - @GetMapping - public Message findAll(){ - return new Message(true,StatusCode.OK, peopleService.findAll() ) ; - } - - @GetMapping(value="/jpa2/{name}") - public Message findByNameOrderByAgeDesc(@PathVariable String name){ - return new Message(true,StatusCode.OK, peopleService.findByNameOrderByAgeDesc(name) ) ; - } - - - @GetMapping(value="/jpa3/{age}") - public Message findByAgeAsc(@PathVariable Integer age){ - return new Message(true,StatusCode.OK, peopleService.findByAgeAsc(age) ) ; - } - - @GetMapping(value="/jpa3/page/{age}/{currentPage}/{pageSize}") - public Message findByAgeAsc2(@PathVariable Integer age,@PathVariable Integer currentPage,@PathVariable Integer pageSize){ - return new Message(true,StatusCode.OK, peopleService.findByAgeAsc2(age,currentPage,pageSize) ) ; - } - - - - - - - @PostMapping - public Message savePeople(@RequestBody People people){ - peopleService.savePeople(people); - return new Message( true , StatusCode.OK) ; - } - - //localhost:8885/people/s1001 delete - @DeleteMapping(value="/{id}") - public Message deletePeopleById(@PathVariable String id){ - peopleService.deletePeopleById(id); - return new Message( true , StatusCode.OK) ; - } - - //update ....set name = ?,age = ? where id = ? - @PutMapping // id, name,age - public Message updatePeople( @RequestBody People people){ - peopleService.updatePeople( people); - return new Message( true , StatusCode.OK) ; - } - - - @PutMapping(value="/update/{id}") - public Message updatePeople(@PathVariable String id){ - return new Message(true,StatusCode.OK, peopleService.updatePeople(id) ) ; - } - - @PutMapping(value="/update2/{id}/{age}") - public Message updatePeople2(@PathVariable String id,@PathVariable Integer age){ - return new Message(true,StatusCode.OK, peopleService.updatePeople2(id,age) ) ; - } +// @GetMapping +// public Message findAll(){ +// return new Message(true,StatusCode.OK, peopleService.findAll() ) ; +// } - @PutMapping(value="/update3") - public Message updatePeople3(@RequestBody People people){ - return new Message(true,StatusCode.OK, peopleService.updatePeople3(people) ) ; + public JwtUtil getJwtUtil() { + return jwtUtil; } - - - - @GetMapping(value="/{id}") - public Message findPeopleById(@PathVariable String id){ - return new Message(true,StatusCode.OK, peopleService.findPeopleById(id) ) ; + public void setJwtUtil(JwtUtil jwtUtil) { + this.jwtUtil = jwtUtil; } - @GetMapping(value="/jpa4/{id}") - public Message findNameById(@PathVariable String id){ - return new Message(true,StatusCode.OK,peopleService.findNameById(id)) ; - - } + //用户名:username + //密码:password + @PostMapping(value="/login") + public Message login(@RequestBody Map login){ + //controller -sercice -dao 模拟操作 + String uname = login.get("username") ; + String upwd = login.get("password") ; + //findUserByUsernameAndPassword + //zs/abc -> 返回这个人的全部信息 User(zs/abc,id(1001).....) + + System.out.println("1111"); + //假设数据库中的zs/abc (并且:假设这个人的id1001,这个人是管理员权限admin ) + if(uname.equals("zs") && upwd.equals("abc")){ + //登录成功,服务端生成token + //String id, String subject,String roles + String token = jwtUtil.createJWT("1001", "zs", "admin"); + + Map map = new HashMap() ; + map.put("token",token) ; + map.put("username",uname) ; + + System.out.println("登录成功"); + //登录成功:返回token\用户名 + return new Message(true,StatusCode.OK,map) ; + }else{ + System.out.println("登录失败"); + return new Message(false,StatusCode.ERROR) ; + } - @GetMapping(value="/jpa4/{name}/{age}") - public Message findPeopleByNameAndAge(@PathVariable String name, @PathVariable int age){ - return new Message(true,StatusCode.OK,peopleService.findPeopleByNameAndAge(name,age)) ; } - //给原生SQL传入的是集合,并且加了分页功能 - @GetMapping(value="/jpa4/findPeopleByAges/{currentPage}/{pageSize}") - public Message findPeopleByAges(@RequestParam(value="ages") List ages,@PathVariable Integer currentPage,@PathVariable Integer pageSize){ - return new Message(true,StatusCode.OK,peopleService.findPeopleByAges(ages,currentPage,pageSize)) ; - - } - //springmvc 接收map 和接收entiy是一致的 - @GetMapping(value="/jpa5/findPeople/{currentPage}/{pageSize}") - public Message findPeople(@RequestBody Map map ,@PathVariable Integer currentPage,@PathVariable Integer pageSize) { - return new Message(true, StatusCode.OK, peopleService.findPeople(map,currentPage,pageSize)); - } +// @GetMapping(value="/jpa2/{name}") +// public Message findByNameOrderByAgeDesc(@PathVariable String name){ +// return new Message(true,StatusCode.OK, peopleService.findByNameOrderByAgeDesc(name) ) ; +// } +// +// +// @GetMapping(value="/jpa3/{age}") +// public Message findByAgeAsc(@PathVariable Integer age){ +// return new Message(true,StatusCode.OK, peopleService.findByAgeAsc(age) ) ; +// } +// +// @GetMapping(value="/jpa3/page/{age}/{currentPage}/{pageSize}") +// public Message findByAgeAsc2(@PathVariable Integer age,@PathVariable Integer currentPage,@PathVariable Integer pageSize){ +// return new Message(true,StatusCode.OK, peopleService.findByAgeAsc2(age,currentPage,pageSize) ) ; +// } +// +// +// +// +// +// +// @PostMapping +// public Message savePeople(@RequestBody People people){ +// peopleService.savePeople(people); +// return new Message( true , StatusCode.OK) ; +// } +// +// //localhost:8885/people/s1001 delete +// @DeleteMapping(value="/{id}") +// public Message deletePeopleById(@PathVariable String id){ +// peopleService.deletePeopleById(id); +// return new Message( true , StatusCode.OK) ; +// } +// +// //update ....set name = ?,age = ? where id = ? +// @PutMapping // id, name,age +// public Message updatePeople( @RequestBody People people){ +// peopleService.updatePeople( people); +// return new Message( true , StatusCode.OK) ; +// } +// +// +// @PutMapping(value="/update/{id}") +// public Message updatePeople(@PathVariable String id){ +// return new Message(true,StatusCode.OK, peopleService.updatePeople(id) ) ; +// } +// +// @PutMapping(value="/update2/{id}/{age}") +// public Message updatePeople2(@PathVariable String id,@PathVariable Integer age){ +// return new Message(true,StatusCode.OK, peopleService.updatePeople2(id,age) ) ; +// } +// +// @PutMapping(value="/update3") +// public Message updatePeople3(@RequestBody People people){ +// return new Message(true,StatusCode.OK, peopleService.updatePeople3(people) ) ; +// } +// +// +// +// +// @GetMapping(value="/{id}") +// public Message findPeopleById(@PathVariable String id){ +// return new Message(true,StatusCode.OK, peopleService.findPeopleById(id) ) ; +// } +// +// @GetMapping(value="/jpa4/{id}") +// public Message findNameById(@PathVariable String id){ +// return new Message(true,StatusCode.OK,peopleService.findNameById(id)) ; +// +// } +// +// @GetMapping(value="/jpa4/{name}/{age}") +// public Message findPeopleByNameAndAge(@PathVariable String name, @PathVariable int age){ +// return new Message(true,StatusCode.OK,peopleService.findPeopleByNameAndAge(name,age)) ; +// +// } +// +// //给原生SQL传入的是集合,并且加了分页功能 +// @GetMapping(value="/jpa4/findPeopleByAges/{currentPage}/{pageSize}") +// public Message findPeopleByAges(@RequestParam(value="ages") List ages,@PathVariable Integer currentPage,@PathVariable Integer pageSize){ +// return new Message(true,StatusCode.OK,peopleService.findPeopleByAges(ages,currentPage,pageSize)) ; +// +// } +// +// //springmvc 接收map 和接收entiy是一致的 +// @GetMapping(value="/jpa5/findPeople/{currentPage}/{pageSize}") +// public Message findPeople(@RequestBody Map map ,@PathVariable Integer currentPage,@PathVariable Integer pageSize) { +// return new Message(true, StatusCode.OK, peopleService.findPeople(map,currentPage,pageSize)); +// } diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/dao/AddressDao.java b/sources/microservice/micro_people/src/main/java/com/yanqun/dao/AddressDao.java index c0bb374..987d902 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/dao/AddressDao.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/dao/AddressDao.java @@ -1,36 +1,30 @@ package com.yanqun.dao; -import com.yanqun.entity.Address; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; - -import java.util.List; - /* * Created by 颜群 */ -public interface AddressDao extends JpaRepository, JpaSpecificationExecutor
{ +public interface AddressDao +// extends JpaRepository, JpaSpecificationExecutor
+{ /*查询每一个地址,各自有多少人使用 xa 3 bj 5 核心:将原生的SQL,放在value中。无论是 单表、还是复杂的多表查询都可以。 */ - @Query(nativeQuery = true ,value="select a.name,count(1) from tb_address a inner join tb_people p on a.id = p.address group by a.name") - public List findAddressNamesAndCount() ; - - //DML - @Modifying - @Query(nativeQuery = true ,value="insert into tb_address(id,name) values(?,?)") - public int addAddress(Integer id ,String name); - - @Modifying - @Query(nativeQuery = true,value="delete from tb_address where id = ?") - public int deleteAddressById(Integer id); - - @Modifying - @Query(nativeQuery = true,value = "update tb_address a set a.name= ? where a.id =?") - public int updateAddress( String name , Integer id ); +// @Query(nativeQuery = true ,value="select a.name,count(1) from tb_address a inner join tb_people p on a.id = p.address group by a.name") +// public List findAddressNamesAndCount() ; +// +// //DML +// @Modifying +// @Query(nativeQuery = true ,value="insert into tb_address(id,name) values(?,?)") +// public int addAddress(Integer id ,String name); +// +// @Modifying +// @Query(nativeQuery = true,value="delete from tb_address where id = ?") +// public int deleteAddressById(Integer id); +// +// @Modifying +// @Query(nativeQuery = true,value = "update tb_address a set a.name= ? where a.id =?") +// public int updateAddress( String name , Integer id ); } diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/dao/PeopleDao.java b/sources/microservice/micro_people/src/main/java/com/yanqun/dao/PeopleDao.java index e6b52e1..e680916 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/dao/PeopleDao.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/dao/PeopleDao.java @@ -1,16 +1,5 @@ package com.yanqun.dao; -import com.yanqun.entity.People; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; - /* * Created by 颜群 * jpa使用方式一:继承JpaRepository , JpaSpecificationExecutor;需要写任何代码 @@ -18,42 +7,44 @@ * JpaRepository :提供了基本的增删改查 * JpaSpecificationExecutor:较为复杂的条件查询 */ -public interface PeopleDao extends JpaRepository , JpaSpecificationExecutor { - //jpa使用方式一:dao层中不用自己写任何方法,只调用父接口中的方法。缺点:父接口中提供的方法有限 - //jpa使用方式二:可以编写自己的方法,但是可以不写SQL。根据约定写方法的名字。 - public List findByNameOrderByAgeDesc(String name) ; - - //jpa使用方式三:面向对象SQL语句 :JPQL - //select p from People p from where 类中的属性 = ?序号 - @Query("select p from People p where age =?1 ") - public List findByAgeAsc(Integer age) ;//因为上面是通过Query指定了HQL,因此方法名可以任意编写 - - //在方式三的基础上,加上分页功能 - @Query("select p from People p where age =?1 ") - public List findByAgeAsc2(Integer age , Pageable pageable) ;//因为上面是通过Query指定了HQL,因此方法名可以任意编写 - - @Modifying - @Query("update People set age=age+1 where id =?1") - public int updatePeople(String id) ; - - @Modifying - @Query("update People set age=?2 where id =?1") - public int updatePeople2( String id,Integer age); - - - @Modifying - @Query("update People p set p.age = :#{#people.age} , p.address=:#{#people.address} where p.id =:#{#people.id}") - public int updatePeople3(@Param("people") People people );//28 ,shanghai - - //jpa使用方式四:面向SQL(原生的SQL语句),推荐 - @Query(nativeQuery = true , value="select name from tb_people where id =? ") - public String findNameById(String id) ; - - @Query(nativeQuery = true,value="select * from tb_people where name = ? and age =? ") - public List findPeopleByNameAndAge(String name ,int age); - - @Query(nativeQuery = true,value="select * from tb_people where age in (:ages) order by age") - public Page findPeopleByAges(@Param("ages") List ages , Pageable pageable); +public interface PeopleDao +// extends JpaRepository , JpaSpecificationExecutor +{ +// //jpa使用方式一:dao层中不用自己写任何方法,只调用父接口中的方法。缺点:父接口中提供的方法有限 +// //jpa使用方式二:可以编写自己的方法,但是可以不写SQL。根据约定写方法的名字。 +// public List findByNameOrderByAgeDesc(String name) ; +// +// //jpa使用方式三:面向对象SQL语句 :JPQL +// //select p from People p from where 类中的属性 = ?序号 +// @Query("select p from People p where age =?1 ") +// public List findByAgeAsc(Integer age) ;//因为上面是通过Query指定了HQL,因此方法名可以任意编写 +// +// //在方式三的基础上,加上分页功能 +// @Query("select p from People p where age =?1 ") +// public List findByAgeAsc2(Integer age , Pageable pageable) ;//因为上面是通过Query指定了HQL,因此方法名可以任意编写 +// +// @Modifying +// @Query("update People set age=age+1 where id =?1") +// public int updatePeople(String id) ; +// +// @Modifying +// @Query("update People set age=?2 where id =?1") +// public int updatePeople2( String id,Integer age); +// +// +// @Modifying +// @Query("update People p set p.age = :#{#people.age} , p.address=:#{#people.address} where p.id =:#{#people.id}") +// public int updatePeople3(@Param("people") People people );//28 ,shanghai +// +// //jpa使用方式四:面向SQL(原生的SQL语句),推荐 +// @Query(nativeQuery = true , value="select name from tb_people where id =? ") +// public String findNameById(String id) ; +// +// @Query(nativeQuery = true,value="select * from tb_people where name = ? and age =? ") +// public List findPeopleByNameAndAge(String name ,int age); +// +// @Query(nativeQuery = true,value="select * from tb_people where age in (:ages) order by age") +// public Page findPeopleByAges(@Param("ages") List ages , Pageable pageable); //public List findPeopleByAges(@Param("ages") List ages , Pageable pageable); //jpa使用方式五:面向对象查法 diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/entity/Address.java b/sources/microservice/micro_people/src/main/java/com/yanqun/entity/Address.java index caa6d1e..f6df30d 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/entity/Address.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/entity/Address.java @@ -1,16 +1,12 @@ package com.yanqun.entity; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; - /* * Created by 颜群 */ -@Entity -@Table(name="tb_address") +//@Entity +//@Table(name="tb_address") public class Address { - @Id +// @Id private Integer id ; private String name ; diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/entity/People.java b/sources/microservice/micro_people/src/main/java/com/yanqun/entity/People.java index faf6abe..dbeb7cd 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/entity/People.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/entity/People.java @@ -4,15 +4,12 @@ * Created by 颜群 */ -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; import java.io.Serializable; -@Entity -@Table(name="tb_people") +//@Entity +//@Table(name="tb_people") public class People implements Serializable { - @Id +// @Id private String id ; //分布式系统 uuid snowflake自动生成一套 不会重复的id private String name ; private Integer age ; diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/service/AddressService.java b/sources/microservice/micro_people/src/main/java/com/yanqun/service/AddressService.java index 2483110..c787a66 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/service/AddressService.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/service/AddressService.java @@ -1,11 +1,6 @@ package com.yanqun.service; -import com.yanqun.dao.AddressDao; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; /* * Created by 颜群 @@ -13,29 +8,28 @@ @Service public class AddressService { - @Autowired - private AddressDao addressDao ; - - - public List findAddressNamesAndCount() { - return addressDao.findAddressNamesAndCount() ; - } - - - - - @Transactional - public int addAddress(Integer id ,String name){ - return addressDao.addAddress(id,name) ; - } - - @Transactional - public int deleteAddressById(Integer id){ - return addressDao.deleteAddressById(id) ; - } - - @Transactional - public int updateAddress( String name , Integer id ){ - return addressDao.updateAddress(name,id) ; - } +// @Autowired +// private AddressDao addressDao ; +// +// +// public List findAddressNamesAndCount() { +// return addressDao.findAddressNamesAndCount() ; +// } +// +// +// +// @Transactional +// public int addAddress(Integer id ,String name){ +// return addressDao.addAddress(id,name) ; +// } +// +// @Transactional +// public int deleteAddressById(Integer id){ +// return addressDao.deleteAddressById(id) ; +// } +// +// @Transactional +// public int updateAddress( String name , Integer id ){ +// return addressDao.updateAddress(name,id) ; +// } } diff --git a/sources/microservice/micro_people/src/main/java/com/yanqun/service/PeopleService.java b/sources/microservice/micro_people/src/main/java/com/yanqun/service/PeopleService.java index 1cc1f0d..448201f 100644 --- a/sources/microservice/micro_people/src/main/java/com/yanqun/service/PeopleService.java +++ b/sources/microservice/micro_people/src/main/java/com/yanqun/service/PeopleService.java @@ -1,21 +1,6 @@ package com.yanqun.service; -import com.yanqun.dao.PeopleDao; -import com.yanqun.entity.People; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; /* * Created by 颜群 @@ -23,114 +8,114 @@ @Service public class PeopleService { - @Autowired - private PeopleDao peopleDao ; - - - public void savePeople(People people){ - peopleDao.save(people) ; - } - - - //jpa底层,修改和 增加都是 save() - public void updatePeople(People people){ - peopleDao.save( people) ; - } - - public void deletePeopleById(String id){ - peopleDao.deleteById(id); - } - - public List findAll() { - return peopleDao.findAll() ; - } - - public People findPeopleById(String id){ - return peopleDao.findById( id ).get() ; - } - - public List findByNameOrderByAgeDesc(String name) { - return peopleDao.findByNameOrderByAgeDesc(name) ; - } - - public List findByAgeAsc(Integer age) { - return peopleDao.findByAgeAsc(age) ; - } - - public List findByAgeAsc2(Integer age,int currentPage ,int pageSize) { -// PageRequest.of(第几页,页面大小); - PageRequest pageRequest = PageRequest.of(currentPage-1, pageSize);//1 ,0 - return peopleDao.findByAgeAsc2(age, pageRequest) ; - } - - @Transactional - public int updatePeople(String id){ - return peopleDao.updatePeople(id) ; - } - - - +// @Autowired +// private PeopleDao peopleDao ; +// +// +// public void savePeople(People people){ +// peopleDao.save(people) ; +// } +// +// +// //jpa底层,修改和 增加都是 save() +// public void updatePeople(People people){ +// peopleDao.save( people) ; +// } +// +// public void deletePeopleById(String id){ +// peopleDao.deleteById(id); +// } +// +// public List findAll() { +// return peopleDao.findAll() ; +// } +// +// public People findPeopleById(String id){ +// return peopleDao.findById( id ).get() ; +// } +// +// public List findByNameOrderByAgeDesc(String name) { +// return peopleDao.findByNameOrderByAgeDesc(name) ; +// } +// +// public List findByAgeAsc(Integer age) { +// return peopleDao.findByAgeAsc(age) ; +// } +// +// public List findByAgeAsc2(Integer age,int currentPage ,int pageSize) { +//// PageRequest.of(第几页,页面大小); +// PageRequest pageRequest = PageRequest.of(currentPage-1, pageSize);//1 ,0 +// return peopleDao.findByAgeAsc2(age, pageRequest) ; +// } +// // @Transactional - public int updatePeople2(String id,int age){ - return peopleDao.updatePeople2(id,age) ; - } - - - - @Transactional - public int updatePeople3(People people){ - return peopleDao.updatePeople3(people) ; - } - - - public String findNameById(String id) { - return peopleDao.findNameById(id) ; - } - - public List findPeopleByNameAndAge(String name,int age){ - return peopleDao.findPeopleByNameAndAge(name,age) ; - } - - - public Page findPeopleByAges(List ages, Integer currentPage, Integer pageSize){ - PageRequest pageRequest = PageRequest.of(currentPage-1, pageSize); - return peopleDao.findPeopleByAges(ages,pageRequest) ; - } - - - //map [ {id,1}, {name,zs} ] - //select *from people where id =? and name like '%?%' and age=? and address=? - //方式五 - public Page findPeople(Map map, int currentPage,int pageSize){ - - PageRequest pageRequest = PageRequest.of(currentPage - 1, pageSize); - - return peopleDao.findAll(new Specification() { - @Override - public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { - //查询条件 - List predicates = new ArrayList<>() ; - if (map.get("age") != null && map.get("age")!="" ) {//是否where子句中有age - predicates.add( criteriaBuilder.equal( root.get("age").as(Integer.class) ,(Integer)map.get("age") ) ) ; - } - - if(map.get("name") != null && map.get("name")!=""){ - predicates.add( criteriaBuilder.like( root.get("name").as(String.class) ,"%"+(String)map.get("name")+"%" ) ); - } - - - //if address - //if age - //API拼凑 - return criteriaBuilder.and( predicates.toArray( new Predicate[predicates.size()] ) ); - } - }, pageRequest ) ; - - - - } - - +// public int updatePeople(String id){ +// return peopleDao.updatePeople(id) ; +// } +// +// +// +//// @Transactional +// public int updatePeople2(String id,int age){ +// return peopleDao.updatePeople2(id,age) ; +// } +// +// +// +// @Transactional +// public int updatePeople3(People people){ +// return peopleDao.updatePeople3(people) ; +// } +// +// +// public String findNameById(String id) { +// return peopleDao.findNameById(id) ; +// } +// +// public List findPeopleByNameAndAge(String name,int age){ +// return peopleDao.findPeopleByNameAndAge(name,age) ; +// } +// +// +// public Page findPeopleByAges(List ages, Integer currentPage, Integer pageSize){ +// PageRequest pageRequest = PageRequest.of(currentPage-1, pageSize); +// return peopleDao.findPeopleByAges(ages,pageRequest) ; +// } +// +// +// //map [ {id,1}, {name,zs} ] +// //select *from people where id =? and name like '%?%' and age=? and address=? +// //方式五 +// public Page findPeople(Map map, int currentPage,int pageSize){ +// +// PageRequest pageRequest = PageRequest.of(currentPage - 1, pageSize); +// +// return peopleDao.findAll(new Specification() { +// @Override +// public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { +// //查询条件 +// List predicates = new ArrayList<>() ; +// if (map.get("age") != null && map.get("age")!="" ) {//是否where子句中有age +// predicates.add( criteriaBuilder.equal( root.get("age").as(Integer.class) ,(Integer)map.get("age") ) ) ; +// } +// +// if(map.get("name") != null && map.get("name")!=""){ +// predicates.add( criteriaBuilder.like( root.get("name").as(String.class) ,"%"+(String)map.get("name")+"%" ) ); +// } +// +// +// //if address +// //if age +// //API拼凑 +// return criteriaBuilder.and( predicates.toArray( new Predicate[predicates.size()] ) ); +// } +// }, pageRequest ) ; +// +// +// +// } +// +// diff --git a/sources/microservice/micro_people/src/main/resources/application.yml b/sources/microservice/micro_people/src/main/resources/application.yml index e984a00..cfc287a 100644 --- a/sources/microservice/micro_people/src/main/resources/application.yml +++ b/sources/microservice/micro_people/src/main/resources/application.yml @@ -1,25 +1,28 @@ server: port: 8885 -spring: - datasource: - username: root - password: root123 - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://192.168.2.130/micro_people?characterEncodig=utf-8 - jpa: - database: mysql - generate-ddl: true #利用jpa,根据实体类、自动生成相应的表 - show-sql: true - #abcda: true 如果属性名写错,背景是黄色 - properties: - hibernate: - dialect: - org.hibernate.dialect.MySQL5InnoDBDialect # 默认 不加也可以;但如果 无法使用自动生成表的功能,则加上此句 +#spring: +# datasource: +# username: root +# password: root123 +# driverClassName: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://192.168.2.130/micro_people?characterEncodig=utf-8 +# jpa: +# database: mysql +# generate-ddl: true #利用jpa,根据实体类、自动生成相应的表 +# show-sql: true +# properties: +# hibernate: +# dialect: +# org.hibernate.dialect.MySQL5InnoDBDialect # 默认 不加也可以;但如果 无法使用自动生成表的功能,则加上此句 # hibernate: # ddl-auto: update +jwt: + config: + key: yanqun + ttl: 1800000 diff --git a/sources/microservice/micro_people/target/classes/META-INF/micro_people.kotlin_module b/sources/microservice/micro_people/target/classes/META-INF/micro_people.kotlin_module deleted file mode 100644 index 8fb6019..0000000 Binary files a/sources/microservice/micro_people/target/classes/META-INF/micro_people.kotlin_module and /dev/null differ diff --git a/sources/microservice/micro_people/target/classes/application.yml b/sources/microservice/micro_people/target/classes/application.yml index e984a00..cfc287a 100644 --- a/sources/microservice/micro_people/target/classes/application.yml +++ b/sources/microservice/micro_people/target/classes/application.yml @@ -1,25 +1,28 @@ server: port: 8885 -spring: - datasource: - username: root - password: root123 - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://192.168.2.130/micro_people?characterEncodig=utf-8 - jpa: - database: mysql - generate-ddl: true #利用jpa,根据实体类、自动生成相应的表 - show-sql: true - #abcda: true 如果属性名写错,背景是黄色 - properties: - hibernate: - dialect: - org.hibernate.dialect.MySQL5InnoDBDialect # 默认 不加也可以;但如果 无法使用自动生成表的功能,则加上此句 +#spring: +# datasource: +# username: root +# password: root123 +# driverClassName: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://192.168.2.130/micro_people?characterEncodig=utf-8 +# jpa: +# database: mysql +# generate-ddl: true #利用jpa,根据实体类、自动生成相应的表 +# show-sql: true +# properties: +# hibernate: +# dialect: +# org.hibernate.dialect.MySQL5InnoDBDialect # 默认 不加也可以;但如果 无法使用自动生成表的功能,则加上此句 # hibernate: # ddl-auto: update +jwt: + config: + key: yanqun + ttl: 1800000 diff --git a/sources/microservice/projct_httpclient/src/main/java/URLConnectionDemo.java b/sources/microservice/projct_httpclient/src/main/java/URLConnectionDemo.java index 1ed7f03..53000db 100644 --- a/sources/microservice/projct_httpclient/src/main/java/URLConnectionDemo.java +++ b/sources/microservice/projct_httpclient/src/main/java/URLConnectionDemo.java @@ -10,50 +10,47 @@ * Created by 颜群 */ public class URLConnectionDemo { - public static void main(String[] args) { + + public static String getResource(){ BufferedReader reader = null ; StringBuffer html = new StringBuffer(); try { - URL url = new URL("http://www.lanqiao.cn/");//如果某个网站无法爬取,则更换网址,或者终止爬取 + URL url = new URL("https://www.lanqiao.cn/");//如果某个网站无法爬取,则更换网址,或者终止爬取 //获取网页的html源码 URLConnection urlConnection = url.openConnection(); urlConnection.connect(); - reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //字节流 ->转换流-> 字符串(字符流)->带缓冲区的字符流 + reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //字节流 ->转换流-> 字符串(字符流)->带缓冲区的字符流 String line = null; while ((line = reader.readLine()) != null) { html.append(line); } - }catch (Exception e){ e.printStackTrace(); }finally { - { - try { - if(reader != null) reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } + { + try { + if(reader != null) reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } + return html.toString() ; + } -// System.out.println(html); - + public static String parseResource(String html){ //通过正则表达式+字符串解析 从html中,解析出需要的数据:将网站的简介(description)进行提取 /* .: 除了换行符以外的任何字符 + : 匹配之前的一次,或多次 ? :0次或1次 - - html : aaa
xxxxx
bbbb (.+):贪婪模式 : <.+> :
xxxxx
(.+?) :惰性模式 : <.+?> :
- - */ - Pattern pattern = Pattern.compile( "meta name=\"description\" content=\"(.+?)\"" ) ; + Pattern pattern = Pattern.compile( "meta data-n-head=\"ssr\" data-hid=\"description\" name=\"description\" itemprop=\"description\" content=\"(.+?)\"" ) ; //从html中,只提取 符合patter约束的字符串 Matcher matcher = pattern.matcher( html) ; @@ -67,7 +64,17 @@ public static void main(String[] args) { group(2) */ result = matcher.group(0); //提取 + result = result.substring(result.indexOf("content=") + "content=".length()); } + return result ; + } + + + public static void main(String[] args) { + + String html = getResource(); + + String result = parseResource(html) ; System.out.println(result==null? "爬取失败":result);