黑马程序员-JAVA.net-网络工具类粗解

2024-01-02 19:08

本文主要是介绍黑马程序员-JAVA.net-网络工具类粗解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-


Java自1.0就已集成网络操作的工具,提供了从基于流的Java.net包以实现网络访问和操作,而Java1.4又假如了nio包,利用异步和面向缓冲的新方式实现了更高效的网络操作工具类,并以此重写了部分io包中的内容。

Java.net

java.net 包可以大致分为两个部分:

  • 低级 API,用于处理以下抽象:
    • 地址,也就是网络标识符,如 IP 地址。
    • 套接字,也就是基本双向数据通信机制。
    • 接口,用于描述网络接口。
  • 高级 API,用于处理以下抽象:
    • URI,表示统一资源标识符。
    • URL,表示统一资源定位符。
    • 连接,表示到 URL 所指向资源的连接。

地址

InetAddress 类是表示 IP(Internet 协议)地址的抽象。它拥有两个子类:
- 用于 IPv4 地址的 Inet4Address。
- 用于 IPv6 地址的 Inet6Address。
IP 地址是 IP 使用的4个byte(IPv4)或者16个byte(IPv6);对于Hostname,将通过主机名解析服务(通常是DNS)将他解析为IP地址。

ipv6

并非所有系统和网络环境都支持 IPv6 协议,在 IPv6 不可用或被显式禁用的情况下,在此情况下,大多数方法在使用 Inet6Address 调用时都将抛出异常。

简单的创建InetAddress 的例子
try {InetAddress ip = null;//localhostip = Inet4Address.getLocalHost();sp(ip);//xxxx-xxxx/192.168.1.100 for example//loopbackip= Inet4Address.getLoopbackAddress();sp(ip);//localhost/127.0.0.1 //Indicate a ip & hostname without NSip=Inet4Address.getByAddress("Its.A.Fake.Domian", new byte[]{(byte) 0xfe,(byte) 0xfe,(byte) 0xfe,(byte) 0xfe});sp(ip);//Its.A.Fake.Domian/254.254.254.254//Indicate a ip with 4bytes for ipv4ip=Inet4Address.getByAddress(new byte[]{(byte) 0xfe,(byte) 0xfe,(byte) 0xfe,(byte) 0xfe});sp(ip);///254.254.254.254//Indicate a ip for hostname using NSip=Inet4Address.getByName("www.oracle.com");sp(ip);//www.oracle.com/184.50.90.127} catch (UnknownHostException e) {e.printStackTrace();}

套接字

套接字是实际操作传输层的Java工具对象,基于UDP和TCP的传输都可以通过构建套接字来完成。

端口

端口是TCP和UDP协议中对同一IP地址不同应用对象的区分手段,TCP与UDP的端口是互不影响的。

UDP与DatagramSocket

UDP:User Datagram Protocol是一种面向无连接,基于数据包的传输层协议,一个UDP数据包最大为65535bytes。但是UDP不含任何传输保证,数据的有效性必须由应用自行处理,但相对于TCP,它的连接开销小,相对速度快,很多协议也是基于UDP的,比如很重要的DNS(UDP53)协议,DHCP(UDP67/68)协议;另外很多协议同时支持TCP以及UDP以实现更好的数据交换。

DatagramSocket是Java中处理UDP点对点传输的网络端点对象。通过传输DatagramPacket网络包实现UDP协议的传输。将DatagramPacket目标指定为广播地址可以实现域内网络多播。

DatagramSocket的构造方法允许指定端口,当绑定端口失败时会抛出SocketException;若不指定,将由JVM随机安排一个可用的端口。
由于端口属于系统资源,必须保证端口在使用完后通过close()方法释放。

MulticastSocket

UDP的组播,多播组通过 D 类 IP 地址和标准 UDP 端口号指定,通过joinGroup(group)加入组,将消息发送到多播组时,该主机和端口的所有预定接收者都将接收到消息,多个 MulticastSocket 可以同时预定多播组和端口,并且都会接收到组数据报。

UDP的简单例子

一个简单的控制台通过本地环回的UDP信息收发

        final int port = 36314;try {UdpReciver serv = new UdpReciver(port);StringUdpSender cli=new StringUdpSender(port);new Thread(serv).start();new Thread(cli).start();ts(10000);serv.stop();} catch (IOException e) {e.printStackTrace();}
class StringUdpSender implements Runnable {private DatagramSocket soc;private final String exitFlag;private final int port;public StringUdpSender(int port,String exitFlag) throws SocketException {super();this.exitFlag = exitFlag;soc=new DatagramSocket();this.port=port;}public StringUdpSender(int port) throws SocketException {this(port,"exit");}@Overridepublic void run() {String msg=null;BufferedReader br= new BufferedReader(new  InputStreamReader(System.in));DatagramPacket dp=null;while(true){try {msg=br.readLine();if(!exitFlag.equals(msg)){dp=new DatagramPacket(msg.getBytes(), msg.getBytes().length, InetAddress.getByName("localhost"), port);soc.send(dp);}else{break;}} catch (IOException e) {e.printStackTrace();}}if (soc != null && !soc.isClosed()) {soc.close();}}}class UdpReciver implements Runnable {private DatagramSocket soc;private volatile boolean runFlag = false;public UdpReciver(int port) throws SocketException {super();this.soc = new DatagramSocket(port);}public void stop() {this.setRunFlag(false);}public boolean isRunning() {return runFlag;}private synchronized void setRunFlag(boolean runFlag) {this.runFlag = runFlag;}@Overridepublic void run() {this.setRunFlag(true);DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);while (runFlag) {try {this.soc.receive(dp);} catch (IOException e) {e.printStackTrace();}sp(dp.getAddress());sp(new String(dp.getData(),0,dp.getLength()));}if (soc != null && !soc.isClosed()) {soc.close();sp("Server stop");}}@Overrideprotected void finalize() throws Throwable {super.finalize();if (soc != null && !soc.isClosed()) {soc.close();}}
}
TCP

TCP(Transfer Control Protocol)是面向连接的,相对可靠的数据传输协议,TCP的双方必须经过3次握手来达成一个连接,有了连接之后才能开始传输数据,TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和,一旦有问题将请求重发,包丢失也将请求重发,而重复的包将丢弃。这样TCP就达成了一个可靠的数据传送。
TCP的连接时有状态的,双方通过协议信号更新彼此的状态,常见的服务端LISTEN表示监听中,任一方ESTABLISHED 表示连接已建立等。

Socket

Socket是Java中TCP端点的抽象,套接字的实际工作由 SocketImpl 类的实例执行。
客户端可以通过构造一个包含服务器IP和端口的Socket尝试打开TCP连接。
打开连接之后,可以通过getInputStream和getOutputStream与对端通信。

ServerSocket

ServerSocket是Java中TCP服务端的抽象,绑定一个端口即可开始服务。服务器套接字的实际工作由 SocketImpl 类的实例执行。
ServerSocket通过accept() 阻塞方法获得客户端的连接,然后可以操作这个连接来处理交互。

TCP服务器和客户端的简单例子

这个例子实现了简单的TCP服务器和客户端,服务器对客户端送来的String简单的+上”response”返回客户端,服务端实现了简单的异步消息和连接统计。


public class TcpDemo {public static void main(String[] args) {final int serverPort = 23333;InetAddress serverAddr = null;try {serverAddr = InetAddress.getLocalHost();} catch (UnknownHostException e1) {e1.printStackTrace();}//start Servertry {new Thread(new TcpServer(serverPort)).start();} catch (IOException e1) {e1.printStackTrace();}//start ClientSocket s = null;//5 thread client
//      for (int i = 0; i < 5; i++) {
//          try {
//              s = new Socket(serverAddr, serverPort);
//          } catch (IOException e) {
//              e.printStackTrace();
//          }
//          new Thread(new TcpClient(s)).start();
//      }//about 400 thread clientwhile(true){ts(10);try {s = new Socket(serverAddr, serverPort);} catch (IOException e) {e.printStackTrace();}new Thread(new TcpClient(s)).start();}}}class TcpClient implements Runnable {//end connection key wordpublic static final String ENDCONN="##$$$$##";Socket socket;public TcpClient(Socket socket) {super();this.socket = socket;}@Overridepublic void run() {
//      sp(socket+" Client");//client request//emulate chatRandom r=new Random();int times=r.nextInt(20)+5;PrintWriter pw=null;BufferedReader bfr=null;try {pw = new PrintWriter(socket.getOutputStream());bfr=new BufferedReader(new InputStreamReader(socket.getInputStream()));} catch (IOException e1) {e1.printStackTrace();}for (int i = 0; i < times; i++) {String msg = "hello from"+socket.getLocalPort()+"##"+i;pw.println(msg);pw.flush();try {msg=bfr.readLine();} catch (IOException e) {e.printStackTrace();}
//          sp(msg);ts(300);}pw.println(TcpClient.ENDCONN);pw.flush();
//      if(socket!=null && !socket.isClosed()){
//          try {
//              socket.close();
//          } catch (IOException e) {
//              e.printStackTrace();
//          }
//      }}}class TcpServer implements Runnable {private ServerSocket s;private ExecutorService exes;private final BlockingQueue<Socket> connects;private volatile ConcurrentHashMap<String, Future<String>> results;public TcpServer(int port) throws IOException {super();this.s = new ServerSocket(port);this.exes = Executors.newCachedThreadPool();this.connects = new SynchronousQueue<Socket>();this.results = new ConcurrentHashMap<String, Future<String>>();}@Overridepublic void run() {// Dispatcher threadnew Thread(new Runnable() {@Overridepublic void run() {while (true) {try {Socket s = connects.take();String stamp = s.toString() + Instant.now().toString();Future<String> result = exes.submit(new RequestHandler(s));results.put(stamp, result);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();// Result collector threadnew Thread(new Runnable() {@Overridepublic void run() {while (true) {ts(1000);List<String> remove=new ArrayList<String>();results.forEach((String stamp,Future<String> result) -> {if(result.isDone()){try {
//                              sp(result.get());remove.add(stamp);} catch (Exception e) {e.printStackTrace();}}else if(result.isCancelled()){
//                          sp(stamp+" is Cancelled");remove.add(stamp);}});for (String string : remove) {results.remove(string);}sp("Missions : "+results.size());}}}).start();//Serv to Clientwhile (true) {try {final Socket socket = s.accept();try {this.connects.put(socket);} catch (InterruptedException e) {e.printStackTrace();}} catch (IOException e) {e.printStackTrace();}}}}class RequestHandler implements Callable<String> {private Socket socket;public RequestHandler(Socket conn) {super();this.socket = conn;}@Overridepublic String call() throws Exception {//server BusinessPrintWriter pw=null;BufferedReader bfr=null;String msg=null;try {pw = new PrintWriter(socket.getOutputStream());bfr=new BufferedReader(new InputStreamReader(socket.getInputStream()));} catch (IOException e1) {e1.printStackTrace();}while(true){msg=bfr.readLine();if(TcpClient.ENDCONN.equals(msg)){
//              sp(this+" recieved ENDCONN");break;}
//          sp(msg);pw.println(msg+" : responsed");pw.flush();}socket.close();return "done :"+socket;}}

网络接口

NetworkInterface 实际指的是网络设备,包括硬件和软件模拟的,比如本地网络环回(lo)就是一个操作系统虚拟的网络设备。
NetworkInterface类提供Java访问本地NetworkInterface的工具,通过它,可以查询比如MAC地址,接口是否物理/虚拟,当前传输MTU值等等有价值的硬件信息,它还有一个很便捷的方法NetworkInterface getByInetAddress(InetAddress addr):可以查询绑定了指定IP地址的网络接口。

高级 API

URI

Uniform Resource Identifier 统一资源标识符,是表示一个网络中资源的标识字符串,这种标识指定了某种协议以便使用者通过合适的方式使用。
URI由URL(地址)和URN(名称)组成,常见的URI有不透明URI和分层URI
比如mailto:java-net@java.sun.com urn:isbn:096139210x 就是不透明URI,其特点是方案定义部分不以’/’开始,其结构可以表示为:[scheme:]scheme-specific-part[#fragment]
而更常见的是分层URI,http://java.sun.com/j2se/1.3/ docs/guide/collections/designfaq.html#28 ../../../demo/jfc/SwingSet2/src/SwingSet2.java 等都是分层URI,分层 URI 还要按照下面的语法进行进一步的解析:[scheme:][//authority][path][?query][#fragment]

Java.net中的URI类提供了构造和解析URI的方便工具,可以通过字符串解析URI的各个部分,也可以通过已有URI构建新的URI。最后,可以把从URI提取URL来使用,这也是最常用的。

URL

Uniform Resource Location 统一资源定位符 ,它是指向互联网“资源”的指针。URL是URI的定位部分,他们之间可以用toURI() 和toURL() 方法相互转换 。
URL 可选择指定一个“端口”,它是用于建立到远程主机 TCP 连接的端口号。如果未指定该端口号,则使用协议默认的端口。例如,http 协议的默认端口为 80。还可以指定一个备用端口,用.au:端口号

Java.net中的URL类除了像URI一样可以解析和构造(解析和构造也可以使用URLDecoder和URLEncoder)以外,特别的,它提供了一个极其方便的方法 openConnection()返回一个URLConnection对象,这个方法通过反射查询当前jre支持的协议,如果支持就打开一个协议连接,然后就可以直接操作了。

URLConnection

这里是一个打开HttpURLConnection的例子:

            URL url=new URL("http://www.java.com");URLConnection conn=url.openConnection();BufferedReader bfr=new BufferedReader(new InputStreamReader(conn.getInputStream()));String str;while((str=bfr.readLine())!=null){sp(str);}
协议处理程序

Java中不仅可以直接使用系统的协议处理程序打开连接,也可以自定义协议处理程序,只需要继承URLStreamHandler抽象类即可。

Java.nio 中的网络相关

@Since Java 1.4
Java1.4中加入了新的IO体系(JSR 51),包括面向缓冲区的各种Buffer对象,双向连接的Channel,Selector模式的多路复用。
在Java1.7中,nio又得到了补充(JSR 203),包括更多的文件系统操作API(包括可插拔的自定义的文件系统), 还提供了对socket和文件的异步(Async) I/O操作。

用Async方法实现异步网络服务

下面是一个基于异步非阻塞模式的服务器简单例子,双方仅仅是简单的进行几十次字符串传递即关闭连接。


import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.*;import static cc.sisel.util.Quic.*;/*** @author lz**/
public class AsyncTcpDemo {public static void main(String[] args) throws IOException,InterruptedException, ExecutionException {timeMark();InetSocketAddress servAddr = new InetSocketAddress("localhost", 22333);// start servernew Thread(new Runnable() {@Overridepublic void run() {new AsyncServer(servAddr.getPort(), 100).start();// blocking server main thread to keep async alivewhile (true) {try {Thread.sleep(Integer.MAX_VALUE);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();// wait server initts(300);Random r = new Random();// 5000 clientsfor (int i = 0; i < 5000; i++) {ts(10);new Thread(new AsyncClient(servAddr, r.nextInt(50) + 10)).start();}sp("ALL DONE");}}class AsyncServer {private AsynchronousServerSocketChannel servsc;private final int port, backlog;private boolean started;public AsyncServer(int port, int backlog) {super();this.port = port;this.backlog = backlog;init();}public void start() {// start by accept a connection channelservsc.accept(null, new AcceptCompletionHandler());this.started = true;}private void init() {// build async groupAsynchronousChannelGroup asyncGroup = null;try {// async thread poolasyncGroup = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 10);} catch (IOException e) {e.printStackTrace();}// open serversockettry {this.servsc = AsynchronousServerSocketChannel.open(asyncGroup);} catch (IOException e) {e.printStackTrace();}// config addr resuse & tcp recieve buffertry {this.servsc.setOption(StandardSocketOptions.SO_REUSEADDR, true);this.servsc.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);} catch (IOException e) {e.printStackTrace();}// bind to port ;ip= 0.0.0.0 for everyonetry {this.servsc.bind(new InetSocketAddress("0.0.0.0", this.port),this.backlog);} catch (IOException e) {e.printStackTrace();}}public void pendingAccept() {// after accepted channel reaccept cycliclyif (this.started && this.servsc.isOpen()) {servsc.accept(null, new AcceptCompletionHandler());} else {throw new IllegalStateException("Controller has been closed");}}// accept complete event handlerclass AcceptCompletionHandler implementsCompletionHandler<AsynchronousSocketChannel, Object> {final ByteBuffer buffer = ByteBuffer.allocate(1024);@Overridepublic void completed(AsynchronousSocketChannel channel,Object attachment) {new ASession(channel, AsyncServer.this).start();}@Overridepublic void failed(Throwable exc, Object attachment) {System.out.println("failed: " + exc);pendingAccept();}}}/*** server session handle it's read & write* * @author lz**/
class ASession {private AsynchronousSocketChannel channel;private AsyncServer server;private final ByteBuffer buffer = ByteBuffer.allocate(1024);private WriteCompletionHandler writeh;private ReadCompletionHandler readh;public ASession(AsynchronousSocketChannel channel, AsyncServer server) {this.channel = channel;this.writeh = new WriteCompletionHandler();this.readh = new ReadCompletionHandler();this.server = server;}public void start() {channel.read(buffer, null, readh);}class WriteCompletionHandler implements CompletionHandler<Integer, Object> {@Overridepublic void completed(Integer result, Object attachment) {if (channel.isOpen()) {buffer.clear();channel.read(buffer, 20, TimeUnit.SECONDS, null, readh);}}@Overridepublic void failed(Throwable exc, Object attachment) {sp("########################## WRITE FAIL IN SERVER");exc.printStackTrace();}}class ReadCompletionHandler implements CompletionHandler<Integer, Object> {@Overridepublic void completed(Integer result, Object attachment) {buffer.flip();String msg = readBuffer(buffer);// sp("server recieved:" + msg);buffer.clear();// if ENDCODE then close session and pending server nextif (AsyncClient.ENDCODE.equals(msg)) {if (channel.isOpen()) {try {channel.close();} catch (IOException e) {e.printStackTrace();}}server.pendingAccept();} else {// write responseif (channel != null && channel.isOpen()) {channel.write(ByteBuffer.wrap((msg + " responsed.").getBytes()),10, TimeUnit.SECONDS, null, writeh);}}}@Overridepublic void failed(Throwable exc, Object attachment) {sp("########################## READ FAIL IN SERVER");exc.printStackTrace();}}
}/*** client emualtor send simple message & recieve* * @author lz**/
class AsyncClient implements Runnable {public static final String ENDCODE = "&#$$#&$$";private final InetSocketAddress serverAddr;private int chatCount;private AsynchronousSocketChannel client = null;private final ByteBuffer buffer = ByteBuffer.allocate(1024);// event handlesprivate ConnectCompletionHandler connecth;private WriteCompletionHandler writeh;private ReadCompletionHandler readh;private NullCompletionHandler endh;public AsyncClient(InetSocketAddress serverAddr, int chatCount) {super();this.serverAddr = serverAddr;this.chatCount = chatCount < 1 ? 1 : chatCount;this.connecth = new ConnectCompletionHandler();this.writeh = new WriteCompletionHandler();this.readh = new ReadCompletionHandler();this.endh = new NullCompletionHandler();}@Overridepublic void run() {try {client = AsynchronousSocketChannel.open();} catch (IOException e) {e.printStackTrace();}// launch connif (client != null && client.isOpen()) {client.connect(serverAddr, null, connecth);}}class ConnectCompletionHandler implements CompletionHandler<Void, Object> {@Overridepublic void completed(Void result, Object attachment) {buffer.clear();if (chatCount > 0) {ts(300);if (client.isOpen()) {client.write(ByteBuffer.wrap(("message:" + chatCount).getBytes()), 10, TimeUnit.SECONDS, null, writeh);chatCount--;}} else {if (client.isOpen()) {client.write(ByteBuffer.wrap(ENDCODE.getBytes()), 10,TimeUnit.SECONDS, null, endh);}}}@Overridepublic void failed(Throwable exc, Object attachment) {sp("########################## CONNECT FAIL IN CLIENT");ts(300);client.connect(serverAddr, null, connecth);exc.printStackTrace();}}class WriteCompletionHandler implements CompletionHandler<Integer, Object> {@Overridepublic void completed(Integer result, Object attachment) {if (client.isOpen()) {buffer.clear();client.read(buffer, 20, TimeUnit.SECONDS, null, readh);}}@Overridepublic void failed(Throwable exc, Object attachment) {sp("########################## WRITE FAIL IN CLIENT");exc.printStackTrace();}}class ReadCompletionHandler implements CompletionHandler<Integer, Object> {@Overridepublic void completed(Integer result, Object attachment) {if (client.isOpen()) {buffer.flip();String msg = readBuffer(buffer);// sp("client recieved :" + msg);buffer.clear();if (chatCount > 0) {// ts(300);client.write(ByteBuffer.wrap(("message:" + chatCount).getBytes()), 10, TimeUnit.SECONDS, null, writeh);chatCount--;} else {client.write(ByteBuffer.wrap(ENDCODE.getBytes()), 10,TimeUnit.SECONDS, null, endh);}}}@Overridepublic void failed(Throwable exc, Object attachment) {sp("########################## READ FAIL IN CLIENT");exc.printStackTrace();}}
}class NullCompletionHandler implements CompletionHandler<Integer, Object> {@Overridepublic void completed(Integer result, Object attachment) {//just do nothing}@Overridepublic void failed(Throwable exc, Object attachment) {//just do nothing}}

附:
- sp和ts方法,偷懒用:

/*** 简单的在控制台输出 对于非数组类型,输出.toString() 对于数组类型,输出:类型[内容] 不递归* * @param o*            被打印的对象*/public static void sp(Object o) {if (o == null) {System.out.println("null");return;}if (o.getClass().isArray()) {StringBuilder sb = new StringBuilder();int len = Array.getLength(o);sb.append(o.getClass().getComponentType().getSimpleName());if (len == 0) {sb.append("[]");System.out.println(sb.toString());return;}sb.append('[');for (int i = 0; i < len; i++) {if (i != 0) {sb.append(':');}sb.append(Array.get(o, i));}sb.append(']');System.out.println(sb.toString());} else {System.out.println(o);}}/*** 简单的换行 调用sp("");*/public static void sp() {sp("");}/*** !!仅用于test 或者 demo 简单的包装了Thread.sleep(millis); 并catch* (InterruptedException e)不作任何处理* * @param millis 毫秒数*            @see java.lang.Thread#sleep(long millis)*/public static void ts(long millis) {if(millis<0){return;}try {Thread.sleep(millis);} catch (InterruptedException e) {e.printStackTrace();}}

这篇关于黑马程序员-JAVA.net-网络工具类粗解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/563387

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n