您的位置:首页 > 科技 > 能源 > 57_2设置Servlet模板、Servlet线程安全问题、跳转

57_2设置Servlet模板、Servlet线程安全问题、跳转

2024/12/23 8:56:34 来源:https://blog.csdn.net/gangain/article/details/140730863  浏览:    关键词:57_2设置Servlet模板、Servlet线程安全问题、跳转

设置Servlet模板

设置Servlet模板
再创建类就有了
Servlet模板
模板代码

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class ${Class_Name} extends HttpServlet {@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException ,IOException {
this.doPost(request, response);
}@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

Servlet线程安全问题

面试题:Servlet是否是单例的?

不是单例,但是一般情况下是单例,

如果Servlet实现了SingleThreadModel接口,该Servlet对象在第一次线程阻塞时会创建新的对象 – 已过时

出现原因

多个客户端访问同一个Servlet中的资源时,有可能会出现线程安全问题

@WebServlet("/ser01")
public class Servlet01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}private  int num;@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {num++;try {Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}response.getWriter().println(num);}
}

这里直接输入指定Servlet访问
添加运行
单独运行
单独运行
浏览器1运行【num++】,同时再开个浏览器运行访问【num++】,就会新开的num变成1+1+1=3
未实现接口两个浏览器同时运行

解决方案:

加锁、使用线程安全的类

1.将Servlet实现SingleThreadModel(已过时),因为当线程阻塞,就会创建新的Servlet对象

2.利用线程锁机制, synchronized或lock

经验:尽可能的不要使用成员变量,而是使用局部变量

实现SingleThreadModel接口
public class Servlet01 extends HttpServlet implements SingleThreadModel{
public Servlet01() {System.out.println("Servlet01被创建了");}......}

添加无参构造,实现接口
添加无参构造,实现接口
再运行
实现接口运行
未实现接口输出个数【单例】
未实现接口输出个数
实现接口,在阻塞【非单例】情况下会创建新的servlet对象,虽然解决了问题,但不可取
创建次数

加锁
@WebServlet("/ser01")
//public class Servlet01 extends HttpServlet implements SingleThreadModel {
public class Servlet01 extends HttpServlet {public Servlet01() {System.out.println("Servlet01被创建了");}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}private int num;@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {synchronized (this){num++;try {Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}response.getWriter().println(num);}}
}

跳转

方式:转发和重定向
欢迎页面:
跳转

情况:

  1. 页面 跳 页面
    页跳页
  1. 页面 跳 Servlet
    页跳s01页跳s01
    页跳s02页跳s02
    页跳s03
    页跳s03
  1. Servlet 跳 Servlet
    s跳s01s跳s01
    s跳s02s跳s02
  1. Servlet 跳 页面
    s跳页01s跳页01
    s跳页02s跳页02

页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>页面 跳 页面</h1><a href="page01.html">跳转到页面1</a><br /><button onclick="fun01()">跳转到页面1</button><br /><form action="page01.html" method="post"><input type="submit" value="跳转到页面1"></form><br /><h1>页面 跳 Servlet</h1><a href="ser01?username=xxx&password=123&nickname=爽了">跳转到Servlet01</a><br /><!--get请求--><button onclick="fun02()">跳转到Servlet01</button><br /><!--get请求--><form action="ser01" method="post"><!--可选请求方式-->账号:<input type="text" name="username"><br />密码:<input type="password" name="password"><br />昵称:<input type="text" name="nickname"><br /><input type="submit" value="跳转到Servlet01"></form><br /><h1>Servlet 跳 Servlet</h1><p>转发方式:Servlet02 -> Servlet03</p><p>浏览器地址栏输入:http://localhost:8080/MyDay18_Web03_war_exploded/ser02</p><p>重定向方式:Servlet04 -> Servlet05</p><p>浏览器地址栏输入:http://localhost:8080/MyDay18_Web03_war_exploded/ser04</p><h1>Servlet 跳 页面</h1><p>转发方式:Servlet06 -> page02.html</p><p>浏览器地址栏输入:http://localhost:8080/MyDay18_Web03_war_exploded/ser06</p><p>重定向方式:Servlet07 -> page03.html</p><p>浏览器地址栏输入:http://localhost:8080/MyDay18_Web03_war_exploded/ser07</p><script type="text/javascript" >function  fun01(){window.location = "page01.html";}function fun02() {window.location = "ser01?username=xxx&password=123&nickname=爽了";}
</script>
</body>
</html>

java代码

@WebServlet("/ser01")
public class Servlet01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");String username = request.getParameter("username");String password = request.getParameter("password");String nickname = request.getParameter("nickname");System.out.println("Servlet01接收到来自客户端的请求了:" + username + " -- " + password + " -- " + nickname);response.getWriter().println(username + " -- " + password + " -- " + nickname);}
}
@WebServlet("/ser02")
......
//doPost方法不同
//转发方式
request.getRequestDispatcher("ser03").forward(request,response);
@WebServlet("/ser03")
......
//doPost方法不同
System.out.println("Servlet03接受到请求了");
@WebServlet("/ser04")
......
//doPost方法不同
//重定向方式
response.sendRedirect("ser05");
@WebServlet("/ser05")
......
//doPost方法不同
System.out.println("Servlet05接受到请求了");
@WebServlet("/ser06")
......
//doPost方法不同
//转发方式
request.getRequestDispatcher("page02.html").forward(request,response);
@WebServlet("/ser07")
......
//doPost方法不同
//重定向方式
response.sendRedirect("page03.html");
转发和重定向的区别

理解图

@WebServlet("/ser01")
public class Servlet01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/*** 知识点:转发和重定向的区别*///区别一:发送请求次数的区别//注意:转发发送1次请求//request.getRequestDispatcher("page01.html").forward(request,response);//http://localhost:8080/Day18_04_war_exploded/ser01//注意:重定向发送2次请求//response.sendRedirect("page01.html");//http://localhost:8080/Day18_04_war_exploded/page01.html//区别二:访问外部资源//注意:转发不能访问外部资源(因为服务器不能访问其他的服务器)//request.getRequestDispatcher("https://www.baidu.com").forward(request,response);//注意:重定向可以访问外部资源(因为本服务器通过响应告诉客户端重新向其他服务器发送请求)//response.sendRedirect("https://www.baidu.com");//区别三:访问受保护的页面//注意:转发可以访问受保护的页面(因为转发是服务器内部的跳转)//request.getRequestDispatcher("WEB-INF/page02.html").forward(request,response);//注意:重定向不可以访问受保护的页面(因为客户端不能直接访问受保护文件夹里的资源)response.sendRedirect("WEB-INF/page02.html");}
}

受保护的页面,放在web\WEB-INF
保护页面

  <h1>受保护的页面</h1>

页面

  <h1>页面1</h1>

转发
转发
重定向
重定向

中文页面

设置请求和响应的编码格式不能解决,对应跳转中文页面还需加编码类进行设置
跳转中文页面地址栏就不会显示乱码和找不到
中文页面乱码

@WebServlet("/ser01")
public class Servlet01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求和响应的编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//跳转中文页面// response.sendRedirect("页面1.html");response.sendRedirect(URLEncoder.encode("页面1.html","UTF-8"));}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com