怎样借助Spring boot快速实现一个简单的http服务器
Spring Boot充分利用了JavaConfig的配置模式以及“约定优于配置”的理念,能够极大的简化基于Spring
MVC的Web应用和REST服务开发。
Spring
4倡导微服务的架构,针对这一理念,近来在微博上也有一些有价值的讨论,如这里和这里。微服务架构倡导将功能拆分到离散的服务中,独立地进行部署,Spring
Boot能够很方便地将应用打包成独立可运行的JAR包,因此在开发模式上很契合这一理念。目前,Spring
Boot依然是050的里程碑版本,因此相关的文档尚不完善,本文将会以一个简单的样例来介绍基于这个项目的开发过程。
要Spring
Boot进行功能开发,需要使用Gradle或者Maven作为构建工具。在本例中,我们会使用Eclipse和Maven插件进行开发。要使用Spring
Boot,首先创建一个Maven工程,并修改Maven主要的配置文件pomxml,如下所示:
orgspringframeworkboot
spring-boot-starter-parent
050M7
orgspringframeworkboot
spring-boot-starter-web
orgthymeleaf
thymeleaf-spring3
comlevinApplication
orgspringframeworkboot
spring-boot-maven-plugin
程序员10款必备工具抓紧掌握
01·Vim文本编辑器
优点:功能强大、高度可定制,Vi编辑器中最好的一个。
Vim是vi发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用,和Emacs并列成为类Unix系统用户最喜欢的文本编辑器。
02·uTools桌面插件工具
优点:简洁美观、插件化,能够节约时间。uTools 是一个极简、插件化的现代桌面软件,通过自由选配丰富的插件,打造得心应手的工具集合。
03·Git分布式版本控制系统
优点:分布式开发、速度快、灵活。Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。也是LinusTorvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。
04·Navicat数据库管理工具
优点:高效、安全,是最好用的数据库管理工具。“Navicat”是一套可创建多个连接的数据库管理工具,用以方便管理 MySQL、Oracle、PostgreSQL、SQLite、SQL Server、MariaDB 和 MongoDB 等不同类型的数据库,它与阿里云、腾讯云、华为云、Amazon RDS、Amazon Aurora、AmazonRedshift、Microsoft Azure、Oracle Cloud 和MongoDB Atlas等云数据库兼容
05·IntelliJ IDEA集成开发环境
优点:业界排名第一的java开发工具。IintelliJIDEA,是java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、创新的GUI设计等方面的功能可以说是超常的。
06·iTerm2终端管理器
优点:功能强大,一款终端神器。Term2 Mac版可以说是Mac下最好的终端工具。iTerm2拥有多标签、中键复制粘贴、命令记忆、高亮指针、迅捷重复、全屏切换等功能,提升操作效率。
07·Alfred查询和搜索工具
优点:被称作效率神器。
Alfred是 Mac系统上一款专注于效率提升的著名应用,它能帮你快速打开网页、快速进行自定义搜索查看剪贴板历史、快速查询单词等等。Alfred 提供的功能虽然很多,但目的只有一个 - 那就是减少我们工作中的一些重复动作,提升我们的工作效率。
08·Beyond Compare代码比较工具
优点:高效,适用于用于文档、源代码和HTMLoBeyond Compare可以很方便地对比出两份源代码文件之间的不同之处,相差的每一个字节用颜色加以表示,查看方便,支持多种规则对比。
09·Docker开源的应用容器引擎
优点:跨平台,跨服务器,实现应用程序跨平台间的无缝衔接。
Docker 其中包括,镜像、容器、仓库,很简单,目的就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的产品(可以是 web 应用或者数据库应用)及其环境能够做到“一次封装,到处运行”。
10·Postman接口调试与测试工具
优点:功能强大,使用简单且易用性好。Postman是一个简单好用的网页调试软件,很适合开发人员使用,性能稳定流畅,提供接口测试、并发测试等功能,还支持编写测试脚本,快速处理各种HTTP请求,测试数据精准高效。
通过轮询来实现长连接
轮询:隔一段时间访问服务器,服务器不管有没有新消息都立刻返回。
http长连接实现代码:
客户端:
package houleicsdnkeepalive;
import javaioIOException;
import javaioInputStream;
import javaioObjectInputStream;
import javaioObjectOutputStream;
import javanetSocket;
import javanetUnknownHostException;
import javautilconcurrentConcurrentHashMap;
/
C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。
<p>
创建时间:2010-7-18 上午12:17:25
@author HouLei
@since 10
/
public class Client {
/
处理服务端发回的对象,可实现该接口。
/
public static interface ObjectAction{
void doAction(Object obj,Client client);
}
public static final class DefaultObjectAction implements ObjectAction{
public void doAction(Object obj,Client client) {
Systemoutprintln("处理:\t"+objtoString());//诊断程序是否正常
}
}
public static void main(String[] args) throws UnknownHostException, IOException {
String serverIp = "127001";
int port = 65432;
Client client = new Client(serverIp,port);
clientstart();
}
private String serverIp;
private int port;
private Socket socket;
private boolean running=false;
private long lastSendTime;
private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
public Client(String serverIp, int port) {
thisserverIp=serverIp;thisport=port;
}
public void start() throws UnknownHostException, IOException {
if(running)return;
socket = new Socket(serverIp,port);
Systemoutprintln("本地端口:"+socketgetLocalPort());
lastSendTime=SystemcurrentTimeMillis();
running=true;
new Thread(new KeepAliveWatchDog())start();
new Thread(new ReceiveWatchDog())start();
}
public void stop(){
if(running)running=false;
}
/
添加接收对象的处理对象。
@param cls 待处理的对象,其所属的类。
@param action 处理过程对象。
/
public void addActionMap(Class<Object> cls,ObjectAction action){
actionMappingput(cls, action);
}
public void sendObject(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(socketgetOutputStream());
ooswriteObject(obj);
Systemoutprintln("发送:\t"+obj);
oosflush();
}
class KeepAliveWatchDog implements Runnable{
long checkDelay = 10;
long keepAliveDelay = 2000;
public void run() {
while(running){
if(SystemcurrentTimeMillis()-lastSendTime>keepAliveDelay){
try {
ClientthissendObject(new KeepAlive());
} catch (IOException e) {
eprintStackTrace();
Clientthisstop();
}
lastSendTime = SystemcurrentTimeMillis();
}else{
try {
Threadsleep(checkDelay);
} catch (InterruptedException e) {
eprintStackTrace();
Clientthisstop();
}
}
}
}
}
class ReceiveWatchDog implements Runnable{
public void run() {
while(running){
try {
InputStream in = socketgetInputStream();
if(inavailable()>0){
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = oisreadObject();
Systemoutprintln("接收:\t"+obj);//接受数据
ObjectAction oa = actionMappingget(objgetClass());
oa = oa==nullnew DefaultObjectAction():oa;
oadoAction(obj, Clientthis);
}else{
Threadsleep(10);
}
} catch (Exception e) {
eprintStackTrace();
Clientthisstop();
}
}
}
}
}
服务端:
package houleicsdnkeepalive;
import javaioIOException;
import javaioInputStream;
import javaioObjectInputStream;
import javaioObjectOutputStream;
import javanetServerSocket;
import javanetSocket;
import javautilconcurrentConcurrentHashMap;
/
C/S架构的服务端对象。
<p>
创建时间:2010-7-18 上午12:17:37
@author HouLei
@since 10
/
public class Server {
/
要处理客户端发来的对象,并返回一个对象,可实现该接口。
/
public interface ObjectAction{
Object doAction(Object rev);
}
public static final class DefaultObjectAction implements ObjectAction{
public Object doAction(Object rev) {
Systemoutprintln("处理并返回:"+rev);//确认长连接状况
return rev;
}
}
public static void main(String[] args) {
int port = 65432;
Server server = new Server(port);
serverstart();
}
private int port;
private volatile boolean running=false;
private long receiveTimeDelay=3000;
private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
private Thread connWatchDog;
public Server(int port) {
thisport = port;
}
public void start(){
if(running)return;
running=true;
connWatchDog = new Thread(new ConnWatchDog());
connWatchDogstart();
}
@SuppressWarnings("deprecation")
public void stop(){
if(running)running=false;
if(connWatchDog!=null)connWatchDogstop();
}
public void addActionMap(Class<Object> cls,ObjectAction action){
actionMappingput(cls, action);
}
class ConnWatchDog implements Runnable{
public void run(){
try {
ServerSocket ss = new ServerSocket(port,5);
while(running){
Socket s = ssaccept();
new Thread(new SocketAction(s))start();
}
} catch (IOException e) {
eprintStackTrace();
Serverthisstop();
}
}
}
class SocketAction implements Runnable{
Socket s;
boolean run=true;
long lastReceiveTime = SystemcurrentTimeMillis();
public SocketAction(Socket s) {
thiss = s;
}
public void run() {
while(running && run){
if(SystemcurrentTimeMillis()-lastReceiveTime>receiveTimeDelay){
overThis();
}else{
try {
InputStream in = sgetInputStream();
if(inavailable()>0){
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = oisreadObject();
lastReceiveTime = SystemcurrentTimeMillis();
Systemoutprintln("接收:\t"+obj);
ObjectAction oa = actionMappingget(objgetClass());
oa = oa==nullnew DefaultObjectAction():oa;
Object out = oadoAction(obj);
if(out!=null){
ObjectOutputStream oos = new ObjectOutputStream(sgetOutputStream());
ooswriteObject(out);
oosflush();
}
}else{
Threadsleep(10);
}
} catch (Exception e) {
eprintStackTrace();
overThis();
}
}
}
}
private void overThis() {
if(run)run=false;
if(s!=null){
try {
sclose();
} catch (IOException e) {
eprintStackTrace();
}
}
Systemoutprintln("关闭:"+sgetRemoteSocketAddress());//关闭长连接
}
}
}
长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。
如果,长时间未发送维持连接包,服务端程序将断开连接。
服务器端接收客户端的请求的话,需要在服务器端的java文件实现HttpServlet这个接口,并且在webxml里配置一个客户端的请求拦截。
webxml里的代码里添加
<servlet><servlet-name>testServlet</servlet-name><!--这个名字可以自己定-->
<servlet-class>comsuntestServlet</servlet-class><!--这里是你需要接收客户端请求的那个类以及包名,也就是下面拦截到的url会转发到的那个类-->
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name><!--和上面的name需要一样-->
<url-pattern>/</url-pattern><!--什么类型的客户端请求会被拦截,/ 就是全拦截了-->
</servlet-mapping>
然后再服务器端的类文件,要实现 HttpServlet这个接口。并把doGet()方法和doPost()方法重写。
这两种方法分别对应的是客户端的get请求和post请求的处理,你的是post请求的话,就在doPost()方法内,写你的业务。
然后再用下面两句话,设置你要返回客户端的数据。
//这是设置你要返回去的数据。value才是你的数据,key是标签。
requestsetAttribute("key", "value");
//这是设置你要返回去testjsp这张页面。
requestgetRequestDispatcher("testjsp")forward(request, response);
不知道你是不是这个意思,你可以再去看看相关servlet方面的知识,
关于客户端和服务器端大概也就是有个servlet作为请求的拦截
然后经过相关判断后,选择性的传到服务器的相应类里面。
再经过类里面的业务,把得到需要的数据回传到指定的页面上。
我觉得你这个问题的解决应该是你的程序做一次这个网站的登陆,而且这个登陆的动作应该是需要发生在你这段代码以前,因为你这段代码的动作其实只是访问了一下那个网站,但是没有任何的用户或者是其他的信息。
一般来说你登陆以后,你会获得一个token,用那个token就可以让网站认为你已经登陆,然后改密码什么就好办了。建议你先抓一下IE的包看看是人家的通信是怎么样的,然后用java做就好了。或者是那个网站有开发者文档就最好了。
0条评论