`
ZHH2009
  • 浏览: 123971 次
  • 性别: Icon_minigender_1
  • 来自: 天堂
文章分类
社区版块
存档分类
最新评论

Without SSH/JSP/Servlet,不走寻常路,Java可以更酷

阅读更多
标题的构思来源于Rod Johnson的那本"Without EJB"以及CCTV5中一句耳熟能详的广告词,
不过此文并不是用来批判SSH(Struts、Spring、Hibernate)/JSP/Servlet的,
也不是为某品牌做广告,而是用来分享这将近一年来的研究心得。

去年圣诞节时曾在JavaEye发过一两篇文章,不过现在找不到了,
文章内容提到要在3个月左右的时间内设计出一个有别于SSH的新型MVC框架,
设计的起点最初是以JSP/Servlet为基础的,虽然在两个多月后有了个雏形,
但是跟Rails这样的框架相比还是没有明显的优势,
比如在不使用反射的情况下,
很难将不同的uri对应到Servlet类中的public方法。
(Servlet类指的是继承自javax.servlet.http.HttpServlet的类)
每次修改Servlet类的源代码时总得经过烦人的手工编译步骤(有时还不得不重启Tomcat),
还有与数据库打交道的模型层也得人工干预,一堆烦人的映射配置。

那三个月内时常有沮丧感,似乎已走近了死胡同!
后来心一狠,决心甩开JSP/Servlet那一堆条条框框,把设计的起点再往下深一个层次。
因为2007年曾详细研究过Java语言的编译器(javac)实现细节,所以从编译器着手,
但是编译器的强项在于分析Java源代码,无法处理Http请求,
接着在网上把Tomcat6的源代码下下来研究了三个月,
期间顺便研究了Sun公司的超轻量级Http服务器"com.sun.net.httpserver"的源代码,
同时详细学习HTTP/1.0(RFC1945)与HTTP/1.1(RFC2616)协议。

但是Tomcat6过于臃肿了,包含的Java文件超过了1300个,
光是解析server.xml与web.xml的代码看完后就让人有烦躁感。
(如org\apache\tomcat\util\digester与org\apache\catalina\startup包中的很多类)

另外最重要一点,Tomcat6采用的是Eclipse JDT编译器,仅仅是用来编译JSP文件,
编译器在控制层没有发挥一点作用。
而Sun公司的超轻量级Http服务器又过于简单了,连HTTP/1.1的大多数功能都没实现,
除了参考一下它的SSL实现外基本上毫无价值。

本想在现有的JSP/Servlet容器上做一下简单扩展就得了,
哪知也是四处碰壁(还下过Jetty的源代码下来看了一会,结果发现比Tomcat6还糟),
后来决定对Tomcat6与Sun的Http服务器进行大刀阔斧的改造,
完成了一个精简版的改良后的基于NIO的Http服务器(目前的版本只有60个左右的Java源文件),
并且能跟Javac编译器完美结合,能直接运行Java源文件。

在模型层这一块,最初是从书上和网络上对Hibernate进行应用层次的研究,
但是并不想深入源代码,因为代码量也实在是太多了,倒是对Ibatis2.0深入研究了一下,
Ibatis2.0代码量比较少,也简单,看了不到一星期就基本上看完了,不过现在并没留下深刻映象,
因为并没发现什么特别出彩的地方,Ibatis2.0还是离不开xml,而我想要完全抛弃xml。

当然,不管Hibernate也好,Ibatis2.0也好,相比Rails的ActiveRecord还是逊色了点,
不过我的目标并不是要造一个Hibernate、Ibatis2.0或ActiveRecord这样的轮子,
我的要求更高,我在想如何才能写更少的代码,如何才能实现自动化?
可不可以在服务器启动时或运行时动态解析数据库的元数据,
让编译器跟据这些元数据动态生成类呢?
接着我转去研究JDBC-1.2/JDBC-2.1/JDBC-3.0/JDBC-4.0规范,研究数据库驱动的开发手册。
我得从零开始,我目前的实现是这样做的:你可以在你自己的Java源文件中直接引用动态生成的类,
就像这些类是你自己写的一样,ORM已基本上实现自动化了,2.9 节专门讲Douyu的ORM。

最后一点值得一提的是,我在Java语言层次引入了权限管理模型,
不过你别担心,我并没有引入新的Java语言语法,
只是借助Annotation扩充了某些特殊的语义。
目前这个权限管理模型的粒度只是划分为功能、字段权限两个等级,
并没有实现与具体业务相关的数据权限,不过在未来的路线图中有打算引入工作流模型,
到时会努力尝试各种实现数据权限的方案。

与权限相关的细节请看2.8节 Douyu的权限模型



折腾了半年后,发现已不再是个MVC框架了,我想称为平台更合适,
一种运行在JVM之上的新型平台,我给她起了个名字: Douyu
(呵呵,名字的由来暂时保密,也许你能猜出来。。。)



虽然孤军奋战将近一年,自我感觉小有成就,但是还有很多不怎么满意的地方,
各位大牛们也许更牛,看见不爽砸砖头便是。



Ok,上干货。




1. 安装配置


(这里只针对Windows平台,特别是XP操作系统,因为我没其他试验环境)



1.1 安装JDK


Douyu是在JDK1.6下开发的,不支持也不打算支持JDK1.4及更早的版本,JDK1.5我没有测试过,
所以我只能推荐你安装JDK1.6了,安装细节我想你都会,
唯一要注意的一点是:最好是建个JAVA_HOME环境变量,然后把%JAVA_HOME%\bin加入到Path中,
因为在Douyu服务器的启动脚本中并没有进行过多的环境检测,
而是直接使用了%JAVA_HOME%\bin目录下的java命令来启动Java HotSpot VM。


1.2 安装Douyu服务器

Douyu项目主页目前放在:
http://code.google.com/p/douyu/

请先下载二进制版的压缩文件:
http://douyu.googlecode.com/files/Douyu_0_1_0.rar

目前的版本是:0.1.0,版本号很小,但大多数功能都包含了,
我并不推荐你用于工业级别的产品开发,
因为还不稳定,目前只适合分享、交流、尝鲜目的。

下下来后直接解压到一个你选定的目录(假定你解压到了D:\Douyu目录)

D:\Douyu目录里头有下面7个目录(跟Tomcat6差不多):
apps  //应用程序的源代码放在这里,里头有一些java源文件是下面的演示中用到的,当然你可以全都删了。
bin   //服务器的启动脚本和运行时类库都在这里
conf  //服务器的配置文件放在这里
lib   //应用程序使用到的第三方类库(比如数据库驱动)都放在这里,初始情况下是个空目录
logs  //存放服务器运行期间的日志(目前日志只是输出到控制台),初始情况下是个空目录
temp  //服务器运行期间用到的临时文件夹(比如上传文件时可能会用到),初始情况下是个空目录
work  //服务器运行期间的工作目录,初始情况下是个空目录

了解了这些就足够了,目前你不需要做任何配置。







2. 体验Douyu



2.1 如何运行Douyu服务器?


点"开始->运行",输入cmd,打开一个控制台,切换到D:\Douyu\bin目录,
然后输入 douyu  启动Douyu服务器 (要关闭Douyu服务器连按两次Ctrl+C既可)
见下图:



如果你是第一次打开操作系统第一次启动JVM运行Java程序
或是隔了一个小时左右重新启动JVM运行Java程序,这时可能要等待几秒钟(5--10秒),
出现这种情况并不是Douyu服务器的问题,而是JVM本身或操作系统的问题,
通常启动Douyu服务器如果不加载数据库的话,一般在一秒钟内就能启动完成了。

Douyu服务器默认情况下监听的主机名是: localhost,端口: 8000

如果你不喜欢这样的默认配置,
或者最常见的情况是端口8000被占用了
(一般抛出异常: java.net.BindException: Address already in use)
你可以打开conf\server.java这个服务器配置文件,
配置文件本身就是一个java源文件,参数的配置使用Java语言的Annotation语法,
所有与服务器配置有关的都是Annotation或是Enum,全都在com.douyu.config包中定义。
import com.douyu.config.*;

@Server(
	port=8000,
	.................



要修改默认主机名和端口,请修改hostName和port的值,
hostName是一个字符串,可以用IP地址来表示,port是一个整型(int)值。


其他很多参数先不罗列了,使用到时再详细说明。


当你修改了conf\server.java后,你也不需要自己去手工编译它,
启动Douyu服务器时,Douyu会自行决定是否要编译它。
如果conf\server.java存在语法错误,那么编译失败,
Douyu服务器的启动也会失败,同时向你显示编译错误信息。



下文中假定Douyu服务器已启动,监听的主机名是: localhost,端口是: 8000
以下所有例子都经过严格测试了,

我的JRE版本:
D:\Douyu\bin>java -version
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode, sharing)

测试浏览器用了两个:

傲游浏览器(IE6.0),
谷歌浏览器(Chrome 3.0.195.27)





2.2 Hello World!



2.2.1 程序代码


//对应apps\HelloWorld.java文件

import java.io.PrintWriter;
import com.douyu.main.Controller;

@Controller
public class HelloWorld {
	public void index(PrintWriter out) {
		out.println("Hello World!");
	}
}


2.2.2 手工编译已经Out了,你再也不需要这一步了。


2.2.3 运行HelloWorld

打开你心爱的浏览器,输入 http://localhost:8000/HelloWorld
如果你能看到下图中所示内容,恭喜你,你己经进入了Douyu的精彩世界。



(注:这是你第一次直接运行Java源文件,可能会等几秒钟(2--4秒),因为Douyu得初始化编译器)


2.2.4 程序代码说明

com.douyu.main包中的类大多数是Annotation,还包含一些重要的接口和类,
相当于java.lang,是你用Douyu开发程序时最常用到的,也是通往其他模块的快速入口,
本想让com.douyu.main包中的类像java.lang一样让编译器自动导入的,
但是考虑到很多开发人员更偏爱使用IDE,不同IDE内置的编译器不一样,
从而会引起找不到com.douyu.main包中的类的问题,所以最后决定放弃这样的设计了。

@Controller 这个Annotation是用来告诉Douyu这是一个控制器,
当你在浏览器的地址栏中输入http://localhost:8000/HelloWorld 这样的uri时,
浏览器内部通常会生成一个HTTP GET请求消息,消息内容类似这样:
GET /HelloWorld HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,......
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon)
Host: localhost:8000
Connection: Keep-Alive

不过这里并不打算介绍HTTP协议,如果你有兴趣,可以把RFC2616下下来研究。

Douyu服务器收到浏览器发来的请求消息后,
特别留意 "GET /HelloWorld HTTP/1.1" 这一行消息,
其中的"/HelloWorld"表示想要获取Douyu服务器上的哪些资源,
资源有静态的(如html、jpg等文件),也有动态的,在Douyu服务器中动态资源只有一种,
凡是带有@Controller这个Annotation的Java源文件都是可以直接通过uri访问的动态资源。

不过Douyu服务器不能根据uri的表面特征一眼就看出它是动态的还是静态资源,
服务器内部有一个专用的资源装载器,装载器的搜索根目录是从apps这个地方开始的,
资源装载器会尝试将apps目录与uri组合成一个java.io.File对象,
如果File对象存在,那么它就是一个静态资源,
然后由Douyu服务器内部的静态资源处理器给浏览器发送包含有文件内容的响应消息;

如果File对象不存在,资源装载器把请求的uri当成一个类名,
然后尝试采用类装载器的方式装载类,如果找不到那么就直接返回未找到(404)消息;
如果找到了,并且uri是第一次请求的,资源装载器会返回java源文件,
然后把java源文件交给Douyu服务器内置的编译器处理,编译器的处理过程很复杂,
这里就不深入说明了,总之它会为你动态生成HelloWorld的实例,
然后调用它的index这个缺省的public方法,
之后调用out.println()方法把"Hello World!"发送给浏览器。
  • 大小: 27.3 KB
  • 大小: 8.7 KB
  • 大小: 14.8 KB
  • 大小: 13.2 KB
  • 大小: 13.4 KB
  • 大小: 11.1 KB
  • 大小: 20.4 KB
  • 大小: 27.3 KB
  • 大小: 63.7 KB
  • 大小: 75.4 KB
  • 大小: 14.7 KB
  • 大小: 22.6 KB
  • 大小: 22.4 KB
  • 大小: 22.8 KB
  • 大小: 24.4 KB
  • 大小: 23.9 KB
  • 大小: 28.5 KB
  • 大小: 36.9 KB
  • 大小: 24.1 KB
  • 大小: 52.6 KB
  • 大小: 77.3 KB
  • 大小: 101.3 KB
  • 大小: 54.2 KB
  • 大小: 122 KB
分享到:
评论
2 楼 ZHH2009 2009-11-15  

2.4 神奇的Action



2.4.1 程序代码


//对应apps\SupernaturalAction.java文件

import com.douyu.main.Context;
import com.douyu.main.Controller;

@Controller
public class SupernaturalAction {
	public void index(Context context) {
		context.out("User.html");
	}

	public void showUser(User user, java.io.PrintWriter out) {
		out.println("姓名:"+user.name);
		out.println("年龄:"+user.age);
	}
}



//对应apps\User.java文件

import com.douyu.main.Form;
import com.douyu.main.Setter;

@Form
public class User {
	String name;
	int age;

	@Setter
	public void init(String name, int age) {
		this.name = name;
		this.age = age;
	}
}


//对应apps\User.html文件

<HTML>
<HEAD><TITLE>User</TITLE></HEAD>
<BODY>
<FORM METHOD=POST ACTION="SupernaturalAction/showUser">
	姓名:<INPUT TYPE="text" NAME="name"><br>
	年龄:<INPUT TYPE="text" NAME="age"><br>
	<INPUT TYPE="submit">
</FORM>
</BODY>
</HTML>



2.4.2 运行 SupernaturalAction


打开浏览器,输入 http://localhost:8000/SupernaturalAction
结果类似这样:




填写完表单,点击提交按钮后的结果:




2.4.3 程序代码说明


上面的代码所完成的功能很简单: 先显示一个User表单让你填写,然后输出你填写的内容。
不过这不是我的主要用意,我的意图是想通过这个非常简单的例子向你说明什么是"Action"?

Action其实就是一个方法,如果一个类带有@Controller 那么在这个类中定义的所有public方法
都是一个Action,你可以通过"类名/方法名"这样的uri来访问这个Action,
例如上面apps\User.html文件中的ACTION="SupernaturalAction/showUser"就表示由SupernaturalAction中
的showUser方法来处理表单。

如果你在uri中未指明方法名,比如http://localhost:8000/SupernaturalAction,
那么就会调用默认的index方法,
http://localhost:8000/SupernaturalAction
与 http://localhost:8000/SupernaturalAction/index 是等价的。

如果你不喜欢index这个默认的方法名,而是喜欢main这样的方法名
你可以把 @Controller 改成 @Controller(defaultAction="main")


另外一个很神奇的地方在于方法声明中的参数,
如果你是一个很细心的人你可能早已发现了一件有趣的事,
前面三小节给出的示例中每个Controller类中都有index方法,但是方法的参数是不同的,
再列出来对比一下:

第1个例子是: index(PrintWriter out)
第2个例子是: index(String name, Context context)
第3个例子是: index(Context context)

如果你学习过Sun发明的Servlet技术,你应该对下面这两个方法很熟悉:
doPost(HttpServletRequest req, HttpServletResponse resp)
doGet(HttpServletRequest req, HttpServletResponse resp)


前者的方法参数类型、个数、顺序都是活的,是由正在写程序的人自己定的,
而后者都是死的,是由Sun在规范中事先定好的,你只能去覆盖doPost、doGet。

通俗一点来讲就是:
主动权在我,要由我说的算,我要什么你就得给我什么;
而不是我去顺从你,你有什么我只能用什么。


能达到这样的灵活性要归功于强大的编译器,
编译器在编译源代码时会根据Douyu服务器运行期间的上下文信息推断出你想要做什么?
比如你想要一个PrintWriter,那么就给你一个能向浏览器输出信息的PrintWriter,
你想要一个Context,那么就把代表上下文的Context实例传给你,
你想要获取某一个Http请求参数值(如上面的String name)也同样满足你。


接着再来看看showUser的参数声明:
showUser(User user, java.io.PrintWriter out)

唯一陌生的地方是:User user,
请先回过头去看看apps\User.java文件的内容,
如果你熟悉JavaBeans,那么一定写过一堆的setter/getter方法吧,
User类有点类似JavaBeans,但又不大一样。

如果你给一个类加上 @Form 这个Annotation,然后你把这个类作为Action方法参数的类型,
那么编译器就会推断出你想要把Http请求参数值自动装配到这个类的实例变量中,
接着编译器就会在这样的类中继续寻找所有带有 @Setter 的public方法,
然后解析方法参数,这一步跟解析Action方法参数一样,
但是在这一步会忽略掉所有的带有@Form 类型的其他参数。
(比如,要是像这样:init(String name, int age, User user),那么直接给user变量赋 null 值)


下面的代码片断:
	@Setter
	public void init(String name, int age) {
		this.name = name;
		this.age = age;
	}

就是最关键的地方,
它告诉编译器:把名叫"name"和"age"的参数值准备好,然后调用init。

参数的名称很重要,必须跟html表单中一样,否则会找不到实际的值,只能给你null或者0这样的默认值。

不过,你也不必担心,通常每个表单在实际应用中都对应数据库中的一张表,
Douyu已经考虑到这个问题了,已将模型层和控制层完美结合,
几乎可以实现自动化了(不过不是采用@Setter方式),
所以通常你不必另外写一个对应html表单的类。
1 楼 ZHH2009 2009-11-15  

2.3 控制器层与视图层的协作


2.3.1 程序代码


//控制器层的代码
//对应apps\WhatTime.java文件

import java.util.Date;
import java.util.HashMap;

import com.douyu.main.Context;
import com.douyu.main.Controller;

@Controller
public class WhatTime {
	public void index(String name, Context context) {
		HashMap<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("name",name);

		context.out("WhatTime.html", paramMap, new ParamWrapper());
	}

	public static class ParamWrapper {
		Date time = new Date();
	}
}


//视图层的代码
//对应apps\WhatTime.html文件

<HTML>
<HEAD><TITLE>现在几点了?</TITLE></HEAD>
<BODY>
你好: ${name}, 现在的时间是: ${time}
</BODY>
</HTML>



2.3.2 运行 WhatTime

打开浏览器,输入 http://localhost:8000/WhatTime?name=Douyu
结果类似这样:




2.3.3 程序代码说明

WhatTime类的功能很简单: 就是提供报时服务。
index方法与第一个例子有所不同,第一参数用来接收请求uri中的name参数值,
第二个参数的类型是Context,它是一个接口,在com.douyu.main包中定义。
Context是最核心的接口,定义了很多重要的方法,
不过这里只介绍out(String template, Object... paramWrappers)方法。
out方法是控制器层与视图层通信的唯一通道。

先来看这一行代码:
context.out("WhatTime.html", paramMap, new ParamWrapper());
上面的WhatTime.html文件就相当于一个模板文件,对应out方法的第一个参数,
WhatTime.html模板文件中的${name}与${time}表示一些占位标记,
意思是告诉控制器:在把我的内容发送到浏览器前,先把这些占位标记提换成实际的参数值。

实际的参数值从哪里取呢?我想你早就看出来了: 从paramWrappers这个可变数组中取。
比如上面那行代码中的paramMap和new ParamWrapper()都可以称为参数包装器,
参数包装器可以是一个Map,也可以是一个普通的类。

如果你在调用out方法时不提供任何参数包装器,那么不会对任何占位标记进行替换,
这种情形通常适用于直接发送静态资源文件。

如果你在调用out方法时提供了多个参数包装器,
那么参数值的查找顺序是按调用out方法时参数包装器出现的先后顺序进行的,
比如上例中,在替换${name}这个占位标记时,先从paramMap中查找(类似这样:paramMap.get("name")),
因为name的值已经在
paramMap.put("name",name);
这一行代码中加入了,所以查找成功,不再往下进行。

当替换${time}这个占位标记时,也是先从paramMap中查找(类似这样:paramMap.get("time")),
但是返回null,接着从new ParamWrapper()这个参数包装器中查找,
控制器识别出ParamWrapper类不是一个Map,所以采用反射技术,事先查找是否定义了time()方法,
因为ParamWrapper类没有定义time()方法,所以再查找是否定义了名叫time的实例变量,
最后找到了,time这个实例变量是Date类型,把它转换成字符串后替换${time}这个占位标记,
最后就可以把模板文件的内容发送给浏览器了。

相关推荐

    《Java Servlet编程(第二版)》英文版 chm (含源码)

    The Java 2, Enterprise Edition (J2EE), specification has included servlets as a core component, and application server vendors wouldn't be caught dead without a scalable servlet implementation....

    test-servlet3-without-webxml.rar

    综上所述,`test-servlet3-without-webxml.rar`文件提供了关于Servlet 3.0无web.xml配置的实践案例,通过学习和分析这个项目,开发者可以深入理解Servlet 3.0的新特性和优势,提升Java Web开发技能。

    SSH移植到android系统步骤.doc

    SSH移植到Android系统步骤 SSH(Secure Shell)是一种安全的远程登录协议,常用于Linux系统中。但是,Android系统并不具备SSH功能,这篇文章将讲述如何将OpenSSH移植到Android系统中。 Step 1: 获取OpenSSH源码 ...

    Hadoop ubuntu 9.10 下的 SSH 免登陆

    4. **配置SSH**:编辑`/etc/ssh/sshd_config`文件,确保`PermitRootLogin`设置为`without-password`或`no`,以禁止root用户通过密码登录。同时,确认`PubkeyAuthentication`设置为`yes`,启用公钥认证。 5. **重启...

    Servlet查询数据库案例--Query(java源码)

    * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you...

    批量配置服务器ssh免密rsa登录

    免密登录是SSH的一种功能,通过公钥认证方式,用户可以在不输入密码的情况下登录远程服务器,极大地方便了多服务器管理和自动化运维。 标题“批量配置服务器ssh免密rsa登录”所涉及的知识点主要包括: 1. **RSA...

    openssh 9.9p1 el8(redhat/centos el8 x86-64)

    安装前,可以多开几个ssh窗口,也可以开启telnet服务,防止意外中断无法访问服务器 rpm -e openssh --nodeps rpm -e openssh-server --nodeps rpm -e openssh-clients --nodeps rpm -e openssh-askpass --nodeps ...

    openssh-server -Ubuntu18.04远程服务离线安装包

    依次运行下面命令进行安装: sudo dpkg -i openssh-client_1%3a7.6p1-4ubuntu0.6_amd64.deb sudo dpkg -i ncurses-term_6.1-1ubuntu1.18.04_all.deb ... 删除permitRootLogin后面的without-password后改为yes

    SSH无密码登录配置(主要针对Hadoop配置)

    SSH(Secure Shell)是一种网络协议,用于在不安全的网络上提供安全的远程登录和其他服务。在Hadoop这样的分布式计算环境中,SSH无密码登录配置至关重要,因为它简化了节点间的通信,提高了运维效率。以下是关于SSH...

    Redis-desktop redis管理工具 支持SSH 无bug版

    在这个特定版本中,开发者声称已经解决了所有已知的bug,这意味着用户可以享受到更稳定、更流畅的使用体验。 描述中的"支持SSH,SSL,Advanced settings"进一步揭示了这款工具的功能特性。除了SSH,它还支持SSL...

    ssh服务安装软件及其操作步骤.zip

    在Linux系统中,SSH(Secure Shell)是一种网络协议,用于安全地远程登录到服务器,执行命令,传输文件等。SFTP(Secure File Transfer Protocol)是SSH的一部分,提供了一个安全的文件传输机制。在这个名为"ssh服务...

    三大技术javaBean+servlet+jsp常见问题和解决方案

    在 JSP 页面中使用 `&lt;c:when&gt;` 标签时,如果没有将其放在 `&lt;c:choose&gt;` 标签的直接子元素中,则会抛出 `javax.servlet.ServletException: Illegal use of &lt;when&gt;-style tag without &lt;choose&gt; as its direct parent` ...

    servlet2.4doc

    Overrides the standard java.lang.Object.clone method to return a copy of this cookie. containsHeader(String) - Method in class javax.servlet.http.HttpServletResponseWrapper The default behavior of ...

    Ubuntu 16.04远程登录服务器ssh的安装和配置.pdf

    在 Ubuntu 16.04 中,默认情况下已经安装了 openssh-client,为了避免与 openssh-server 不匹配,需要卸载原有的 ssh-client 和 ssh-server,然后重新安装 openssh-server 和 openssh-client。 卸载原有的 ssh-...

    OpenSSH 9.3 CentOS7 RPM安装包

    基于centos7编译的openssh9.3的安装包,使用x11-ssh-askpass让openssh不在依赖openssl1.1.1。 更新前:注意备份好/etc/ssh和/etc/pam.d/ ,一般建议开启telnet增加一条备用登陆通道 更新操作:rpm -Uvh openssh-*....

    eclipse 反编译插件 java工具JadClipse

    eclipse 反编译插件 java工具JadClipse 将JadClipse插件(net.sf.jadclipse_3.3.0.jar)拷贝到{EclipseHome}/plugins文件夹下(如C:\Program F\eclipse-jee-kepler-R-win32-x86_64\eclipse\plugins)。JAD 解压到...

    FreeBSD 8.0 配置密钥登录

    - **PermitRootLogin**: 设置为`without-password`,表示root用户可以使用密钥认证登录,但不能使用密码登录。 下面是修改后的部分配置示例: ``` Protocol 2 RSAAuthentication yes PubkeyAuthentication ...

    Anolis8.x rpm升级openssh9.6

    在Linux系统管理中,安全是至关重要的,OpenSSH作为一个开源的Secure Shell (SSH)协议实现,为远程登录、文件传输等提供了加密保障。本话题主要关注如何在Anolis8.x操作系统上,通过RPM(Red Hat Package Manager)...

    java嵌入式tomcat[借鉴].pdf

    这些 Jar 包包括 Tomcat 的核心包、servlet-api.jar 和 javax.servlet.jsp-api.jar 等。这些 Jar 包可以从 Apache Tomcat 的官方网站下载。 接下来,在 src 目录下创建一个 conf 目录,用于存放 Tomcat 的配置文件...

    ubuntu16.04服务器配置ssh免密码登录

    SSH (Secure Shell) 是一种网络协议,用于在不安全的网络上安全地远程登录到Linux或Unix服务器。在Ubuntu 16.04系统中,配置SSH免密码登录可以简化管理任务,避免每次连接时输入密码的繁琐过程。以下是详细步骤和...

Global site tag (gtag.js) - Google Analytics