JavaWeb| 深入Servlet技术(三)

简介: JavaWeb| 深入Servlet技术(三)

1


写在前面的话


      这篇文章应该是Servlet篇的结尾篇了,在这篇文章中,我会讲到重定向并且给大家演示一个小栗子,还会讲到请求转发和重定向的区别、网页的自动刷新以及Servlet线程安全问题。废话不多说了,继续往下看吧!


2


重定向这个东东


首先当然是来自百度百科的解释:


      重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。


也有另外一种解释:


     重定向是根据服务器返回状态码来实现的。如果此时服务器返回了一个301或者302的状态码,那么浏览器就会到新的网址重新请求该资源。服务器的响应中会带着这个新资源的地址。


可能你现在还是不懂重定向是啥,我给你举个简单的例子,当我们在某个网站登录时,我们点击登录之后就会跳转到个人中心之类的页面,此时就是因为发生了重定向。



给大家简单的画了张图:


image.png


我们通过一个实际的代码案例来让大家体验一下:


  <form action="test2" method="get">
  用户名:<input name="username" type="text">
    密码:<input name="password" type="password">
    <input type="submit" name="tijiao">
  </form>


这是我们的表单,模拟登录界面。


@WebServlet(name = "TestServlet2",urlPatterns = "/test2")
public class TestServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = "JAP";
        String password = "123456";
        String username = request.getParameter("username");
        String passWord = request.getParameter("password");
        if (name.equals(username)&&password.equals(passWord)){
            // HttpServletResponse.SC_MOVED_TEMPORARILY是302常量
            response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
            response.setHeader("Location","https://www.baidu.com");
        }
    }
}


上面是我们的Servlet代码,其实非常的简单,我们运行案例之后,如果登录成功,那么页面会跳转至百度。


3


请求转发和重定向的区别


区别:


   ①重定向可以跳转至任何的网址,转发只能在服务器内部进行,就好比上面我们重定向至百度。


   ②重定向的地址栏是会发生变化的而转发不会


   ③重定向是两次请求,两次响应,转发是一次请求一次响应。


   ④重定向路径需要加工程名而转发路径不需要。


这里也给大家两张图:


image.png


4

网页的自动刷新和跳转

这里给大家的是一个小案例:


@WebServlet(name = "TestServlet3",urlPatterns = "/test3")
public class TestServlet3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //防止乱码
        response.setContentType("text/html;charset=utf-8");
        // 设置自动刷新和跳转
        response.setHeader("refresh","3;url='index.jsp'");
        response.getWriter().println("3秒后自动跳转!");
    }
}


这三句简单的代码就可以实现页面的自动刷新和跳转


5

Servlet线程安全

  首先给大家一串代码,大家思考一下此时是否存在线程安全问题?


@WebServlet(name = "ThreadServlet",urlPatterns ="/thread")
public class ThreadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int i =0;
        i++;
    }
}


其实这里是没有线程安全问题的,为啥呢?因为doGet方法是由Service方法实现的,Service方法是一个多线程的方法,当多个客户端同时访问doGet方法时,它会为每个doGet方法创建一个int i的变量。


我们再来看看这串代码,我们将i变量变成成员变量,并且我们通过Thread的sleep方法模拟一个并发问题。


@WebServlet(name = "ThreadServlet",urlPatterns ="/thread")
public class ThreadServlet extends HttpServlet {
    int i =0;
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        i++;
        try {
            Thread.sleep(5*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(i+"");
    }
}


我们来看一下两个浏览器同时访问它会是一个怎样的结果:


image.png


可以看到,我们两个浏览器同时去访问它时,两个显示的都是2,这说明了当第一个线程运行i++并且睡眠5秒时,另一个线程此时访问进来了并且执行了i++,所以此时i变成了2,当休眠期过了,就在浏览器上显示了2.


咱们来总结一下:

当多个客户端并发访问同一个Servlet的时候,web服务器会为每一个客户端的访问创建一个线程,并且在这个线程上调用service方法,因此service方法内部如果访问同一个共享资源时,就可能引发线程安全问题


既然问题出来了,怎么去解决它呢?

1.同步代码块:


@WebServlet(name = "ThreadServlet",urlPatterns ="/thread")
public class ThreadServlet extends HttpServlet {
    int i =0;
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        synchronized (this){
            i++;
            try {
                Thread.sleep(5*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(i+"");
        }
    }
}


通过加synchronized同步代码块,可以解决多线程安全问题,结果我就不展示了。其实这种方法也会给我们带来一些问题,例如,我们加了同步代码块后,我们第二次线程访问时需要等待第一个线程结束才能够进去访问,如果一个网站1000人去访问,那需要等很久很久,所以这给用户带来的体验也是不好的。


总结:为了减少这种线程安全问题的发生,唯一一种有效的方法就是少去使用一些共享的资源,最好都是一些局部资源,这样就可以去保证Servlet的线程安全问题。

相关文章
|
24天前
|
Java 容器
【学习笔记】Jsp与Servlet技术
【学习笔记】Jsp与Servlet技术
54 0
|
2月前
|
Java 应用服务中间件 Maven
JavaWeb基础5——HTTP,Tomcat&Servlet
JavaWeb技术栈、HTTP、get和post区别、响应状态码、请求响应格数据式、IDEA使用Tomcat、报错解决、Servlet的体系结构、IDEA使用模板创建Servlet
JavaWeb基础5——HTTP,Tomcat&Servlet
|
3月前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
31 3
|
3月前
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
30 1
|
3月前
|
前端开发 Java 开发工具
servlet技术--使用注解模拟用户登录实现页面跳转
该文章介绍了Servlet技术的使用,通过注解方式开发Servlet来模拟用户登录功能,并在登录成功后实现页面跳转,展示用户的用户名和密码。
servlet技术--使用注解模拟用户登录实现页面跳转
|
3月前
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
50 3
|
3月前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
36 0
|
3月前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
25 0
|
4月前
|
安全 Java API
Java中的Servlet编程详解
Java中的Servlet编程详解
|
4月前
|
Java 数据库连接 开发者
Java中的Servlet生命周期详解
Java中的Servlet生命周期详解