设置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);}}
}
跳转
方式:转发和重定向
欢迎页面:
情况:
- 页面 跳 页面
- 页面 跳 Servlet
页跳s01
页跳s02
页跳s03
- Servlet 跳 Servlet
s跳s01
s跳s02
- Servlet 跳 页面
s跳页01
s跳页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"));}
}