概述
- 处理客户端请求并做出响应
- servlet是开发动态web的技术
- servlet跑在tomcat容器中
![在这里插入图片描述](https://img-blog.csdnimg.cn/d3a84e97080f4f768094130ca8fb2a57.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiA5Liq5q2j5Zyo5Yqq5Yqb55qE6I-c6bih,size_11,color_FFFFFF,t_70,g_se,x_16)
输出内容到网页
1.学习
2.仿照实践
@WebServlet("/hello.action")
public class Hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head><meta charset='utf-8'><title>第一个</title></head>");
out.println("<body>");
out.println("<p style='color:red'>你好</p>");
out.println("</body>");
out.println("</html>");
}
}
乱码问题解决:
1.开发者工具查出错,则服务器端乱码(响应信息,回送的数据乱码)
resp.setContentType("text/html;charset=utf-8");
2.开发者工具查无错,则服务器端是好的,但是界面乱码(服务器渲染时的乱码)
<meta charset='utf-8'>
3.底层
![在这里插入图片描述](https://img-blog.csdnimg.cn/cf6e7737088f4e0e8b06f077277f86b9.png)
生命周期
1.特点
- servlet只实例化一次(单例),即项目重新启动时才会重新实例化
- 单例会使全局变量的值不确定,线程不安全,应避免声明全局变量
每次请求的实例都是同一个,可以随时改变属性
2.调用
- 调用顺序
![在这里插入图片描述](https://img-blog.csdnimg.cn/f0173c4045784196ad42d0152618641d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiA5Liq5q2j5Zyo5Yqq5Yqb55qE6I-c6bih,size_12,color_FFFFFF,t_70,g_se,x_16)
第一次请求:构造块1 -> 构造函数2 -> init()3 -> service()4[方法体中使用super.service()5判断请求方法get/post] -> doGet()/doPost()6
第二次请求:service() -> doGet()/doPost()
关闭容器时调用销毁方法destroy
- 调用流程
![在这里插入图片描述](https://img-blog.csdnimg.cn/9aca9e7a18ed495d8e7a6df5b61d1d95.png)
3.测试
@WebServlet("/Life.action")
public class LifeServlet extends HttpServlet {
{
System.out.println("1.构造代码块(实力块)");
}
public LifeServlet(){
System.out.println("2.构造方法");
}
@Override
public void init() throws ServletException {
System.out.println("3.初始化init()");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("4.service()");
super.service(req, resp);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("6.doGet");
}
@Override
public void destroy() {
System.out.println("7.servlet销毁");
super.destroy();
}
}
ServletContext(上下文)
1.概述
- web容器启动时,为每个web程序创建ServletContext,代表当前web应用
web应用相当于IDEA中的模块,为每个模块分配tomcat服务器
而servlet相当于是继承HttpServlet的子类
2.共享
- ServletContext被每个servlet共享
@WebServlet("/setParam")
public class TestSet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user = new User(1,"user_1");
ServletContext context = this.getServletContext();
context.setAttribute("user",user);
System.out.println("设置成功");
}
}
@WebServlet("/getParam")
public class TestGet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
User user = (User) context.getAttribute("user");
System.out.println("获取成功");
}
}
3.初始化参数
- 局部参数(争对一个servlet)
![在这里插入图片描述](https://img-blog.csdnimg.cn/72d08457762849e8a38cd5fa9c9fc801.png)
- 全局参数
![在这里插入图片描述](https://img-blog.csdnimg.cn/aad2d392ca2f4688b0f7f8bc8df98bc1.png)
4.请求转发
@WebServlet("/dispatcher")
public class RequestDispatcherTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
RequestDispatcher dispatcher = context.getRequestDispatcher("/getParam");
dispatcher.forward(req,resp);
}
}
- 请求转发与重定向的区别
![在这里插入图片描述](https://img-blog.csdnimg.cn/3836d19d7fdd4950badf83c8f027e910.png)
HttpServletResponse
1.输出消息到浏览器
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("xxxxx");
2.下载文件
@WebServlet("/downFile")
public class DownFile extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String path = "E:/IdeaProjects/web/webstudy/src/com/yc/web/servlets/T3_HttpServletResponse/7.jpg";
String filename = path.substring(path.lastIndexOf("/")+1);
FileInputStream fin = new FileInputStream(path);
byte[] bytes = new byte[1024];
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));
OutputStream out = resp.getOutputStream();
int len = 0;
while ((len=fin.read(bytes))>0){
out.write(bytes,0,len);
}
fin.close();
out.close();
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/882c80daada1403b9c939735c4234a19.png)
3.验证码
@WebServlet("/yzm")
public class YZM extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("refresh","3");
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = (Graphics2D) image.getGraphics();
graphics2D.setColor(Color.WHITE);
graphics2D.fillRect(0,0,80,20);
graphics2D.setColor(Color.BLUE);
graphics2D.setFont(new Font(null,Font.BOLD,20));
graphics2D.drawString(getNum(),0,20);
resp.setContentType("image/jpeg");
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-catch");
resp.setHeader("Pragma","no-catch");
ImageIO.write(image,"jpg",resp.getOutputStream());
}
public String getNum(){
Random random = new Random();
String num = random.nextInt(9999999)+"";
StringBuffer buffer = new StringBuffer();
for (int i=0;i<7-num.length();i++){
buffer.append("0");
}
return buffer.toString()+num;
}
}
4.重定向
@WebServlet("/redirect")
public class Redirect extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/helloWeb/yzm");
}
}
HttpServletRequest
1.获取请求参数
![在这里插入图片描述](https://img-blog.csdnimg.cn/9ca7e767520e43dab58f073c85727c9a.png)
2.请求转发
![在这里插入图片描述](https://img-blog.csdnimg.cn/bac82e6e58a24adebb98b131049ef282.png)
实现B+S+DB操作
1.需求
- 浏览器:在输入框中输入数据,带着参数发送请求到服务器
- 服务器:接收浏览器发送的请求,进行一些处理后,回送响应结果给服务器
2.浏览器端HTML
关键action**
<form action="reg.action" method="post">
用户名:<input type="text" name="uname" value="张三" /><br />
密码:<input type="password" name="pwd" value="abc" /><br />
<input type="submit" value="登录" />
</form>
3.服务器端Servlet
@WebServlet("/reg.action")
public class RegServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String uname = request.getParameter("uname");
String pwd = request.getParameter("pwd");
System.out.println(uname+" "+pwd);
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}catch (Exception ex){
ex.printStackTrace();
}
int result=-1;
try ( Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","scott","a");
PreparedStatement pstmt = con.prepareStatement("insert into yc108 values(seq_yc108.nextval,?,?)");
){
pstmt.setString(1,uname);
pstmt.setString(2,pwd);
result = pstmt.executeUpdate();
}catch (Exception ex){
ex.printStackTrace();
}
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
if(result ==1){
out.println("添加"+uname+"成功");
}else if(result ==0){
out.println("添加"+uname+"失败");
}else{
out.println("系统异常,添加失败");
}
out.close();
}
}
Cookie与Session
1.理解Cookie与Session的关系
学校如何确定我有没有交学费呢?
学校给我开发票(Cookie)
学校登记我的信息(Session)
2.Cookie(小饼干)
- 服务器给客户端的信件,客户端下次访问服务器带上信件(Cookie)就好
- 客户端技术
- cookie一般保存在本地用户目录下appdata
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie,多的没有作用
- cookie有大小限制4kb
- 300个cookie是浏览器上限
- 设置cookie,保留最后一次访问的时间
@WebServlet("/lastLoginTime")
public class LastLoginTime extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if(cookies==null){
out.println("第一次访问");
}else{
for (Cookie cookie:cookies){
if (cookie.getName().equals("lastLoginTime")){
out.print("上次访问的时间:");
long time = Long.parseLong(cookie.getValue());
out.print(new Date(time).toLocaleString());
}
}
}
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
}
1.不设置有效期,关闭客户端就会删除cookie
2.设置有效期为0,响应到浏览器立马过期
3.Session(会话)
- 服务器登记访问的用户信息,下此服务器匹配用户(浏览器)
- 会话是此次打开浏览器-操作-关闭浏览器的完整过程
- 服务端技术
- 基本操作(看源码学习)
@WebServlet("/helloSession")
public class HelloSession extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;character=utf-8");
HttpSession session = req.getSession();
session.setAttribute("name","zhangsan");
String sessionId = session.getId();
if (session.isNew()){
resp.getWriter().write("新session:"+sessionId);
}else{
resp.getWriter().write("旧session:"+sessionId);
}
session.invalidate();
session.setMaxInactiveInterval(1);
}
}
1.保存用户登录信息
2.保存购物车信息
3.保存网站中经常使用的数据
- ServletContext与Session区别
![在这里插入图片描述](https://img-blog.csdnimg.cn/57a920a5a70642e4b25c28cb31f87d44.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiA5Liq5q2j5Zyo5Yqq5Yqb55qE6I-c6bih,size_20,color_FFFFFF,t_70,g_se,x_16)
4.一个网站怎么证明你来过?
- Cookie
![在这里插入图片描述](https://img-blog.csdnimg.cn/8a96e86a2002487cbb7955eac60c6496.png)
- Session
![在这里插入图片描述](https://img-blog.csdnimg.cn/26f8a44b30fd42138408b2dd1b06aac9.png)
- ServletContext
![在这里插入图片描述](https://img-blog.csdnimg.cn/a9f52576efde4b2fa50946f6f1126bec.png)
5.应用
private void number(HttpServletRequest request, HttpServletResponse response){
JsonModel jsonModel = new JsonModel();
int userid = 0;
String ip = getIpAddress(request);
String addr = "";
HttpSession session = request.getSession();
if(session.getAttribute("userid")==null){
userid = new Random().nextInt(1000);
session.setAttribute("userid",userid);
ServletContext application = request.getSession().getServletContext();
Map<String,Object> onlineuserMap = new HashMap<String,Object>();
List<Map<String,Object>> onlineuserList = null;
if(application.getAttribute("onlineuserList")==null){
onlineuserList = new ArrayList<Map<String,Object>>();
application.setAttribute("onlineuserList",onlineuserList);
}
onlineuserMap.put("userid",userid);
onlineuserMap.put("ip",ip);
onlineuserList = (List<Map<String, Object>>) application.getAttribute("onlineuserList");
onlineuserList.add(onlineuserMap);
}
userid = Integer.parseInt(session.getAttribute("userid").toString());
try {
jsonModel.setCode(1);
jsonModel.setData(userid);
super.writeJson(jsonModel,response);
} catch (IOException e) {
e.printStackTrace();
jsonModel.setCode(0);
jsonModel.setMsg(e.getMessage());
}
}
private void quit(HttpServletRequest request,HttpServletResponse response){
HttpSession session = request.getSession();
int id = Integer.parseInt(session.getAttribute("userid").toString());
ServletContext application = request.getServletContext();
List<Map<String,Object>> onlineuserList = (List<Map<String, Object>>) application.getAttribute("onlineuserList");
for (int i=0;i<onlineuserList.size();i++){
if(Integer.parseInt(onlineuserList.get(i).get("userid").toString())==id){
onlineuserList.remove(i);
break;
}
}
session.removeAttribute("userid");
JsonModel jsonModel = new JsonModel();
jsonModel.setCode(1);
try {
super.writeJson(jsonModel,response);
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendMessage(HttpServletRequest request,HttpServletResponse response){
ServletContext application = request.getServletContext();
HttpSession session = request.getSession();
int userid = Integer.parseInt(session.getAttribute("userid").toString());
String message = request.getParameter("message");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = simpleDateFormat.format(date);
List<String> messageList = null;
if (application.getAttribute("messageList")==null){
messageList = new ArrayList<String>();
application.setAttribute("messageList",messageList);
}
messageList = (List<String>) application.getAttribute("messageList");
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(userid+"说:<br />");
stringBuffer.append(message+"<br />");
stringBuffer.append("<div style='text-align:right'>"+time+"</div>");
messageList.add(stringBuffer.toString());
JsonModel jsonModel = new JsonModel();
jsonModel.setCode(1);
jsonModel.setData(messageList);
try {
super.writeJson(jsonModel,response);
} catch (IOException e) {
e.printStackTrace();
}
}
Filter
1.架构
![在这里插入图片描述](https://img-blog.csdnimg.cn/58fea626960c4834a2ba432aab29c8b3.png)
2.使用
- 导包不要错
![在这里插入图片描述](https://img-blog.csdnimg.cn/5d90cb082b1044ea8a95ee5f077a357a.png)
- 使用(重点都在注解)
@WebServlet(value = {"/showServlet","/filter/showServlet"})
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("你好世界!");
}
}
@WebFilter("/filter/*")
public class CharacterEncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;character=utf-8");
System.out.println("CharacterEncodingFilter过滤前");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("CharacterEncodingFilter过滤后");
}
@Override
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}