常见问题
Tomcat启动失败的解决方案
首先,如果启动时,弹出对话框,对话框中提示了端口号,多是因为端口号冲突,例如此前已经启动了Tomcat却没有关闭,仍再次启动,就会出现冲突。如果要解决问题,可以先停止此前占用端口的程序,例如在Eclipse找到停止按钮,或者在Tomcat的bin目录下执行shutdown指令,如果不知道如何,可以重启电脑!
如果启动过程中报告异常信息,提示ClassNotFoundException
或者FileNotFoundException
,就检查对应的类是否存在,如果提示的类是依赖的jar包中的类,可能是jar包文件已经损坏,需要重新下载(可以删除.m2中的jar包或者更换版本)。
如果启动过程中报告的异常信息是ZipException
,一定是某个jar包损坏,则检查最近添加的依赖的jar包并重新下载。
如果启动过程中报告的异常信息是LifeCycleException
,通常是由于缓存问题导致的,则需要Clean项目及Tomcat。
关于GET和POST的区别
GET请求会将请求参数体现在URL中,POST请求会将请求参数封装在请求体中,并不会体现在URL中。
GET请求不适用于涉及隐私、安全方面的数据,也不适用于传输数据量较大的数据,通常限制值是2K,该值既取决于客户端的浏览器,也取决于服务器端。
所以,在涉及隐私、安全的数据提交,或者较大数据的提交(特别是上传文件),都应该优先考虑POST方式提交请求。
由于POST方法将请求参数封装在请求体中,没有体现在URL中,所以,如果涉及URL分享等操作,必须使用GET方式提交请求。
在发生请求时,如果使用GET请求,将一次性将请求的URL提交到服务器,所以,请求参数也就直接提交到了服务器,如果使用POST请求,会先向服务器提交第1次请求,此次请求并不携带请求参数,当服务器响应100后,客户端发出第2次请求,再将请求参数提交到服务器。所以,GET请求的访问速度比POST请求更快。
关于转发和重定向
无论是转发还是重定向,都是客户端请求的第1个目标无法实现请求的响应,需要配合服务器端的其它组件来完成响应!
转发的原因是因为使用控制器可以处理用户请求,但是,当得到数据结果后,存在不便于显示的问题,毕竟控制器是Java类,不便于组织HTML代码,所以,会将数据结果转发给JSP页面,由JSP页面来完成数据的呈现,当然,JSP也存在不便于处理数据逻辑的问题,即与HTML高度相似的代码结构中不便于编写Java代码,所以,推荐的做法就是控制器负责处理数据,得到数据结果后把这些数据结果转发给JSP,由JSP呈现,整个过程是发生在服务器内部的,对于客户端来说是不可见的,所以,在转发时,客户端只发出了1次请求,请求的URL就是控制器的URL,并且,即使WEB-INF文件夹的内容是不可以被客户端直接访问的,也不影响把JSP放在这个文件夹下。
重定向是客户端发出第1次请求后,服务器端无法完成最终的响应,所以,只能给出302(通常是302)响应码,让客户端请求另一个URL来完成最终响应,在整个过程中,客户端是发出了2次请求的,同时,客户端也明确第2次的请求目标,所以,在客户端的浏览器中,会显示第2次请求的URL,由于客户端共发出2次请求,所以,在没有经过特殊的处理方式时,第1次请求的数据不可以直接应用到第2次请求中。
解决乱码问题
计算机能够直接识别并处理的都是二进制数,也就是由0和1组成的序列,每个存储0或者1的空间称为“位(bit)”,由于每个二进制位只能存储1个0或者1个1,只能表达2种可能性,就不足以表示更多的内容,在计算机中,使用了更大的单位“字节(byte)”作为基本单位,每个字节由8个二进制位组成。
在ASCII编码表中指定了人类生活使用的字符与二进制数的对应关系,例如a
对应的就是110 0001
,假设输入了1个a
,其实计算机处理的是110 0001
,当计算机运算得到110 0001
,就会显示为a
。
由于ASCII编码表只制定了1个字节的对应关系,但是,中文的汉字种类太多,1个字节无法表达,就需要更多的字节数,例如使用2个字节,就可以表示更多种对应关系,Java语言在处理字符时,内存中就使用的Unicode编码。
当数据需要传输时,如果传输的是a
,只需要1个字节就够了,如果传输的是中
这个汉字,至少需要2个字节,所以,如果单纯直接传输二进制数的序列,接收方可能接收到1110 0001 1101 1100 1011 1010
,却不知道如何进行分隔!所以,为了保证能够正确的分隔这些二进制的序列,就产生了传输编码,例如UTF-8。
在UTF-8中,如果某个字符是2个字节的,则使用的格式是:
1 | 110x xxxx 10xx xxxx |
如果某个字符是3个字节的,则使用的格式是:
1 | 1110 xxxx 10xx xxxx 10xx xxxx |
如果某个字符是4个字节的,则使用的格式是:
1 | 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx |
通常,UTF-8分为常用版本(utf8mb3)和包括了不常用字符的版本(utf8mb4),一般默认指的是常用版本。
当然,除了UTF-8以外,还有其它的编码格式,例如GBK、GB2312、ISO-8859-1、latin1等,不同的编码格式的编码规范是不相同的,甚至有些编码格式并不支持中文!所以,如果发出和接收使用的是不同的编码,甚至使用了不支持中文的编码,就会导致无法解读,进而出现乱码!
所以,乱码问题都是由于“使用的编码不统一”所导致的,而解决方案就是“使用统一的编码”,在项目中,常见的需要指定编码的位置有:项目的源代码、网络传输和接收的编码、界面、其它网络连接、数据库等存储位置……可以简单的理解为:只要能够指定编码的位置,统统指定同一种编码,就不会出现乱码,如果没有指定,就可能出现乱码。
如何快速的向数据表中插入已知的1000万条数据
假设这1000万条数据在1个List
集合中,将这个集合进行遍历,循环1000万次,结合数据库编程技术,就可以将这些数据插入到数据库中。
这样做的缺陷:
- 在实际工作环境中,应用服务器(程序运行所在的Tomcat服务器)与MySQL数据库服务器并不是同一台服务器,当需要执行数据操作时,会由应用服务器将SQL语句发送到MySQL数据库服务器,发送过程中就需要建立网络连接,才可以发送SQL语句,如果使用以上原始做法,就需要连接1000万次,每次发送1条SQL语句,效率非常低下!
- 每次执行1条SQL语句之前,MySQL服务器还会对SQL语句进行词法分析、语义分析、编译等过程,才可以执行,假设有1000万条SQL语句,则这些词法分析、语义分析、编译等过程就需要经历1000万次!
针对问题1,可以使用批处理来解决,批处理可以一次性发送多条SQL语句到数据库服务器,减少传递SQL语句的次数,从而提高运行效率;
针对问题2,可以把INSERT INTO xx () VALUES ();
这种语法调整为INSERT INTO xx () VALUES (值列表1), (值列表2), ..., (值列表N)
,这种做法可以使得1条SQL语句插入多条数据,假设每条SQL语句插入了1000条数据,则只需要1万条SQL语句即可!
所以,总的来说,可以使用每条SQL语句插入100条数据,批处理时每次发送1000条这样的SQL语句,整体循环100次,就可以完成所有数据的插入!
理论上来说,批处理时,不建议一次性处理超过5000条SQL语句。另外,每条SQL语句也不是插入越多数据就越快,拼接这样的SQL语句也是需要耗时的。