Tomcat
Apache是web服务器,Tomcat是应用(java)服务器,它只是一个servlet容器
,是Apache的扩展,Apache和Tomcat都可以做为独立的web服务器来运行,但是Apache不能解释java程序(jsp,servlet),两者都是一种容器,只不过发布的东西不同:Apache是html容器,功能像IIS一样;Tomcat是jsp/servlet容器,用于发布jsp及java的,类似的有IBM的websphere、BEA的Weblogic,sun的JRun等等
概述
JDK下载地址:建议使用8
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
https://www.oracle.com/java/technologies/javase-downloads.html
http://openjdk.java.net/projects/jdk/
https://www.oracle.com/downloads/
https://www.oracle.com/java/technologies/javase-jdk15-downloads.html
http://jdk.java.net/ (也可以下载)
这里选择JDK14:
tar -zxvf jdk-14.0.2_linux-x64_bin.tar.gz -C /usr/local/
#解压完毕后将JDK路径增加到环境变量中
vim /etc/profile #文件定位到PATH处新增一行进行增加环境变量
export JAVA_HOME=/usr/local/jdk-14.0.2/
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
tomcat下载地址:
http://tomcat.apache.org/download-70.cgi
或者去:
http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7.0.96/bin/apache-tomcat-7.0.96.zip
部署(记住JDK一定下完整包的,如果没有就yum安装)
因为如果JDK不是完整包,对于有些程序是无法运行成功的
第一种:JDK配置
配置Java环境,安装JDK:
把jdk-8u201解压到/usr/local/jdk
目录下
二进制方式安装JDK,不用编译直接可用
[root@CentOS-6-3 ~ 19:22]# tar zvxf jdk-8u201-linux-x64.tar.gz
[root@CentOS-6-3 ~ 19:25]# mv jdk1.8.0_212/ /usr/local/jdk
# 配置JDK的环境变量;注意 一定是'>>'两个大于号哈
[root@node4 ~]# cat >> /etc/profile << EOF
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=.:\$JAVA_HOME/jre/lib/*:\$JAVA_HOME/lib/*
export PATH=\$PATH:\$JAVA_HOME/bin
EOF
# 将环境变量加载到当前的shell中;
[root@node4 ~]# source /etc/profile
[root@CentOS-6-3 /usr/local/jdk 19:26]# java -version #查看是否配置完成
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
报错:
解决方案:暂无
第二种:JDK配置
Ps:或者直接yum安装:
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
安装tomcat:
首先创建tomcat用户:
useradd -u 601 tomcat
passwd tomcat
tar xf apache-tomcat-8.0.32.tar.gz
mv apache-tomcat-8.0.32 /usr/local
ln -s /usr/local/apache-tomcat-8.0.32/ /usr/local/tomcat
cd /usr/local
chown -R tomcat.tomcat /usr/local/jdk
chown -R tomcat.tomcat /usr/local/tomcat
su - tomcat
ps:这里su到tomcat后,就可以在tomcat用户下,执行所有操作,也比较安全
[root@haha /usr/local/tomcat8/bin]# ./startup.sh #启动tomcat
Using CATALINA_BASE: /usr/local/tomcat8
Using CATALINA_HOME: /usr/local/tomcat8
Using CATALINA_TMPDIR: /usr/local/tomcat8/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar
Tomcat started.
如果出现如下情况:
原因:缓存的关系,删除temp及work目录下的所以内容
[root@haha /usr/local/tomcat8/bin]#netstat -nutlp | grep 8080 #查看8080端口是否已运行
tcp 0 0 :::8080 :::* LISTEN 2371/java
提示:三个端口,8080为提供web服务的端口,8005为管理端口,8009端口为第三方服务调用的端口,比如httpd和Tomcat结合时会用到
jps命令
(显示当前系统的java进程情况,及其id号)
jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。
如果没有该命令:安装java开发包
# yum install java-1.8.0-openjdk-devel.x86_64
# which jps
#关闭tomcat,然后在重新启动
# sh shutdown.sh
# sh startup.sh
注: ./catalina.sh start
和./startup.sh
都能启动tomcat。使用./catalina.sh stop
或 ./shutdown.sh
停止tomcat。
加入环境变量(可以在任意位置进行启动关闭服务):
[root@haha /usr/local/tomcat8/bin]# vim /etc/profile.d/tomcat8.sh
export PATH=$PATH:/usr/local/tomcat8/bin
[root@haha /usr/local/tomcat8/bin]# source /etc/profile.d/tomcat8.sh
访问测试:http://192.168.2.171:8080/
tomcat启动脚本
# cat /usr/lib/systemd/system/tomcat.service
[Unit]
Description=Tomcat
After=network.target
[Service]
Type=forking
Environment="JAVA_HOME=/usr/local/jdk"
PIDFile=/usr/local/tomcat/tomcat.pid
ExecStart=/usr/local/tomcat/bin/catalina.sh start
ExecReload=/usr/local/tomcat/bin/catalina.sh restart
ExecStop=/usr/local/tomcat/bin/catalina.sh stop
[Install]
WantedBy=multi-user.target
[Unit] 表示这是基础信息
-
Description 是描述
-
After 是在那个服务后面启动,一般是网络服务启动后启动
[Service] 表示这里是服务信息
-
Type 是服务类型
-
PIDFile 是服务的pid文件路径, 开启后,必须在tomcat的
bin/catalina.sh
中加入CATALINA_PID参数 -
ExecStart 是启动服务的命令
-
ExecReload 是重启服务的命令
-
ExecStop 是停止服务的指令
[Install] 表示这是是安装相关信息
- WantedBy 是以哪种方式启动:multi-user.target表明当系统以多用户方式(默认的运行级别)启动时,这个服务需要被自动运行。
tomcat的bin/catalina.sh
中加入CATALINA_PID
参数时,需要在# OS specific support.
上加入
2. 创建软链接
创建软链接是为了下一步系统初始化时自动启动服务
bash
ln -s /usr/lib/systemd/system/tomcat.service /etc/systemd/system/multi-user.target.wants/
3. 刷新配置
刚刚配置的服务需要让systemctl能识别,就必须刷新配置
bash
$ systemctl daemon-reload
如果没有权限可以使用sudo
$ sudo systemctl daemon-reload
4. 启动、重启、停止
启动tomcat
$ systemctl start tomcat
重启tomcat
$ systemctl restart tomcat
停止tomcat
$ systemctl stop tomcat
5. 开机自启动
tomcat服务加入开机启动
$ systemctl enable tomcat
禁止开机启动
$ systemctl disable tomcat
6. 查看状态
查看状态
bash
$ systemctl status tomcat
#!/bin/bash
### BEGIN INIT INFO
# Provides: tomcat
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: tomcat-server daemon
# Description: tomcat-server daemon
### END INIT INFO
#
# chkconfig: - 95 15
# description: Tomcat start/stop/status script
#Location of JAVA_HOME (bin files)
export JAVA_HOME=/usr/local/jdk
#Add Java binary files to PATH
export PATH=$JAVA_HOME/bin:$PATH
#CATALINA_HOME is the location of the configuration files of this instance of Tomcat
CATALINA_HOME=/usr/local/tomcat
#TOMCAT_USER is the default user of tomcat
TOMCAT_USER=root
#TOMCAT_USAGE is the message if this script is called without any options
TOMCAT_USAGE="Usage: $0 {\e[00;32mstart\e[00m|\e[00;31mstop\e[00m|\e[00;32mstatus\e[00m|\e[00;31mrestart\e[00m}"
#SHUTDOWN_WAIT is wait time in seconds for java proccess to stop
SHUTDOWN_WAIT=20
tomcat_pid() {
echo `ps -ef | grep java | grep $CATALINA_HOME/ | grep -v grep | tr -s " "|cut -d" " -f2`
}
start() {
pid=$(tomcat_pid)
if [ -n "$pid" ]; then
echo -e "\e[00;31mTomcat is already running (pid: $pid)\e[00m"
else
echo -e "\e[00;32mStarting tomcat\e[00m"
if [ `user_exists $TOMCAT_USER` = "1" ]; then
su $TOMCAT_USER -c $CATALINA_HOME/bin/startup.sh
else
$CATALINA_HOME/bin/startup.sh
fi
status
fi
return 0
}
status() {
pid=$(tomcat_pid)
if [ -n "$pid" ]; then
echo -e "\e[00;32mTomcat is running with pid: $pid\e[00m"
else
echo -e "\e[00;31mTomcat is not running\e[00m"
fi
}
stop() {
pid=$(tomcat_pid)
if [ -n "$pid" ]; then
echo -e "\e[00;31mStoping Tomcat\e[00m"
$CATALINA_HOME/bin/shutdown.sh
let kwait=$SHUTDOWN_WAIT
count=0;
until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ]
do
echo -n -e "\e[00;31mwaiting for processes to exit\e[00m\n";
sleep 1
let count=$count+1;
done
if [ $count -gt $kwait ]; then
echo -n -e "\n\e[00;31mkilling processes which didn't stop after $SHUTDOWN_WAIT seconds\e[00m"
kill -9 $pid
fi
else
echo -e "\e[00;31mTomcat is not running\e[00m"
fi
return 0
}
user_exists() {
if id -u $1 >/dev/null 2>&1; then
echo "1"
else
echo "0"
fi
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo -e $TOMCAT_USAGE
;;
esac
exit 0
详解tomcat目录:
[root@CentOS6 /opt/app/apache-tomcat-8.5.39]# tree -L 1
.
├── bin #存放启动或关闭tomcat的脚本文件
├── BUILDING.txt
├── conf #存放tomcat服务器的各种全局配置文件,其中最重要的是server.xml和web.xml
├── CONTRIBUTING.md
├── lib #存放tomcat运行所需的库文件(JARS)
├── LICENSE
├── logs #存放tomcat执行时的log文件
├── NOTICE
├── README.md
├── RELEASE-NOTES
├── RUNNING.txt
├── temp #临时文件,如果tomcat启动或者报错时,可以删除该目录下的所有文件,在进行操作,建议停止tomcat后就删除该目录
├── webapps #tomcat的主要web发布目录(包括应用程序实例)
└── work #存放有JSP编译的servlet的.java和.class文件,如果tomcat启动或者报错时,可以删除该目录下的所有文件,在进行操作,建议停止tomcat后就删除该目录
7 directories, 7 files
[root@CentOS6 /opt/app/apache-tomcat-8.5.39]# ls -1 conf/ #conf目录详解
Catalina
catalina.policy #权限控制配置文件
catalina.properties #tomcat属性配置文件
context.xml #上下文配置文件
jaspic-providers.xml
jaspic-providers.xsd
logging.properties #日志log相关配置文件
server.xml #为tomcat的主配置文件,通过配置改文件,可以修改tomcat的启动端口、网站目录、虚拟主机、开启https等重要功能
tomcat-users.xml #manager-gui管理用户配置文件(tomcat安装后提供一个manager-gui的管理界面,通过配置该文件可以开启访问)
tomcat-users.xsd
web.xml #tomcat的servlet、servlet-mapping、filter、MIME等相关配置
以下是默认安装后的server.xml
文件的部分内容,其中<!-- -->
内的内容是注释信息
下面列出需要注意和需要经常更改的部分。
第一处:
<Server port="8005" shutdown="SHUTDOWN">
tomcat关闭的端口,默认只对本机地址开发,可以在本机通过Telnet 172.0.0.1 8005 访问改端口,对tomcat进行关闭操作
第二处:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
tomcat启动的默认端口号8080,可以根据需要进行更改
第三处:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
tomcat启动AJP1.3连接器时默认的端口号,可以根据需要进行更改
第四处:
以下是定义tomcat的虚拟主机时的配置及日志配置
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
tomcat server的组成部分说明
1、server
server元素代表了整个catalina的servlet的容器
2、service
service是这样一个集合,它由一个或者多个connector组成,以及一个engine,负责处理所有connector所获得的客户请求
3、connector
有一个connector在某个指定端口上侦听客户请求,并将获得的请求交过engine来处理,从engine处获得回应并返回客户
tomcat有两个典型的connector,一个直接侦听来自browser的http请求,一个侦听来自其他webserver的请求
coyote http/1.1 connector在端口8080处侦听来自browser的请求
connector JK2 connector在端口8009处侦听来自其他webserver(Apache)的servlet/jsp代理请求
4、engine
engine下可以配置多个虚拟主机(virtual host),每个虚拟主机都有一个域名。当engine获得一个请求时,它把该请求匹配到某个host上,然后把该请求交给该host来处理
engine有一个默认虚拟主机,当请求无法匹配到任意一个host上的时候,将交给该默认host来处理
5、host
代表一个virtual host(虚拟主机),每个虚拟主机和某个网络域名相匹配
每个虚拟主机下都可以部署一个或者多个web app ,每个web app对应一个context,有一个context path
匹配的方法是"最长匹配"
6、context
一个context对应一个web application,一个web application由一个或者多个servlet组成
建立Java的web站点
1、首先在根目录下建立一个web目录,并在里面建立一个webapp1目录,用于存放网站文件
[root@CentOS6 ~]# mkdir -pv /web/webapp1
mkdir: 已创建目录 "/web"
mkdir: 已创建目录 "/web/webapp1"
2、在webapp1目录下,建立一个index.jsp的测试页面
# vim /web/webapp1/index.jsp
<%@ page language="jave" import="java.util.*" pageEncoding="utf-8"%>
<HTML>
<HEAD>
<TITLE>JSP TEST PAGE</TITLE>
</HEAD>
<BODY>
<%
Random rand = new Randdom();
out.println("<h1>Random number:</h1>");
out.println(rand.nextInt(99)+100);
%>
</BODY>
</HTML>
------------------------------------用这个页面测试已成功-----------------------------
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>JSP TEST PAGE</title>
</head>
<body>
<% out.println("tomcat");%>
</body>
</html>
3、修改tomcat的server.xml文件
定义一个虚拟主机,并将网站文件路径指向已经建立的/web/webapp1,在host段增加context段。(或者直接增加host段)
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context docBase="/web/webapp1" path="" reloadable="false">
</Context>
docBase:web应用的文档基准目录
path=""
:设置默认"类"
reloadable:设置监视"类"是否变化
4、关闭tomcat,然后在重新启动
# sh shutdown.sh
# sh startup.sh
注: ./catalina.sh start 和 ./startup.sh 都能启动tomcat。使用 ./catalina.sh stop 或 ./shutdown.sh 停止tomcat。
# ss -tanl #查看端口8080是否启动
5、通过浏览器进行访问:http://ip地址:8080
tomcat多实例及集群架构
tomcat多实例(4处修改的地方必须正确,否则无法正确启动所以实例)
复制tomcat目录
[root@tomcat conf]# cd /application/
[root@tomcat application]# cp -a apache-tomcat-9.0.19 tomcat8_1
[root@tomcat application]# cp -a apache-tomcat-9.0.19 tomcat8_2
修改第一个实例配置文件
[root@tomcat application]# vim tomcat8_1/conf/server.xml
Server port="8011" shutdown="SHUTDOWN"> #第一处修改
<Connector port="8081" protocol="HTTP/1.1" #第二处修改
connectionTimeout="20000"
redirectPort="8443" />
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />--> #第三处修改
<Host name="localhost" appBase="/data/www/ww" #第四处修改
unpackWARs="true" autoDeploy="true">
第二个实例配置文件:
[root@tomcat application]# vim tomcat8_2/conf/server.xml
<Server port="8012" shutdown="SHUTDOWN"> #第一处修改
<Connector port="8082" protocol="HTTP/1.1" #第二处修改
connectionTimeout="20000"
redirectPort="8443" />
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />--> #第三处修改
<Host name="localhost" appBase="/data/www/www" #第四处修改
启动多实例
[root@tomcat application]# mkdir /data/www/www/ROOT -p
[root@tomcat application]# cp /application/tomcat/webapps/ROOT/* /data/www/www/ROOT/
[root@tomcat application]# /application/tomcat8_1/bin/startup.sh
[root@tomcat application]# /application/tomcat8_2/bin/startup.sh
ps:在生产环境中
tomcat集群
使用nginx+tomcat方向代理集群
[root@proxy_a keepalived]# vim /application/nginx/conf/nginx.conf
upstream tomcatpools {
server 10.0.0.144:8081 weight=1 max_fails=3 fail_timeout=20s;
server 10.0.0.144:8082 weight=1 max_fails=3 fail_timeout=20s;
}
server {
listen 80;
server_name tomcat.etiantian.org;
location / {
proxy_pass http://tomcatpools;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
tomcat安装Jpress博客
Jpress,一个wordpress的Java代替版本,使用JFinal开发。
需要maven支持
[root@tomcat tools]# tar xf apache-maven-3.6.1-bin.tar.gz -C /application/
[root@tomcat tools]# ln -s /application/apache-maven-3.6.1 /application/maven
[root@tomcat tools]# tail -2 /etc/profile
export MAVEN_HOME=/application/maven
export PATH="$MAVEN_HOME/bin:$PATH"
[root@tomcat tools]# source /etc/profile
[root@tomcat tools]# mvn -version
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-05T03:00:29+08:00)
Maven home: /application/maven
Java version: 1.8.0_201, vendor: Oracle Corporation, runtime: /application/jdk1.8.0_201/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "2.6.32-573.el6.x86_64", arch: "amd64", family: "unix"
安装jpress
[root@tomcat ROOT]# cd /tools
[root@tomcat tools]# unzip GalaIO-jpress-master.zip
[root@tomcat tools]# cd /data/www/www/ROOT/
[root@tomcat ROOT]# jar xf /tools/jpress/wars/jpress-web-newest.war
[root@tomcat ROOT]# ls
META-INF robots.txt static templates WEB-INF
数据库操作(172.16.1.52 mysql2) 版本必须5.5以上!
[root@mysql_master ~]# mysql -uroot -p123456
mysql> create database jpress ;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on jpress.* to jpress@'172.16.1.%' identified by '123456';
Query OK, 0 rows affected (0.09 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
访问
10.0.0.144:8082
后台:http://10.0.0.144:8082/admin/login
web站点部署
参考:https://blog.csdn.net/Likes1234/article/details/88817255
上线的代码有两种方式,第一种是直接将程序目录放在webapps/ROOT目录下面,第二种方式是适用开发工具将程序打包成war包。然后上传到webapps目录下
使用war包部署站点
上传war到tomcat/webapps/目录下面
访问:ip+port/目录名
例如:192.168.137.10:8080/jenkins
自定义默认网站目录
上面访问的网址为http://10.0.0.144:8080/memtest/meminfo.jsp
现在我想访问格式为http://10.0.0.144:8080/meminfo.jsp
怎么破?
方法一:
将meminfo.jsp或其他程序放在tomcat/webapps/ROOT目录下即可。因为默认网站根目录为tomcat/webapps/ROOT
方法二:修改server.xml配置文件
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/application/tomcat/webapps/memtest" debug="0" reloadable="false" crossContext="true"/> #插入这一行
用户管理
# vim /usr/local/tomcat/conf/tomcat-users.xml
<tomcat-users>
<role rolename="admin"/>
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<role rolename="manager"/>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user name="admin" password="admin123456" roles="admin,manager,admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status" />
</tomcat-users>
# vim /usr/local/tomcat/conf/tomcat-users.xml
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
</tomcat-users>
在访问tomcat时,点击"manager webapp"会跳出一个验证弹框,输入用户名密码
访问:(就可以查查tomcat status 等信息)
http://192.168.137.30:8080/manager/status
http://192.168.137.30:8080/manager/html
http://192.168.137.30:8080/host-manager/html
Ps:建议在实际环境中,修改如下:
如何操作:
manager可以看状态信息,可以不用删除
然后在通过nginx进行访问限制,只允许内部的机器访问tomcat的状态,这样就只需要zabbix进行监控tomcat和jvm了。
tomcat安全优化优化和性能优化
安全优化
[root@tomcat ~]# cd /home/oldboy/
[root@tomcat oldboy]# cp -a /application/apache-tomcat-9.0.19/ .
[root@tomcat ~]# su - oldboy
[oldboy@tomcat ~]$ apache-tomcat-9.0.19/bin/startup.sh
Using CATALINA_BASE: /home/oldboy/apache-tomcat-9.0.19
Using CATALINA_HOME: /home/oldboy/apache-tomcat-9.0.19
Using CATALINA_TMPDIR: /home/oldboy/apache-tomcat-9.0.19/temp
Using JRE_HOME: /application/jdk
Using CLASSPATH: /home/oldboy/apache-tomcat-9.0.19/bin/bootstrap.jar:/home/oldboy/apache-tomcat-9.0.19/bin/tomcat-juli.jar
Tomcat started.
oldboy@tomcat ~]$ ps -ef | grep java
oldboy 30764 1 3 20:49 pts/0 00:00:01 /application/jdk/bin/java -Djava.util.logging.config.file=/home/oldboy/apache-tomcat-9.0.19/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /home/oldboy/apache-tomcat-9.0.19/bin/bootstrap.jar:/home/oldboy/apache-tomcat-9.0.19/bin/tomcat-juli.jar -Dcatalina.base=/home/oldboy/apache-tomcat-9.0.19 -Dcatalina.home=/home/oldboy/apache-tomcat-9.0.19 -Djava.io.tmpdir=/home/oldboy/apache-tomcat-9.0.19/temp org.apache.catalina.startup.Bootstrap start
oldboy 30800 30729 0 20:50 pts/0 00:00:00 grep java
2.telnet管理端口保护((直接Telnet到tomcat的8005端口就可以关闭tomcat的端口))
[oldboy@tomcat conf]$ vim server.xml
<Server port="8005" shutdown="SHUTDOWN"> #1024到65535
3.ajp链接端口保护(进行注释掉,禁止访问连接)
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />-->
4.禁用管理端
docs examples host-manager manager memtest 目录删掉或者移动到其他位置
5、隐藏版本信息
6、server hearder重写
7、起停脚本回收
8、访问日志格式
附带标准配置
性能优化
https://www.cnblogs.com/yaowen/p/9080009.html
- 屏蔽DNS查询、空闲数、下载超时、连接超时、压缩
# vim /usr/local/tomcat8/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxConnections="1000"
enableLookups="false"
maxThreads="3000"
acceptCount="500"
minSpareThreads="100"
maxSpareThreads="500"
maxKeepAliveRequests="200"
keepAliveTimeout="120000"
redirectPort="8443"
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla,traviata"
server="jdws"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,text/plain"/>
connectionTimeout以毫秒为单位,默认设置为20秒。通过修改该参数,可以修改tomcat的请求超时时间;
关于修改最大并发请求连接数,需要修改maxThreads和acceptCount两个参数
参数逐项说明
(1)URIEncoding="UTF-8"
使得tomcat可以解析含有中文名的文件的url
(2)minSpareThreads
最小备用线程数,tomcat启动时的初始化的线程数,默认10.
(3)maxSpareThreads
最大备用线程数,tomcat启动时的初始化的线程数,
(4)enableLookups
如果希望调用request.getRemoteHost()进行DNS查询,以返回远程客户的实际主机名,将enableLookups设为true。
如果希望忽略DNS查询,仅仅返回IP地址,设为false(这样提高了性能), 缺省情况下,DNS查询是使能的。
一句话:是否反查域名,取值为: true 或 false 。为了提高处理能力,应设置为 false
(5)disableUploadTimeout
disableUploadTimeout="true",
类似于Apache中的keeyalive一样,是否需要tomcat容器单独设置上传时间限制,这里是不用,还是使用标准的,不去给上传的附件单独做超时设置。
(6)connectionTimeout
connectionTimeout:网络连接超时,单位毫秒。设置为 -1 表示永不超时。
(7)acceptCount
acceptCount是当线程数达到maxThreads后,后续请求会被放入一个等待队列,这个acceptCount是这个队列的大小,如果这个队列也满了,就直接refuse connection.
一句话:acceptCount:当处理任务的线程数达到最大时,接受排队的请求个数,默认100。
(8)maxThreads
maxThreads:最大线程数,即同时处理的任务个数,默认值为200 , Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数,即最大并发数。保守推荐:600---900。
(9)maxProcessors
与下面minProcessors相对应,具体解释看下面。
(10)minProcessors
在 Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。通常Windows是1000个左右,Linux是2000个左右。
(11)useURIValidationHack
减少它对一些url的不必要的检查从而减省开销,为提供性能可以设置为false
(12)compression
compression :设置是否开启GZip压缩
HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML,CSS,Javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,压缩效率惊人。
(13)compressionMinSize
compressionMinSize="2048" 启用压缩的输出内容大小,这里面默认为2KB
(14)compressableMimeType
compressableMimeType:哪些类型需要压缩,默认是text/html,text/xml,text/plain
4.超时控制:
修改conf/web.xml文件配置,设置session-timeout的值(单位:分钟)
5.最后不要忘了把8443端口的地方也加上同样的配置,因为如果我们走https协议的话,我们将会用到8443端口这个段的配置。
2.jvm调优(重点)
参考:https://www.cnblogs.com/kevingrace/p/5616752.html
Tomcat最吃内存,只要内存足够,这只猫就跑的很快。如果系统资源有限,那就需要进行调优,提高资源使用率。线上环境8G内存一般给系统2G内存,剩下的tomcat按多实例平分,( 1.5G到3.0G)
[oldboy@tomcat apache-tomcat-9.0.19]$ vim bin/catalina.sh
# -----------------------------------------------------------------------------
# OS specific support. $var _must_ be set to either true or false.
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:Newsize=512m -XX:MaxNewSize=512m -XX:PermSize=512m -XX:MaxPermSize=512m -Xloggc:/usr/local/tomcat/logs/tomcat_gc.log"
-Xms1024
-Xmx1024m
->需要设置一样
一、JVM调优参数简介
1、 JVM参数简介
-XX
参数被称为不稳定参数,之所以这么叫是因为此类参数的设置很容易引起JVM 性能上的差异,使JVM 存在极大的不稳定性。如果此类参数设置合理将大大提高JVM 的性能及稳定性。
不稳定参数语法规则:
1.布尔类型参数值
-XX:+<option> '+'表示启用该选项
-XX:-<option> '-'表示关闭该选项
2.数字类型参数值:
-XX:<option>=<number> 给选项设置一个数字类型值,可跟随单位,例如:'m'或'M'表示兆字节;'k'或'K'千字节;'g'或'G'千兆字节。32K与32768是相同大小的。
3.字符串类型参数值:
-XX:<option>=<string> 给选项设置一个字符串类型值,通常用于指定一个文件、路径或一系列命令列表。
例如:-XX:HeapDumpPath=./dump.core
2、 JVM参数示例
配置:
-Xmx4g –Xms4g –Xmn1200m –Xss512k -XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:PermSize=100m
-XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15
解析:
-Xmx4g:堆内存最大值为4GB。
-Xms4g:初始化堆内存大小为4GB 。
-Xmn1200m:设置年轻代大小为1200MB。增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss512k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K。应根据应用线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=8:设置年轻代中Eden区与Survivor区的大小比值。设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10
-XX:PermSize=100m:初始化永久代大小为100MB。
-XX:MaxPermSize=256m:设置持久代大小为256MB。
-XX:MaxTenuringThreshold=15:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
二、JVM调优目标
1. 何时需要做jvm调优?
1. heap 内存(老年代)持续上涨达到设置的最大内存值;
2. Full GC 次数频繁;
3. GC 停顿时间过长(超过1秒);
4. 应用出现OutOfMemory 等内存异常;
5. 应用中有使用本地缓存且占用大量内存空间;
6. 系统吞吐量与响应性能不高或下降。
2. JVM调优原则
1.多数的Java应用不需要在服务器上进行JVM优化;
2.多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;
3.在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);
4.减少创建对象的数量;
5.减少使用全局变量和大对象;
6.JVM优化是到最后不得已才采用的手段;
7.在实际使用中,分析GC情况优化代码比优化JVM参数更好;
3. JVM调优目标
1. GC低停顿;
2. GC低频率;
3. 低内存占用;
4. 高吞吐量;
JVM调优量化目标(示例):
1. Heap 内存使用率 <= 70%;
2. Old generation内存使用率<= 70%;
3. avgpause <= 1秒;
4. Full gc 次数0 或 avg pause interval >= 24小时 ;
注意:不同应用,其JVM调优量化目标是不一样的。
三、JVM调优经验
1. JVM调优经验总结
JVM调优的一般步骤为:
第1步:分析GC日志及dump文件,判断是否需要优化,确定瓶颈问题点;
第2步:确定JVM调优量化目标;
第3步:确定JVM调优参数(根据历史JVM参数来调整);
第4步:调优一台服务器,对比观察调优前后的差异;
第5步:不断的分析和调整,直到找到合适的JVM参数配置;
第6步:找到最合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。
2. JVM调优重要参数解析
注意:不同应用,其JVM最佳稳定参数配置是不一样的。
配置: -server
-Xms12g -Xmx12g -XX:PermSize=500m -XX:MaxPermSize=1000m -Xmn2400m -XX:SurvivorRatio=1 -Xss512k -XX:MaxDirectMemorySize=1G
-XX:+DisableExplicitGC -XX:CompileThreshold=8000 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseCompressedOops -XX:CMSInitiatingOccupancyFraction=60 -XX:ConcGCThreads=4
-XX:MaxTenuringThreshold=10 -XX:ParallelGCThreads=8
-XX:+ParallelRefProcEnabled -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled
-XX:CMSMaxAbortablePrecleanTime=500 -XX:CMSFullGCsBeforeCompaction=4
XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCMSCompactAtFullCollection
-XX:+HeapDumpOnOutOfMemoryError -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/usr/local/tomcat/logs/tomcat_gc.log
重要参数(可调优)解析:
-Xms12g:初始化堆内存大小为12GB。
-Xmx12g:堆内存最大值为12GB 。
-Xmn2400m:新生代大小为2400MB,包括 Eden区与2个Survivor区。
-XX:SurvivorRatio=1:Eden区与一个Survivor区比值为1:1。
-XX:MaxDirectMemorySize=1G:直接内存。报java.lang.OutOfMemoryError: Direct buffer memory 异常可以上调这个值。
-XX:+DisableExplicitGC:禁止运行期显式地调用 System.gc() 来触发fulll GC。
注意: Java RMI的定时GC触发机制可通过配置-Dsun.rmi.dgc.server.gcInterval=86400来控制触发的时间。
-XX:CMSInitiatingOccupancyFraction=60:老年代内存回收阈值,默认值为68。
-XX:ConcGCThreads=4:CMS垃圾回收器并行线程线,推荐值为CPU核心数。
-XX:ParallelGCThreads=8:新生代并行收集器的线程数。
-XX:MaxTenuringThreshold=10:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
-XX:CMSFullGCsBeforeCompaction=4:指定进行多少次fullGC之后,进行tenured区 内存空间压缩。
-XX:CMSMaxAbortablePrecleanTime=500:当abortable-preclean预清理阶段执行达到这个时间时就会结束。
3. 触发Full GC的场景及应对策略
年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,对老年代GC称为MajorGC,而Full GC是对整个堆来说的,在最近几个版本的JDK里默认包括了对永生带即方法区的回收(JDK8中无永生带了),出现Full GC的时候经常伴随至少一次的Minor GC,但非绝对的。MajorGC的速度一般会比Minor GC慢10倍以上。
**触发Full GC的场景及应对策略: **
1.System.gc()方法的调用,应对策略:通过-XX:+DisableExplicitGC来禁止调用System.gc ;
2.老年代代空间不足,应对策略:让对象在Minor GC阶段被回收,让对象在新生代多存活一段时间,不要创建过大的对象及数组;
3.永生区空间不足,应对策略:增大PermGen空间
4.GC时出现promotionfailed和concurrent mode failure,应对策略:增大survivor space
5.Minor GC后晋升到旧生代的对象大小大于老年代的剩余空间,应对策略:增大Tenured space 或下调CMSInitiatingOccupancyFraction=60
6.内存持续增涨达到上限导致Full GC ,应对策略:通过dumpheap 分析是否存在内存泄漏
4. Gc日志分析工具
借助GCViewer
日志分析工具,可以非常直观地分析出待调优点。可从以下几方面来分析:
1.Memory,分析Totalheap、Tenuredheap、Youngheap内存占用率及其他指标,理论上内存占用率越小越好;
2.Pause ,分析Gc pause、Fullgc pause、Total pause三个大项中各指标,理论上GC次数越少越好,GC时长越小越好;
5. MAT 堆内存分析工具
EclipseMemory Analysis Tools (MAT) 是一个分析Java堆数据的专业工具,用它可以定位内存泄漏的原因。
tomcat-session 共享
https://www.jianshu.com/p/f75c84505f9f
https://cloud.tencent.com/developer/article/1027117
https://blog.51cto.com/yw666/1888747
https://www.cnblogs.com/you-men/p/13045736.html
https://hewanyue.com/blog/6254cc16.html
链接:https://www.jianshu.com/p/f75c84505f9f
1.session的了解
在计算机中,尤其是在网络应用中,称为"会话控制"。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话
实现思路
对于web应用集群的技术实现而言,最大的难点就是:如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块。要实现这一点, 大体上有两种方式:
一种是把所有Session数据放到一台服务器上或者数据库中,集群中的所有节点通过访问这台Session服务器来获取数据
另一种就是在集群中的所有节点间进行Session数据的同步拷贝,任何一个节点均保存了所有的Session数据
在集群系统下实现session统一的有如下几种方案
1、请求精确定位:session sticky,
例如nginx基于访问ip的hash策略,即当前用户的请求都集中定位到一台服务器中,这样单台服务器保存了用户的session登录信息,如果宕机,则等同于单点部署,会丢失,会话不复制
2.session复制共享:session replication
tomcat自带session共享,主要是指集群环境下,多台应用服务器之间同步session,使session保持一致,对外透明。 如果其中一台服务器发生故障,根据负载均衡的原理,调度器会遍历寻找可用节点,分发请求,由于session已同步,故能保证用户的session信息不会丢失,会话复制.
不足之处:
1)必须在同一种中间件之间完成(比如tomcat-tomcat之间),
2)session复制带来的性能损失会快速增加,特别是当session中保存了较大的对象,而且对象变化较快时, 性能下降更加显著,会消耗系统性能。这种特性使得web应用的水平扩展受到了限制。
3)Session内容通过广播同步给成员,会造成网络流量瓶颈,即便是内网瓶颈
4)在大并发下表现并不好
3.基于 memcache/redis缓存的 session 共享
用cacheDB存取session信息,应用服务器接受新请求将session信息保存在cache DB中,当应用服务器发生故障时,调度器会遍历寻找可用节点,分发请求,当应用服务器发现session不在本机内存时,则去cacheDB中查找,如果找到则复制到本机,这样实现session共享和高可用
Tomcat集群session同步方案有以下几种方式:
1)使用tomcat自带的cluster方式,多个tomcat间自动实时复制session信息,配置起来很简单。但这个方案的效率比较低,在大并发下表现并不好。
2)利用nginx的基于访问ip的hash路由策略,保证访问的ip始终被路由到同一个tomcat上,这个配置更简单。但如果应用是某一个局域网大量用户同时登录,这样负载均衡就没什么作用了。
3)利用nginx插件实现tomcat集群和session同步,nginx-upstream-jvm-route-0.1.tar.gz,是一个Nginx的扩展模块,用来实现基于Cookie的Session Sticky的功能。
4)利用memcached实现(MSM工具)。memcached存储session,并把多个tomcat的session集中管理,前端在利用nginx负载均衡和动静态资源分离,在兼顾系统水平扩展的同时又能保证较高的性能。
5)利用redis实现。使用redis不仅仅可以将缓存的session持久化,还因为它支持的单个对象比较大,而且数据类型丰富,不只是缓存 session,还可以做其他用途,可以一举几得。
6)利用filter方法实现。这种方法比较推荐,因为它的服务器使用范围比较多,不仅限于tomcat ,而且实现的原理比较简单容易控制。
7)利用terracotta服务器共享session。这种方式配置比较复杂。
在Tomcat集群中,当一个节点出现故障,虽然有高可用集群来负责故障转移,但用户的session信息如何保持呢?
监控
Tomcat开启远程监控功能
在安装Windows安装Java环境,然后修改服务端的配置并连接到服务器上,进行查看jvm的状态
# vim bin/catalina.sh (查看jvm的状态,添加配置文件,然后重启tomcat)
参数解释:
开启jmx远程
开启jmx远程的端口:12345
关闭jmx的认证:false
关闭ssl:false
监听的端口:192.168.56.11(本地的IP地址)
这个工具更牛逼,可以连接多个
Zabbix开启java监控
Zabbix_server开启Java poller;
Zabbix_java开启Javagateway,端口为10052
Tomcat JMX开启12345提供性能数据
数据获取:java poller <->j avagateway:10052 <-> tomcat:12345
java支持
编译安装zabbix server需要加上--enable-java
以支持jmx监控,如果之前的zabbix没装,那么请重新编译安装。
Yum 安装 zabbix-java-gateway
还可以用cmdline-jmxclient进行监控
Resin
tomcat与resin的比较
参考:
https://www.iteye.com/blog/aoyouzi-2017141
https://www.iteye.com/blog/luo-yifan-1888039
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5 支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。目前最新版本是7.0。
Tomcat运行时占用的系统资源小,扩展性好,支持负载平衡与邮件服务等开发应用系统常用的功能;而且它还在不断的改进和完善中,任何一个感兴趣的程序员都可以更改它或在其中加入新的功能。
Apache Tomcat 6.x 在汲取 Tomcat 5.5.x优点的基础上,实现了Servlet 2.5和JSP 2.1等特性的支持。
Apache Tomcat 7.x 是目前的开发焦点,仍基于Apache Software License v2.0标准,同时也是自2006年以来的首个主要发布版本。它在汲取了Tomcat 6.0.x优点的基础上,实现了对于Servlet 3.0、JSP 2.2和Expression Language(EL)2.2等特性的支持。除此以外的改进列表如下:
• Web应用内存溢出侦测和预防
• 增强了管理程序和服务器管理程序的安全性
• 一般 CSRF保护
• 支持web应用中的外部内容的直接引用
• 重构 (connectors, lifecycle)及很多核心代码的全面梳理
Resin是CAUCHO公司的产品,是一个非常流行的支持servlets 和jsp的引擎,速度非常快。Resin本身包含了一个支持HTTP/1.1的WEB服务器。虽然它可以显示动态内容,但是它显示静态内容的能力也非常强,速度直逼APACHE SERVER。许多站点都是使用该WEB服务器构建的。
Resin也可以和许多其他的WEB服务器一起工作,比如Apache server和IIS等。Resin支持Servlets 3.0标准和JSP 1.2标准。熟悉ASP和PHP的用户可以发现用Resin来进行JSP编程是件很容易的事情。
Resin支持负载平衡(Load balancing),可以增加WEB站点的可靠性。方法是增加服务器的数量。比如一台SERVER的错误率是1%的话,那么支持负载平衡的两个Resin服务器就可以使错误率降到0.01%。
Resin也是全免费的,从站点下载的就是完整版本。相对于tomcat,后者更象是一个正在研究的项目。目前resin可以支持sun的j2ee,而tomcat不能直接支持,而j2ee是基于java服务器端大系统的基础。Resin3 之后已经不在是一个简单的jsp容器,并且支持ejb,jta等企业功能。目前resin4 (2010年后已经比较稳定)性能更是优秀。并且已经支持servlet 3.0标准. pro版本是收费版本,支持负载均衡和文件缓存。普通版本独立作为web服务器性能就要差一些,可以使用apache+resin的方案借助apache的缓存功能提高性能,但负载均衡就是普通版不能比的。CAUCHO公司还为resin添加了php解析执行功能,能够运行php程序。但相对 php的原生版本还是有一定差距。
Tomcat 和Sun Java结合的最好,和其他应用服务器配合使用可支持完整的j2ee标准,应用也很广泛。但是从Java 普遍存在的编码问题来看,还是Resin 解决的最好。还有从使用的角度讲,个人认为Resin比Tomcat方便,而且Resin也可以结合Jbuilder6等ide使用。Resin强调使用Xml技术。
resin的启动与关闭机制比tomcat好很多,首先,tomcat在windows下启动,双击完startup.bat后总要等几秒钟才会启动服务,并且关闭的时候也是一样的,有的时候甚至双击了shutdown.bat后startup.bat的窗口还总是在那好长时间,并且如果你哪一次不小心直接关闭了dos窗口而没有运行shutdown,那下一次肯定要出问题,在linux下启动速度还是很不错的,但如果启动错误报错真是很郁闷。而相反,resin的启动就十分人性化了,运行httpd后会出来个窗口,其中有start和stop,你可以随时方便的启动和关闭服务,并且速度也十分的快,并且如果你的配置文件如果有改动的话,启动程序会自动监测并自动重启的,这样在配置环境的时候就不需要像tomcat那样需要反复人工关闭再启动,这点tomcat真是差的很远。
tomcat的报错机制真是不敢恭维,对于一个老手来说还是可以接受的,但如果对于一个刚开始写程序的人来说无疑是个灾难,哪怕仅仅只是个小错误,tomcat都会用整页的篇幅来描述,如果时间长了还好,但新手肯定会望而生畏的,相反,resin的报错是十分简洁而明确的,可以让你一眼就可以看出程序错误的类型和位置
resin对于中文的支持要比tomcat好不少,各种编码和转码很多都是对tomcat设计的,因为在resin平台下根本就不需要,这点对于开发也是很重要的,特别要提的一点就是,用tomcat写的面页很多时候如果只在面页加上contentType="text/html; charset=gb2312"还是不能完成编码的还必须要加入一条看起来像是画蛇添足的一条语句request.setCharac terEncoding("gb2312")
resin支持自动编译Servlet和Bean
免责声明: 本文部分内容转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除。