您的位置:首页 > 运维架构 > Tomcat

servlet读书笔记

2016-06-18 19:43 549 查看
[b]每文一语:一个人的影子无法铺满大地,但有些声音可以传的很远,绵延不绝,生生不息。[/b]



将Tomcat的common包下的lib下的jsp_api.jar,servlet_api.jar复制到JDK下的lib下,就可编译servlet程序。将servlet编译成class文件后移动到Tomcat的自建的myweb下的WEB-INF下的class里粘上,然后再myweb下的web.xml中进行配置。

查看端口占用命令:NETSTAT -NAO, 查出占用端口的pid,然后在资源管理器中关闭该pid所对应的应用进程。

Servlet中设置字符集问题:



1.Servlet的生命周期:

A.生命全过程:

加载ClassLoader

实例化  new

初始化   init(ServletConfig)

处理请求  service doGet   doPost

退出服务  destroy()

B.只有一个对象

C.API中的过程

Init()   //只执行一次, 第一次初始化的时候

public void init(ServletConfig config)
4000
 throws ServletException

Service() 

Public void service(ServletRequest reg, ServletResponse res) throws ServletException, java.io.IOException

Destroy()//退出的时候

Public void destroy()\

2.cookies问题:

1.服务器可以向客户端写内容

2.只能是文本内容

3.客户端可以阻止服务器写入

4.只能拿自己webapp写入的东西

5.Cookes分为两种

A.属于窗口/子窗口

B.属于文本

6.一个servlet/jsp设置的cookies能够被同一个路径下面或是子路径下面的servlet/jsp读到(路径 = URL) (路径 != 真实文件路径)

3.session的两种实现方式:

1.通过cookies实现

2.通过URL重写来实现

4.session规则:

1.如果浏览器支持Cookie,创建Session的时候会把SessionID保存在Cookie里。

2.如果不支持Cookie,必须自己编程使用URL重写的方式实现Session。

Response.encodeURL()

1.转码

2.URL后面加入SessionID.

3Session不像Cookie拥有路径访问的问题

同一个application下的servlet/jsp可以共享同一个session,前提是同一个客户端窗口。

5.服务器端的doGet方法,只有客户端用get方式来访问servlet的时候goGet方法才会被调用,即直接在URL中敲我们的地址,就是get方式。Post方式,只有在form里面点提交,而且form的method是post,这种时候才是post方式。doGet方法中的第一个参数request封装了从客户端到服务器端的请求,第二个参数response是从服务器端返回给客户端的那个对象的信息。

6.服务器常用的状态码及其对应的含义如下:

200:服务器响应正常。

304:该资源在上次请求之后没有任何修改,这通常用于浏览器的缓存机制,使用GET请求时尤其需要注意。

400:无法找到请求的资源。

401:访问资源的权限不够。

403:没有权限访问资源。

404:需要访问的资源不存在。

405:需要访问的资源被禁止。

407:访问的资源需要代理身份验证。

414:请求的URL太长。

500:服务器内部错误。

7.在servlet中response.getWritert().println("<br>");想让这个<br>以html的格式在浏览器中解析,如果浏览器无法以html的格式解析,可以在代码中输入response.setContentType("text/html;charset=gb2312");来告诉浏览器以html的格式解析。


韩顺平视频笔记















修改session的存在时间(这里是按秒来计算):





























请求转发与重定向

(1).请求转发

servlet类的对象可以使用javax.servlet.RequestDispatcher.forward()方法来转发它所收到的HTTP请求。如果当前Servlet组件要把请求转发给一个JSP组件,例如index.jsp。可以执行如下代码:

String url = "index.jsp";

RequestDispatcher rd = request.getRequestDispatcher(url);

rd.forward(request, response);

在jsp页面中,可以使用<jsp:forward>标签来转发请求,执行代码如下:

<jsp:forward page="index.jsp"/>

对于请求转发,转发的源组件和目标组件共享request范围内的共享数据。

(2).URL重定向

URL重定向类似于请求转发,但也有一些重要的区别。主要区别有一下两个方面:

        1.Web组件可以将请求重定向到任意一个URL,而不仅仅是同一应用上下文中的URL。但最初请求的内容(例如POST参数)丢失了,这是因        为服务器与重定向请示的过程无关,这与请求转发的情况是一样的。

        2.重定向的源组件和目标组件之间不共用同一个HttpServletRequest对象,因此不能共享request范围内的共享数据。

URL重定向可以直接通过操作HTTP头来完成,但首选方式还是使用javax.servlet.ServletResponse.sendRediect.这个方法的唯一参数就是重定向的目标URL。如果当前应用的Servlet组件要把请求转发给URL“http://www.baidu.com”,可以执行如下代码:

    String url = "http://www.baidu.com";

    response.sendRediect(url);

线程安全——Servlet的非线程安全

    众所周知,Servelt并不是线程安全的,它存在着一定的线程安全隐患,因为Servlet只会有一个实例,当多个用户请求同一个Servlet时,Tomcat就会启动多线程执行Servlet的代码,所以一旦开发人员设计不当,就会酿成非常严重的后果。看下面例子;

public class TestServelt extends HttpServlet{

    private String name;  //定义一个公共的私有变量

    

    public void doGet(HttpServeltRequest request, HttpServletResponse response) throws ServeltException, IOException{

        doPost(request, response);

    }

    public void doPost(HttpServeltRequest request, HttpServletResponse response) throws ServeltException, IOException{

        name = request.getParameter("name");     //获取name参数

        try{

            Thread.sleep(10000);   //让线程沉睡10秒钟。

        }catch(InterruptedException e){

            e.printStackTrace();

        }

        response.getWriter().println("获取的name参数为:" + name);   //输出信息

    }

}

上面程序初看起来没有什么问题,而且单个用户测试的时候程序都是正常的,但是当多个用户同时执行这个servlet的时候,问题就来了,在10秒内分别用两个不同的用户访问这个Servlet。

在十秒之内在两个不同的浏览器上同时输入:
http://localhost:8080/3.18/servlet/TestServlet?name=wgh    //应该输出:name = wgh

http://localhost:8080/3.18/servlet/TestServlet?name=mingri   //应该输出:name = mingri

输出结果为:

name = mingri

name = mingri

从运行结果可以看出,两次访问获取的name参数都为“mingri”,第一个请求的name参数已经被第二个请求的name参数所覆盖,这就意味着程序中出现了致命的问题。

为什么会出现这样的结果呢?由于有两个用户同时访问这个Servlet,Tomcat就创建了两个线程来执行这个servlet,由于TestServlet?name=wgh

的请求先执行,所以当第二个请求TestServlet?name=mingri执行的时间,name 参数就覆盖了第一个请求的参数,因此,Servlet并不是线程安全的,不当的设计可能会造成数据的不同步。

    解决上述代码数据不同步最好的办法就是不要定义共有的私有变量,最好把变量分配到doGet()方法和doPost()方法中。例如改造后的doPost()方法的代码如下:

  public void doPost(HttpServeltRequest request, HttpServletResponse response) throws ServeltException, IOException{
        response.setCharacterEncoding("GB2312");

        String name = request.getParameter("name");     //获取name参数

        try{

            Thread.sleep(10000);

        }catch(InterruptedException e){

            e.printStackTrace();

        }

        response.getWriter().println("获取的name参数为:" + name);   //输出信息

    }

tomcat技巧——常用优化技巧

    使用tomcat发布应用的时候,如果程序的并发量小,系统并不会出现问题,但是当并发量大的时候,就会占用系统的大量资源,从而造成系统反应缓慢,由于不了解原因程序员还在程序中查找问题,殊不知服务器调优才是一个正确的解决之道。

    在进行调优之前,先找到Tomcat安装目录中的子目录conf,打开web.xml,修改下面的代码即可:

 <Connector
    calssName="org.apache.coyote.tomcat4.CoyoteConnector"

     port="8080"  minProcessors="5"  maxThreads="75" 
    enableLookups="true"

    acceptCount="10" debug="0"

    connectionTimeout="20000" 
    redirectPort="8443" URIEncoding="UTF-8"
    useURIValidationHack="false"

/>

    1.线程控制

        Tomcat通过线程池响应用户的并发访问,例如,用户并发数量大约在1000左右。那么可以设置minProcessors="1000" maxProcessors="1000",  将线程最大和最小设置为一样后,线程池不会再释放空闲的线程,当访问量增加的时候,服务器也不会再消耗系统资源去创建新的线程。

    2.屏蔽DNS查询

        关闭该属性只需修改enableLoopups=“false”.Web应用程序可以通过Web容器提供的getRemoteHost()方法获得访问用户的IP地址和名称,它是通过IP地址与DNS服务器反查用户的名字实现的,在一定程度上浪费了Web容器资源,可以关闭该属性。

    3.设置最大连接数

        该属性并不好设置,高了会造成系统消耗大量资源去切换线程,低了会不能满足用户的并发需求。设置这个值前最好对系统的实际情况做一下调研。一般情况下,可以将其设置为maxProcessors的1.5倍,修改acceptCount这个属性即可。

    4.设置网络超时

        为了保证用户不会因为超时而断开连接,可以将这个属性设置长一些,一般connection Timeout="30000"就可以了,其属性设置过长反而会浪费系统资源,设置为0会造成一定的系统隐患。

如何防止重复提交:(页面提交速度比较慢时用户不停提交)

    1.token拦截器:

    2.post提交方式

   3.url后面加一个new Date()或者一个随机数;

servlet中文乱码问题的解决方法:(get和post提交方式的处理方式不同)

get请求:

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//request的处理方法
String username = request.getParameter("username");
username = new String(username.getBytes("ISO8859-1"),"UTF-8");

//response的处理方法(两种方法)
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;utf-8"); //推荐

}

post请求:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
//response的处理方法
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;utf-8"); //推荐

}

以后写form表单等时不要直接写项目名称,而用如下方式:

 <form aciton="${pageContext.request.contextPath}/LoginServlet" method="post">
  <input type="text" name="username"/></br>
 <input type="password" nam="password"/></br>
 <input type="submit" value="提交"/>
  </form>

用${pageContext.request.contextPath}来取得项目名称,以防项目名称有变。

1.用eclipse开发时上传文件的相对路径问题(害我花了一天时间):request.getSession().getServletContext().getRealPath("\\") + "saveFile\\"

[b]每文一语:一个人的影子无法铺满大地,但有些声音可以传的很远,绵延不绝,生生不息。
[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java tomcat servlet