原理图:
前提:我用的命令行都是mac系统下用的,非win
jsp实质是一个servlet,所以要先了解servlet,如上页面是一个servletdemo,下面是尝试的步骤
1.先写好Demo.java
(正常可以在eclipes里直接创建一个servlet,然后打成war包丢到tomcat的webapps里,运行tomcat就可以访问),为了了解本质,我用记事本写了如下:
Demo.java
package cn.itcaste; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Demo extends HttpServlet { public void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { OutputStream out=arg1.getOutputStream(); out.write("hello!".getBytes()); } }
写好放到tomcat中webappps下的----》2web应用下的---》classes里,在没编译前是是没有Demo.class的
tomcat里的结构:
2.编译Demo.java
命令行输入: javac -d . Demo.java(意思是引入jar,并在当前地址编译java文件)
然后显示编译失败,理由是:servlet的jar要单独引入
servlet的jar要单独引入:$export CLASSPATH=${CLASSPATH}:/Users/snowing/Downloads/apache-tomcat-9.0.0.M18/lib/servlet-api.jar
引入成功后重新编译: javac -d . Demo.java
编译成功如下
3.配置 web.xml
这里我犯了一个错误,就是我的<servlet-mapping>写错了,注意这里一定要配置mapping,不然无法访问
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>Demo</servlet-name>//类名 <servlet-class>cn.itcaste.Demo</servlet-class>//完整类名 </servlet> <servlet-mapping> <servlet-name>Demo</servlet-name>//对应上面的类名 <url-pattern>/Demo</url-pattern>//对外访问路径 </servlet-mapping> </web-app>
启动tomcat:
结果:
servlet细节:
servlet细节-----》1影射到多个url上
同一个servlet可以被影射到多个url上
name一样,mapping不一样 -----------》
servlet细节------》2 通配符
在servlet影射的url上可以使用通配符,但只能用两种固定的格式:
一种是“*.扩展名”,另一种格式“/扩展名/*”
每个tomcat都会在conf里配置好了读取web.xml
servlet细节---》3 servlet响应关系
servlet在使用过通配符映射,很有可能会出现都可以响应的情况,所以会有优先级的安排
越像越会响应,而且*.do是匹配度最低的
servlet细节---》4 servlet实例对象生命的顽强
servlet引擎:就是调用servlet的web服务器的程序
对于客户端的多次请求只创建一次servlet实例对象,直到web容器退出才会销毁
servlet细节---》5 servlet生命周期(面试)
servlet生: 服务启动不生,访问servlet才生 . init只调用一次
@Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub super.init(config); System.out.println("init"); }
servlet死:服务死才死
@Override public void destroy() { // TODO Auto-generated method stub System.out.println("destroy"); }
servlet细节---》6 servlet <load-on-startup> web项目启动即创建servlet实例对象
web.xml里修改 <load-on-startup>数字</load-on-startup> 数字越小优先级越高
servlet细节---》6 servlet 里的web.xml如果配置了缺损servlet则访问配置的,相当于复写了tomcat里配置好的servlet
tomcat里的web.xml写好了默认的缺损,可以找到对应名字webroot下的静态资源
注意:复写后访问缺损URL就会找你复写的servlet,而不是寻找webroot下的静态页面!
servlet细节---》6 servlet 线程安全问题(少使用static)
每个客户端访问会创建一个线程,并在线程上调用service方法,如果请求的是一个资源,就有可能会发生线程安全问题
6.1如下int i=0;这个写法是错误的,会造成安全问题, 放在doget方法里是没问题的!
6.2线程上调用的service方法里如果存在静态成员,一定要注意用完移除,不然会内存太多。尽量少使用static(方立勋老师的提示)
6.3线程安全问题之按访问顺序进行排队-------》web资源不能这样做,不可能一个在访问其他人排队等着访问,啊哈哈哈哈哈,看看就好
6.4线程安全问题之SingleThreadModel-------》认真你就输啦web资源不能这样做 淘汰做法,本质是创建多个servlet大象🐘进行服务,当然不会有安全问题
这里引入一个概念,java中存在标记接口,也就是java中的特工。 赋予特殊权限
例子:
Serializable------>可以被序列化(JAVA默认是不可以的)
SingleThreadModel------->创建多个servlet进行服务
Cloneable--->对象可以被克隆
另一个概念:子类在复写父类的方法时不能抛出比父类多的异常!
所以这里的doget和dopost都不能抛异常
6.5线程安全问题之解决------》抛出异常,并抓住给友好提示信息