欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第一天servlet

程序员文章站 2022-06-03 13:13:57
...

一、第一个JavaWeb项目

1.1编写一个java类继承HttpServlet方法

//myServlet.java
package com.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class myServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.getWriter().write("this is my first servlet.");
	}
}

1.2配置web.xml

<!-- 配置servlet路径 -->
<servlet>
	<servlet-name>my</servlet-name>
	<servlet-class>com.servlet.myServlet</servlet-class>
</servlet>
<!-- 配置访问方式 -->
<servlet-mapping>
	<servlet-name>my</servlet-name>
	<url-pattern>/my</url-pattern>
</servlet-mapping>
浏览器访问:
http://localhost:8000/test/my
浏览器显示:
this is my first servlet.

二、request和response对象

2.1servlet的生命周期

//ServletLeft.java
package com.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
 * Servlet的生命周期: 
 * 1、从第一次调用到服务器关闭。 
 * 2、如果Servlet在web.xml中配置了load-on-startup,生命周期为 从服务器启动到服务器关闭
 * 3、注意: * init方法是对Servlet进行初始化的一个方法,会在Servlet第一次 加载进行存储时执行 
 * 4、destory方法是在servlet被销毁时执行,也就服务器关闭时
 * 
 */
public class ServletLeft extends HttpServlet{
	//初始化方法,在servlet第一次加载内容时被调用
	@Override
	public void init() throws ServletException {
		System.out.println("servlet初始化完成");
	}
	
	//service方法,浏览器请求时被调用
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("service被调用");
	}
	
	//销毁方法,服务器关闭时调用
	@Override
	public void destroy() {
		System.out.println("servlet被销毁");
	}
}
<!--web.xml-->
<!-- 配置servlet路径 -->
<servlet>
	<servlet-name>lift</servlet-name>
	<servlet-class>com.servlet.ServletLeft</servlet-class>
</servlet>
<!-- 配置访问方式 -->
<servlet-mapping>
	<servlet-name>lift</servlet-name>
	<url-pattern>/lift</url-pattern>
</servlet-mapping>
控制台:
servlet初始化完成-------浏览器第一次请求时被调用
service被调用-----------浏览器每次请求调用
service被调用-----------浏览器每次请求调用
service被调用-----------浏览器每次请求调用
servlet被销毁-----------服务器关闭调用
<!--加上次标签则在服务器启动就调用-->
<load-on-startup>1</load-on-startup>
<!-- 配置servlet路径 -->
<servlet>
	<servlet-name>lift</servlet-name>
	<servlet-class>com.servlet.ServletLeft</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置访问方式 -->
<servlet-mapping>
	<servlet-name>lift</servlet-name>
	<url-pattern>/lift</url-pattern>
</servlet-mapping>

2.2service方法和doGet方法和doPost方法的使用和区别

package com.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
 * Service方法和doGet方法和doPost方法的区别
 * 	Service方法:
 * 		可以处理get/post方式的请求,如果servlet中有Service方法,会优先调用service方法对请求进行处理。
 * 	doGet方法:
 * 		处理get方式的请求
 * 	doPost方法:
 * 		处理post方式的请求
   *      注意:
 * 		如果在覆写的service方法中调用了父类的service方法(super.service(arg0, arg1)),
 * 		则service方法处理完后,会再次根据请求方式响应的doGet和doPost方法执行。所以,一般情况下
 * 		我们是不在覆写的service中调用父类的service方法的,避免出现405错误。
 */
public class ServletMethod extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("我是service方法");
		super.service(req, resp);
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("我是post方法");
	}
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("我是get方法");
	}
}

2.3Servlet的常见错误:

  •  404错误:资源未找到
    
  •  原因一:在请求地址中的servlet的别名书写错误。
    
  •  原因二:虚拟项目名称拼写错误
    
  •  500错误:内部服务器错误
    
  •  错误一:
    
  •  java.lang.ClassNotFoundException: com.bjsxt.servlet.ServletMothod
    
  •  解决:
    
  •  在web.xml中校验servlet类的全限定路径是否拼写错误。
    
  •  错误二:
    
  •  因为service方法体的代码执行错误导致
    
  •  解决:
    
  •  根据错误提示对service方法体中的代码进行错误更改。
    
  •  405错误:请求方式不支持
    
  •  原因:
    
  •  请求方式和servlet中的方法不匹配所造成的。
    
  •  解决:
    
  •  尽量使用service方法进行请求处理,并且不要再service方法中调用父类的service。
    

2.4request对象的介绍和获取请求头信息

作用:request对象中封存了当前请求的所有请求信息

使用:

获取请求头数据

获取请求行数据

获取用户数据

注意:

如果要获取的请求数据不存在,不会报错,返回null。

request对象由tomcat服务器创建,并作为实参传递给处理请求的servlet的service方法。

2.4.1获取请求头数据

<!--index.jsp-->
<body>
	<form action="request" method="post">
		用户名:<input type="text" name="username"><br>
		密码:<input type="password" name="password"><br>
		<input type="submit" value="登录">
	</form>
</body>
public class RequestServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取请求头数据
			//获取请求方式
				String method = req.getMethod();
				System.out.println("请求方式:"+method);
			//获取请求URL+URI
				StringBuffer url = req.getRequestURL();
				System.out.println("url地址:"+url);
				String uri = req.getRequestURI();
				System.out.println("uri地址:"+uri);
			//获取协议
				String h = req.getScheme();
				System.out.println("网络协议:"+h);
	}
}
浏览器:
http://localhost:8000/test/request
控制台:
请求方式:GET
url地址:http://localhost:8000/test/request
uri地址:/test/request
网络协议:http
浏览器:
http://localhost:8000/test/index.jsp
控制台:
请求方式:POST
url地址:http://localhost:8000/test/request
uri地址:/test/request
网络协议:http

2.4.2获取请求行数据

第一天servlet

public class RequestServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取请求行数据
			//获取指定的请求行信息
			String agent = req.getHeader("user-agent");
			System.out.println("用户代理:"+agent);
			String host = req.getHeader("host");
			System.out.println("host:"+host);
			System.out.println("-----------------------------------");
			//获取所有请求行的键的枚举
			Enumeration e = req.getHeaderNames();
			while(e.hasMoreElements()) {
				String name = (String)e.nextElement();
				String value2=req.getHeader(name);
				System.out.println(name+":"+value2);
			}
			
	}
}
浏览器:
http://localhost:8000/test/request
控制台:
用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
host:localhost:8000
-----------------------------------
host:localhost:8000
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
accept-encoding:gzip, deflate
connection:keep-alive
cookie:JSESSIONID=DC6B2BD41074E8A4BBF6605A93A80115
upgrade-insecure-requests:1

2.4.3获取用户数据

<body>
	<form action="request" method="post">
		用户名:<input type="text" name="username"><br />
		密码:<input type="password" name="password"><br />
		爱好:<br />
    	<input type="checkbox" name="hobbys" value="sing"/>唱歌<br />
    	<input type="checkbox" name="hobbys" value="dance"/>跳舞<br />
    	<input type="checkbox" name="hobbys" value="swim"/>游泳<br />
		<input type="submit" value="登录">
	</form>
</body>
public class RequestServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取用户数据
		String name=req.getParameter("username");
		String pwd=req.getParameter("password");
		System.out.println("用户名:"+name);
		System.out.println("密码:"+pwd);
		//获取所有的用户请求数据的键的枚举集合---req.getParameterNames()
		String[] hobbys=req.getParameterValues("hobbys");
		System.out.println("爱好:");
		if(hobbys!=null){
			for(String hobby:hobbys){
				System.out.print(hobby+" ");
			}
		}	
	}
}
浏览器:
http://localhost:8000/test/index.jsp
填入参数提交
控制台:
用户名:zhangsan
密码:123
爱好:
sing dance swim 

2.5response对象学习

Respone对象学习:

作用:

用来响应数据到浏览器的一个对象

使用:

1.设置响应头

2.设置响应状态

3.设置响应实体

4.设置响应编码格式:

2.5.1设置响应头

public class ResponseServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置响应头
		//setHeader会覆盖同名对象
		resp.setHeader("phone", "MI");
		resp.setHeader("phone", "HUAWEI");
		//addHeader不会覆盖同名对象
		resp.addHeader("laptop", "MAC");
		resp.addHeader("laptop", "ASUS");
	}
}

第一天servlet

2.5.2设置响应状态码

//设置响应状态码
resp.sendError(404,"this Method is not supported");

第一天servlet

2.5.3设置响应实体

//设置响应实体
resp.getWriter().write("<h1>response响应实体</h1>");

第一天servlet

2.5.4设置响应编码格式

//设置响应编码格式
//方法一:
resp.setHeader("content-type", "text/html;charset=utf-8");
//方法二:推荐使用
resp.setContentType("text/html;charset=utf-8");

第一天servlet

//其他格式
//plain:普通文本
resp.setContentType("text/plain;charset=utf-8");
//xml
resp.setContentType("text/xml;charset=utf-8");
//html
resp.setContentType("text/html;charset=utf-8");

例子:

public class ResponseServlet extends HttpServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置响应编码格式
		//resp.setHeader("content-type", "text/html;charset=utf-8");
		resp.setContentType("text/html;charset=utf-8");
		//设置响应实体
		resp.getWriter().write("<h1>response响应实体</h1>");
	}
}

第一天servlet

三.Servlet转发和重定向

3.1servlet登录练习

##创建用户表
create table t_user(
	uid int(10) not null auto_increment,
	uname varchar(100) not null,
	pwd varchar(100) not null,
	primary key(uid)
)
##添加测试数据
insert into t_user values(default,'zhangsan','123');
insert into t_user values(default,'lisi','456');
select * from t_user

第一天servlet

//登录页com.zh.servlet
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PageServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		// 处理请求
		// 响应处理结果
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<form action='login' method='get'>");
		resp.getWriter().write("用户名:<input type='text' name='uname' value=''/><br/>");
		resp.getWriter().write("密码:<input type='password' name='pwd' value=''/><br/>");
		resp.getWriter().write("<input type='submit'  value='登录'/><br/>");
		resp.getWriter().write("</form>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}
//登录验证页com.zh.servlet
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zh.model.User;
import com.zh.service.LoginService;
import com.zh.service.impl.LoginServiceImpl;

public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			resp.getWriter().write("登录成功");
		}else {
			resp.getWriter().write("登录失败");
		}
	}
}
//模型层 com.zh.model
package com.zh.model;

public class User {
	private int uid;
	private String uname;
	private String pwd;
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	@Override
	public String toString() {
		return "User [uid=" + uid + ", uname=" + uname + ", pwd=" + pwd + "]";
	}
}
//业务层接口com.zh.service
package com.zh.service;

import com.zh.model.User;

public interface LoginService {
	//校验用户登录信息
	public User CheckLoginService(String uname,String pwd);
}
//业务层实现com.zh.service.impl
package com.zh.service.impl;

import com.zh.dao.LoginDao;
import com.zh.dao.impl.LoginDaoImpl;
import com.zh.model.User;
import com.zh.service.LoginService;

public class LoginServiceImpl implements LoginService{
	//创建Dao层对象
	LoginDao ld = new LoginDaoImpl();
	@Override
    //校验用户登录信息
	public User CheckLoginService(String uname, String pwd) {
		
		return ld.checkLoginDao(uname, pwd);
	}
}
//持久层com.zh.dao接口
package com.zh.dao;

import com.zh.model.User;

public interface LoginDao {
	//根据用户名和密码获取用户信息
	public User checkLoginDao(String uname,String pwd);
}
//持久层实现com.zh.dao.impl
package com.zh.dao.impl;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.zh.dao.LoginDao;
import com.zh.model.User;

public class LoginDaoImpl implements LoginDao{

	//根据用户名和密码获取用户信息
	@Override
	public User checkLoginDao(String uname, String pwd) {
		//声明Jdbc对象
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		//声明数据存储对象
		User u = null;
		try {
			//加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获取连接对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
			//创建Sql命令
			String sql="select * from t_user where uname=? and pwd=?";
			//创建Sql命令对象
			ps=conn.prepareStatement(sql);
			//给占位符赋值
			ps.setString(1, uname);
			ps.setString(2, pwd);
			//执行
			rs=ps.executeQuery();
			//遍历执行结果
			while(rs.next()){
				u=new User();
				u.setUid(rs.getInt("uid"));
				u.setUname(rs.getString("uname"));
				u.setPwd(rs.getString("pwd"));
			}
			//关闭资源
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return u;
	}
}

第一天servlet

第一天servlet

第一天servlet

存在问题:

1.登录成功应该跳到成功页面

2.登录失败应该换回登录页面

3.2请求乱码问题解决和Servlet流程总结

请求中文乱码解决:

1、使用String进行数据重新编码

uname=new String(uname.getBytes("iso8859-1"),"utf-8");

2、使用公共配置

get方式:

​ 步骤一:req.setCharacterEncoding("utf-8");

​ 步骤二:在tomcat的目录下的conf目录中修改server.xml文件:在Connector标签中增加属性 useBodyEncodingForURI="true"

post方式:

req.setCharacterEncoding("utf-8");

第一天servlet

控制台
??:123
//使用String进行数据重新编码:用于重要数据编码
uname=new String(uname.getBytes("iso8859-1"),"utf-8");
//post方式
req.setCharacterEncoding("utf-8");
//get方式第一步
req.setCharacterEncoding("utf-8");
<!--get方式第二步server.xml-->
<Connector port="8089" protocol="AJP/1.3" redirectPort="8443" useBodyEncodingForURI="true"/>

3.3Servlet流程总结:

浏览器发起请求到服务器(请求)

服务器接受浏览器的请求,进行解析,创建request对象存储请求数据

服务器调用对应的servlet进行请求处理,并将request对象作为实参传递给servlet的方法

servlet的方法执行进行请求处理

  1. 设置请求编码格式
  2. 设置响应编码格式
  3. 获取请求信息
  4. 处理请求信息
  5. //创建业务层对象
  6. //调用业务层对象的方法
  7. //响应处理结果

3.4servlet学习-请求转发

请求转发学习:

  •  **作用:**实现多个servlet联动操作处理请求,这样避免代码冗余,让servlet的职责更加明确。
    
  •  **使用:**`req.getRequestDispatcher("要转发的地址").forward(req, resp);`
    
  •  **地址:**相对路径,直接书写servlet的别名即可。
    
  •  **特点:** **一次请求**,**浏览器地址栏信息不改变**。
    
  •  **注意:**请求转发后直接`return`结束即可。
    
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zh.model.User;
import com.zh.service.LoginService;
import com.zh.service.impl.LoginServiceImpl;

public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			resp.getWriter().write("登录成功");
		}else {
            //登录失败请求转发
			req.getRequestDispatcher("page").forward(req, resp);
			System.out.println("哈哈");
		}
	}
}
控制台:
zs:123
哈哈

分析:请求转发相当于调用方法下面的内容会执行

解决:使用return结束

req.getRequestDispatcher("page").forward(req, resp);
return;

3.5servlet学习-request对象的作用域

  • **问题:**使用请求转发后,不同的 Servlet 之间怎么进行数据的共享呢?或者说数据怎么从一个 servlet 流转给另外一个 Servlet 呢?
  • **解决:**使用 request 对象的作用域
  • 使用:request.setAttribute(objectname,Objectvalue); request.getAttribute(Objectobj);
  • **作用:**解决了一次请求内的不同 Servlet 的数据(请求数据+其他数据)共享问题。
  • **作用域:**基于请求转发,一次请求中的所有 Servlet 共享。
  • **注意:**使用 Request 对象进行数据流转,数据只在一次请求内有效。
  • **特点:**1.服务器创建 2.每次请求都会创建 3.生命周期一次请求
//存取request作用域对象
req.setAttribute("str", "用户名或密码错误");
//获取作用域对象
req.getAttribute("str")
//login.java登录处理页面
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zh.model.User;
import com.zh.service.LoginService;
import com.zh.service.impl.LoginServiceImpl;

public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			resp.getWriter().write("登录成功");
		}else {
			//存取request作用域对象
			req.setAttribute("str", "用户名或密码错误");
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}
//page.java 登录页面
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PageServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		// 处理请求
		// 响应处理结果
		//获取作用域对象
		String str = (String) req.getAttribute("str")==null?"":(String) req.getAttribute("str");
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<font color='red' size='20px'>"+str+"</font>");
		resp.getWriter().write("<form action='login' method='post'>");
		resp.getWriter().write("用户名:<input type='text' name='uname' value=''/><br/>");
		resp.getWriter().write("密码:<input type='password' name='pwd' value=''/><br/>");
		resp.getWriter().write("<input type='submit'  value='登录'/><br/>");
		resp.getWriter().write("</form>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}

登录页面

第一天servlet

输入错误的用户名密码转发后的页面

第一天servlet

3.6servlet学习-重定向学习

  • **重定向:**解决了表单重复提交的问题,以及当前servlet无法处理的请求的问题。

  • 使用:resp.sendRedirect(String uri);

  • 示例:resp.sendRedirect("/login/main");

  • 特点: 1.两次请求,两个request对象。2.浏览器地址栏信息改变

  • 时机:

    1.如果请求中有表单数据,而数据又比较重要,不能重复提交,建议使用重定向。

    2.如果请求被Servlet接收后,无法进行处理,建议使用重定向定位到可以处理的源。

//main登录成功后的页面
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MainServlet extends HttpServlet {
	
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
	//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
	//获取请求信息
	//处理请求信息
	//响应处理结果
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<h3>欢迎"+req.getParameter("uname")+"访问JAVA管理系统</h3>");
		resp.getWriter().write("<hr>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}
//login登录验证页面
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zh.model.User;
import com.zh.service.LoginService;
import com.zh.service.impl.LoginServiceImpl;

public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			//重定向
			resp.sendRedirect("/test/main");
		}else {
			//存取request作用域对象
			req.setAttribute("str", "用户名或密码错误");
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}

第一天servlet

第一天servlet

好处:防止了表单的重复提交

存在问题:因为存在两次请求,所以无法流转第一个servlet的数据

四、servlet学习-Cookie

4.1cookie的创建

//创建cookie对象
Cookie c = new Cookie("phone", "MI");
//响应cookie信息
resp.addCookie(c);
package cookie.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//创建cookie对象
		Cookie c = new Cookie("phone", "MI");
		//响应cookie信息
		resp.addCookie(c);
		//直接响应
		resp.getWriter().write("cookie学习");		
	}
}

第一天servlet

第一天servlet

特点:cookie会存储在浏览器的运行内存中,请求同项目其他地址会附带。

问题:关闭浏览器cookie会失效

解决:设置有效期

4.2cookie的有效期

//创建cookie对象
Cookie c = new Cookie("phone", "MI");
//设置cookie有效期(单位秒)
c.setMaxAge(3600*24*3);
//响应cookie信息
resp.addCookie(c);
package cookie.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//创建cookie对象
		Cookie c = new Cookie("phone", "MI");
		//设置cookie有效期(单位秒)
		c.setMaxAge(3600*24*3);
		//响应cookie信息
		resp.addCookie(c);
		//直接响应
		resp.getWriter().write("cookie学习");		
	}
}

第一天servlet

特点:cookie存储在硬盘中,在设置时间(3天)内不会失效

**问题:**同项目下每个请求都附带cookie

解决:设置cookie有效路径

4.3设置cookie有效路径

//创建cookie对象
Cookie c = new Cookie("phone", "MI");
//设置cookie有效期(单位秒)
c.setMaxAge(3600*24*3);
//设置有效路径
c2.setPath("/cookie/abc");
//响应cookie信息
resp.addCookie(c);
package cookie.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//创建cookie对象
		Cookie c = new Cookie("phone", "MI");
		//设置cookie有效期(单位秒)
		c.setMaxAge(3600*24*3);
		//设置cookie有效路径
		c.setPath("/cookie/abc");
		//响应cookie信息
		resp.addCookie(c);
		//直接响应
		resp.getWriter().write("cookie学习");		
	}
}

第一天servlet

第一天servlet

第一天servlet

作用:在访问/cookie/abc才会附带cookie信息,其他地址则不会附带

4.4Cookie信息的获取

//获取cookie信息
Cookie[] cks = req.getCookies();
if(cks!=null) {
	for(Cookie c:cks) {
		String name = c.getName();
		String value = c.getValue();
		System.out.println(name+":"+value);
	}
}
//存储cookie ck
package cookie.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//创建cookie对象
		Cookie c1 = new Cookie("phone", "MI");
		Cookie c2 = new Cookie("laptop", "HUAWEI");
		//设置cookie有效期(单位秒)
		c1.setMaxAge(3600*24*3);
		c2.setMaxAge(3600*24*3);
		//设置cookie有效路径
		c1.setPath("/cookie/gc");
		c2.setPath("/cookie/gc");
		//响应cookie信息
		resp.addCookie(c1);
		resp.addCookie(c2);
		//直接响应
		resp.getWriter().write("cookie学习");		
	}
}
//读取cookie gc
package cookie.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GetCookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取cookie信息
		Cookie[] cks = req.getCookies();
		if(cks!=null) {
			for(Cookie c:cks) {
				String name = c.getName();
				String value = c.getValue();
				System.out.println(name+":"+value);
			}
		}
	}
}

第一天servlet

第一天servlet

控制台
phone:MI
laptop:HUAWEI

4.5Cookie使用之三天免登陆

1.返回登录页面

//ck
package com.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		Cookie[] cks = req.getCookies();
		//处理请求信息
		if(cks!=null) {

		}else {
			//响应处理结果
			req.getRequestDispatcher("page").forward(req, resp);
		}
	}
}

第一天servlet

2.存储cookie信息

//创建Cookie信息实现三天免登录
Cookie c = new Cookie("uid", u.getUid()+"");
//设置cookie有效期
c.setMaxAge(3*24*3600);
//设置有效路径
c.setPath("/test/ck");
//添加cookie信息
resp.addCookie(c);
//login登录验证
package com.zh.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zh.model.User;
import com.zh.service.LoginService;
import com.zh.service.impl.LoginServiceImpl;

public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			//创建Cookie信息实现三天免登录
			Cookie c = new Cookie("uid", u.getUid()+"");
			//设置cookie有效期
			c.setMaxAge(3*24*3600);
			//设置有效路径
			c.setPath("/test/ck");
			//添加cookie信息
			resp.addCookie(c);
			//重定向
			resp.sendRedirect("/test/main");
		}else {
			//存取request作用域对象
			req.setAttribute("str", "用户名或密码错误");
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}
//ck免登录验证
package com.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		Cookie[] cks = req.getCookies();
		//处理请求信息
		if(cks!=null) {
			resp.sendRedirect("/test/main");
		}else {
			//响应处理结果
			req.getRequestDispatcher("page").forward(req, resp);
		}
	}
}

第一天servlet

第一天servlet

浏览器:
http://localhost:8000/test/ck
跳转到:
http://localhost:8000/test/main

存在问题:如果用户注销,而三天免登录cookie还在,用户还可以访问主页

解决:查数据库检查

3.查数据库验证

if(cks!=null) {
	//遍历cookie信息
	String uid="";
	for(Cookie c:cks) {
		//遍历cookie名为uid的key
		if("uid".equals(c.getName())) {
		//获取key为uid的值
		uid=c.getValue();
	}
	//检验uid是否存在
	if("".equals(uid)) {
			req.getRequestDispatcher("page").forward(req, resp);
			return;
	}else {
		//校验UID用户信息
		//获取业务层对象--查库
		LoginService ls = new LoginServiceImpl();
		User u = ls.checkUidService(uid);
			if(u!=null) {
				//重定向
				resp.sendRedirect("/test/main");
				return;
			}else {
			//响应处理结果
			req.getRequestDispatcher("page").forward(req, resp);
			return;
			}
		}
	}
}
//uid校验
package com.zh.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zh.model.User;
import com.zh.service.LoginService;
import com.zh.service.impl.LoginServiceImpl;

public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		Cookie[] cks = req.getCookies();
		//处理请求信息
		if(cks!=null) {
			//遍历cookie信息
			String uid="";
			for(Cookie c:cks) {
				//遍历cookie名为uid的key
				if("uid".equals(c.getName())) {
					//获取key为uid的值
					uid=c.getValue();
				}
				//检验uid是否存在
				if("".equals(uid)) {
					req.getRequestDispatcher("page").forward(req, resp);
					return;
				}else {
					//校验UID用户信息
					//获取业务层对象--查库
					LoginService ls = new LoginServiceImpl();
					User u = ls.checkUidService(uid);
					if(u!=null) {
						//重定向
						resp.sendRedirect("/test/main");
						return;
					}else {
						//响应处理结果
						req.getRequestDispatcher("page").forward(req, resp);
						return;
					}
				}
			}
		}else {
			//响应处理结果
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}
//service接口
package com.zh.service;

import com.zh.model.User;

public interface LoginService {
	//校验用户登录信息
	public User CheckLoginService(String uname,String pwd);

	//校验用户uid
	public User checkUidService(String uid);
}
//service实例
package com.zh.service.impl;

import com.zh.dao.LoginDao;
import com.zh.dao.impl.LoginDaoImpl;
import com.zh.model.User;
import com.zh.service.LoginService;

public class LoginServiceImpl implements LoginService{
	//创建Dao层对象
	LoginDao ld = new LoginDaoImpl();
	
	//校验用户登录信息
	@Override
	public User CheckLoginService(String uname, String pwd) {
		
		return ld.checkLoginDao(uname, pwd);
	}
	
	//校验用户uid
	@Override
	public User checkUidService(String uid) {
		return ld.checkUidDao(uid);
	}
}
//dao层接口
package com.zh.dao;

import com.zh.model.User;

public interface LoginDao {
	//根据用户名和密码获取用户信息
	public User checkLoginDao(String uname,String pwd);

	//根据uid获取用户信息
	public User checkUidDao(String uid);
}
//dao层实现
package com.zh.dao.impl;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.zh.dao.LoginDao;
import com.zh.model.User;

public class LoginDaoImpl implements LoginDao {

	// 根据用户名和密码获取用户信息
	@Override
	public User checkLoginDao(String uname, String pwd) {
		// 声明Jdbc对象
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		// 声明数据存储对象
		User u = null;
		try {
			// 加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 获取连接对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
			// 创建Sql命令
			String sql = "select * from t_user where uname=? and pwd=?";
			// 创建Sql命令对象
			ps = conn.prepareStatement(sql);
			// 给占位符赋值
			ps.setString(1, uname);
			ps.setString(2, pwd);
			// 执行
			rs = ps.executeQuery();
			// 遍历执行结果
			while (rs.next()) {
				u = new User();
				u.setUid(rs.getInt("uid"));
				u.setUname(rs.getString("uname"));
				u.setPwd(rs.getString("pwd"));
			}
			// 关闭资源
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return u;
	}

	// 根据uid获取用户信息
	@Override
	public User checkUidDao(String uid) {
		// 声明Jdbc对象
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		// 声明数据存储对象
		User u = null;
		try {
			// 加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 获取连接对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
			// 创建Sql命令
			String sql = "select * from t_user where uid=?";
			// 创建Sql命令对象
			ps = conn.prepareStatement(sql);
			// 给占位符赋值
			ps.setString(1, uid);
			// 执行
			rs = ps.executeQuery();
			// 遍历执行结果
			while (rs.next()) {
				u = new User();
				u.setUid(rs.getInt("uid"));
				u.setUname(rs.getString("uname"));
				u.setPwd(rs.getString("pwd"));
			}
			// 关闭资源
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return u;
	}
}

五、session学习

**问题:**一个用户的不同请求处理的数据共享怎么办?

**解决:**使用session技术

**原理:**用户第一次访问服务器,服务器会创建一个session对象给此用户,并将该session对象的JSESSIONID使用Cookie技术存储到浏览器中,保证用户的其他请求能够获取到同一个session对象,也保证了不同请求能够获取到共享的数据。

特点:1.存储在服务器端 2.服务器进行创建 3.依赖Cookie技术 4.一次会话 5.默认存储时间是30分钟

**作用:**解决了一个用户不同请求处理的数据共享问题

**简单理解:**用户第一次访问服务器,服务器将在服务器上创建一个柜子(session对象),并将打开柜子的钥匙(JSESSIONID)发送到浏览器存储(使用cookie技术),用户访问其他页面时就会附带这个钥匙(JSESSIONID)

总结:

session解决了一个用户的不同请求的数据共享问题,只要在JSESSIONID不失效和session对象不失效的情况下。

用户的任意请求在处理时都能获取到同一个session对象。

**作用域:**1.一次会话 2.在JSESSIONID和SESSION对象不失效的情况下为整个项目内。

**session失效处理:**将用户请求中的JSESSIONID和后台获取到的SESSION对象的JSESSIONID进行比对,如果一致

则session没有失效,如果不一致则证明session失效了。重定向到登录页面,让用户重新登录。

注意:JSESSIONID存储在了Cookie的临时存储空间中,浏览器关闭即失效。

5.1创建和获取session对象

//创建session对象
/*
	1.如果请求中拥有session的标识符也就是JSESSIONID,则返回其对应的session对象
	2.如果请求中没有session的标识符也就是JSESSIONID,则创建新的session对象,并将其JSESSIONID作为从cookie数据存储到浏览器内存中
  	3.如果session对象是失效了,也会重新创建一个session对象,并将其JSESSIONID存储在浏览器内存中。
*/
HttpSession hs = req.getSession();
public class SessionServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset;utf-8");
		//创建session对象
		HttpSession hs = req.getSession();
	}

}

第一天servlet

浏览器存储JSESSIONID,在访问同项目其他路径就会携带
失效3种情况
1.cookie被清除
2.关掉了浏览器
3.服务端的session超时被销毁
//获取session对象
HttpSession hs = req.getSession();
System.out.println("获取JJSESSIONID:"+hs.getId());
public class SessionServlet2 extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取session对象
		HttpSession hs = req.getSession();
		System.out.println("获取JJSESSIONID:"+hs.getId());
	}
}
浏览器:
http://localhost:8000/session/ss2
控制台:
获取JJSESSIONID:F600094776C95430C610E678AA4AA0C1

5.2设置session存储时间

//创建session对象
HttpSession hs = req.getSession();
//设置session存储时间(单位秒)
hs.setMaxInactiveInterval(5);
public class SessionServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset;utf-8");
		//创建session对象
		HttpSession hs = req.getSession();
		//设置session存储时间(单位秒)
		hs.setMaxInactiveInterval(5);
	}
}

第一天servlet

第一天servlet

超时访问生成新的JSESSIONID
在指定的时间内session对象没有被使用则销毁,如果使用了则重新计时。
如果在5秒内又访问则又重新计时5秒,session对象不会销毁

5.3设置session强制失效

作用:当用户退出登录时主动销毁session

//设置强制失效
hs.invalidate();
public class SessionServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset;utf-8");
		//创建session对象
		HttpSession hs = req.getSession();
		//设置session存储时间(单位秒)
		hs.setMaxInactiveInterval(5);
		//设置强制失效
		hs.invalidate();
	}

}

5.4session存储和获取数据

//存储数据
String name = "张三";
hs.setAttribute("name", name);
public class SessionServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset;utf-8");
		//创建session对象
		HttpSession hs = req.getSession();
		//存储数据
		String name = "张三";
		hs.setAttribute("name", name);
	}
}
//取数据
hs.getAttribute("name")
public class SessionServlet2 extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取session对象
		HttpSession hs = req.getSession();
		System.out.println("获取JJSESSIONID:"+hs.getId());
		System.out.println("name:"+hs.getAttribute("name"));
	}

}

存数据

第一天servlet

取数据

浏览器:
http://localhost:8000/session/ss2
控制台
获取JJSESSIONID:9B9D3A88910624E8FE79E93F0E0883AB
name:张三

存储和获取数据

存储:hs.setAttribute(String name,Object value);

获取:hs.getAttribute(String name) 返回的数据类型为Object

注意:存储的动作和取出的动作发生在不同的请求中,但是存储要先于取出执行。

**使用时机:**一般用户在登陆web项目时会将用户的个人信息存储到Sesion中,供该用户的其他请求使用。

5.5修改session默认失效时间

<!--D:\tomcat\conf\web.xml-->
<!--注意:
1.全局模式:修改tomcat下的web.xml,tomcat下所有项目有效
2.局部模式:在项目下的web.xml添加如下代码
-->
<session-config>
   <session-timeout>30</session-timeout>
</session-config>

5.6session登录练习使用解决null显示问题

思路:

1.在登录验证servlet中存入session对象,在主页取出session对象

2.存在问题:因为三天免登录,在退出浏览器session对象销毁,主页将不能取出数据造成空指针异常

3.在cookie验证页面验证后,存储session

4.在主页添加查看个人信息按钮

1.存取数据

//将数据存储到session对象中
HttpSession hs = req.getSession();
hs.setAttribute("user", u);
//取数据
HttpSession hs = req.getSession();
User u = (User) hs.getAttribute("user");
resp.getWriter().write("<h3>欢迎"+u.getUname()+"访问JAVA管理系统</h3>");
//存数据
public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			//创建Cookie信息实现三天免登录
			Cookie c = new Cookie("uid", u.getUid()+"");
			//设置cookie有效期
			c.setMaxAge(3*24*3600);
			//设置有效路径
			c.setPath("/test/ck");
			//添加cookie信息
			resp.addCookie(c);
			//将数据存储到session对象中
			HttpSession hs = req.getSession();
			hs.setAttribute("user", u);
			//重定向
			resp.sendRedirect("/test/main");
		}else {
			//存取request作用域对象
			req.setAttribute("str", "用户名或密码错误");
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}
public class MainServlet extends HttpServlet {
	
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
	//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
	//获取请求信息
		HttpSession hs = req.getSession();
		User u = (User) hs.getAttribute("user");
	//处理请求信息
	//响应处理结果
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<h3>欢迎"+u.getUname()+"访问JAVA管理系统</h3>");
		resp.getWriter().write("<hr>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}

第一天servlet

存在问题:在退出浏览器session对象销毁,主页将不能取出数据造成空指针异常

解决:在cookie免登录验证页存入session

2.存取数据

/ck
public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			//创建Cookie信息实现三天免登录
			Cookie c = new Cookie("uid", u.getUid()+"");
			//设置cookie有效期
			c.setMaxAge(3*24*3600);
			//设置有效路径
			c.setPath("/test/ck");
			//添加cookie信息
			resp.addCookie(c);
			//将数据存储到session对象中
			HttpSession hs = req.getSession();
			hs.setAttribute("user", u);
			//重定向
			resp.sendRedirect("/test/main");
		}else {
			//存取request作用域对象
			req.setAttribute("str", "用户名或密码错误");
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}

3.添加查看个人信息

resp.getWriter().write("<form action='show' method='get'>");
resp.getWriter().write("<input type='submit' value='查看个人信息'>");
resp.getWriter().write("</form>");
//main
public class MainServlet extends HttpServlet {
	
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
	//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
	//获取请求信息
		HttpSession hs = req.getSession();
		User u = (User) hs.getAttribute("user");
	//处理请求信息
	//响应处理结果
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<h3>欢迎"+u.getUname()+"访问JAVA管理系统</h3>");
		resp.getWriter().write("<hr>");
		resp.getWriter().write("<form action='show' method='get'>");
		resp.getWriter().write("<input type='submit' value='查看个人信息'>");
		resp.getWriter().write("</form>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}
//show
public class ShowServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 设置请求编码格式
		req.setCharacterEncoding("utf-8");
		// 设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		// 获取请求信息
		HttpSession hs = req.getSession();
		if (hs.getAttribute("user") == null) {
			// 重定向
			resp.sendRedirect("/login/ck");
			return;
		}
		User u = (User) hs.getAttribute("user");
		// 处理请求信息
		// 响应处理结果
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<table border='1px'>");
		resp.getWriter().write("<tr>");
		resp.getWriter().write("<td>用户名</td>");
		resp.getWriter().write("<td>" + u.getUname() + "</td>");
		resp.getWriter().write("</tr>");
		resp.getWriter().write("<tr>");
		resp.getWriter().write("<td>密码</td>");
		resp.getWriter().write("<td>" + u.getPwd() + "</td>");
		resp.getWriter().write("</tr>");
		resp.getWriter().write("</table>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}

第一天servlet

第一天servlet

六、ServletContext对象学习

ServletContext对象学习:

**问题:**不同的用户使用相同的数据

**解决:**ServletContext对象

特点: 1.服务器创建 2.用户共享

**作用域:**整个项目内

**生命周期:**服务器启动到服务器关闭

6.1获取ServletContext对象三种方法

//获取servletContext的三种方式:
//第一种方式(常用)
ServletContext sc1 = this.getServletContext();
//第二种方式
ServletContext sc2 = this.getServletConfig().getServletContext();
//第三种方式(常用)
ServletContext sc3 = req.getSession().getServletContext();
public class ServletContextServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取servletContext的三种方式:
		//第一种方式
		ServletContext sc1 = this.getServletContext();
		//第二种方式
		ServletContext sc2 = this.getServletConfig().getServletContext();
		//第三种方式
		ServletContext sc3 = req.getSession().getServletContext();
		System.out.println(sc1==sc2);
		System.out.println(sc1==sc3);
	}
}
浏览器:
http://localhost:8000/ServletContext/context
控制台:
true
true
结论:通过三种方式拿到的是同一个对象

6.2使用ServletContext对象的存取

数据存储 sc.setAttribute(String name, Object value);

数据获取sc.getAttribute("str") 返回的是Object类型

注意:不同的用户可以给ServletContext对象进行数据的存取。获取的数据不存在返回null。

//数据存储
sc.setAttribute("str", "servletcontext学习");
//获取数据
sc.getAttribute("str");
//数据存储
public class ServletContextServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取servletContext的三种方式:
		//第一种方式
		ServletContext sc1 = this.getServletContext();
		//使用ServletContext对象完成数据共享
		//数据存储
		sc1.setAttribute("str", "servletcontext学习");
	}
}
//数据获取
public class ServletContextServlet2 extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//创建servletcontext对象
		ServletContext sc = this.getServletContext();
		//获取数据
		System.out.println(sc.getAttribute("str"));
	}

}
浏览器:
先 http://localhost:8000/ServletContext/context
后 http://localhost:8000/ServletContext/context2
控制台
servletcontext学习

6.3获取项目中web.xml文件中的全局配置数据

获取项目中web.xml文件中的全局配置数据

sc.getInitParameter(String name); 根据键的名字返回web.xml中配置的全局数据的值,返回String类型。

如果数据不存在返回null。

sc.getInitParameterNames();返回键名的枚举

**配置方式:**注意 一组标签只能存储一组键值对数据,多组可以声明多个 进行存储。
作用: 将静态数据(不可改变)和代码进行解耦。对于一些重要数据的修改避免改源码。

<!-- 配置全局数据 -->
<context-param>
  <param-name>name</param-name>
  <param-value>zhangsan</param-value>
</context-param>
<!-- 配置多个全局参数 -->
<context-param>
  <param-name>name</param-name>
  <param-value>zhangsan</param-value>
</context-param>
<context-param>
  <param-name>age</param-name>
  <param-value>18</param-value>
</context-param>
//获取项目web.xml的全局配置数据
String name = sc.getInitParameter("name");
System.out.println(name);
public class ServletContextServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取servletContext的三种方式:
		//第一种方式
		ServletContext sc = this.getServletContext();
		//使用ServletContext对象完成数据共享
		//数据存储
		sc.setAttribute("str", "servletcontext学习");
		//获取项目web.xml的全局配置数据
		String name = sc.getInitParameter("name");
		System.out.println("全局参数:"+name);
	}
}
控制台:
全局参数:zhangsan

6.4获取项目webroot下的资源的绝对路径和流对象。

1.获取项目webroot下的资源的绝对路径,eclipse下为WebContent

第一天servlet

//获取项目根目录下的资源的绝对路径
1.String path = "D:\\apache-tomcat-7.0.56\\webapps\\sc\\doc\\1.txt";
System.out.println(path);
//存在问题,当项目部署到远程服务器或没有D盘将出错
//获取项目根目录下的资源的绝对路径
2.String path = sc.getRealPath("/doc/1.txt");
System.out.println(path);

2.获取webroot下的资源的流对象

//获取项目根目录下资源的流对象
InputStream is = sc.getResourceAsStream("/doc/1.txt");

注意:此种方式只能获取项目根目录下的资源流对象,class文件的流对象需要使用类加载器获取。

6.5使用ServletContext对象完成网页计数器

  •  在用户登录校验中创建计数器并自增,然后存储到ServletContext对象中
    
  •  在主页面里取出计数器数据显示给用户即可。
    
//创建网络计数器
//获取计数器数据
ServletContext sc = this.getServletContext();
int nums = (int) sc.getAttribute("nums");
//计数器自增
nums+=1;
//再次存储到ServletContext对象中
sc.setAttribute("nums", nums);

问题:在第一次访问的时候ServletContext中还没有nums,直接取将会报空指针异常

解决:访问时先判断nums是否为空,如果为空就给nums存一个1

//获取计数器数据
ServletContext sc = this.getServletContext();
if(sc.getAttribute("nums")!=null) {
	int nums = (int) sc.getAttribute("nums");
	//计数器自增
	nums+=1;
	//再次存储到ServletContext对象中
	sc.setAttribute("nums", nums);
}else {
	sc.setAttribute("nums", 1);
}
//获取人数
ServletContext sc = this.getServletContext();
int nums = (int) sc.getAttribute("nums");
//简写
int nums = (int)this.getServletContext().getAttribute("nums");
resp.getWriter().write("当前访问人数:"+nums);
//获取计数器存数据
public class LoginServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		System.out.println(uname+":"+pwd);
		//处理请求信息
		//获取业务层对象
		LoginService ls = new LoginServiceImpl();
		//响应处理结果
		User u=ls.CheckLoginService(uname, pwd);
		if(u!=null) {
			//创建Cookie信息实现三天免登录
			Cookie c = new Cookie("uid", u.getUid()+"");
			//设置cookie有效期
			c.setMaxAge(3*24*3600);
			//设置有效路径
			c.setPath("/test/ck");
			//添加cookie信息
			resp.addCookie(c);
			//将数据存储到session对象中
			HttpSession hs = req.getSession();
			hs.setAttribute("user", u);
			//创建网络计数器
			//获取计数器数据
			ServletContext sc = this.getServletContext();
			if(sc.getAttribute("nums")!=null) {
				int nums = (int) sc.getAttribute("nums");
				//计数器自增
				nums+=1;
				//再次存储到ServletContext对象中
				sc.setAttribute("nums", nums);
			}else {
				sc.setAttribute("nums", 1);
			}
			//重定向
			resp.sendRedirect("/test/main");
		}else {
			//存取request作用域对象
			req.setAttribute("str", "用户名或密码错误");
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}
//获取人数
public class MainServlet extends HttpServlet {
	
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//获取请求信息
		int nums = (int)this.getServletContext().getAttribute("nums");
	//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
	//获取请求信息
		HttpSession hs = req.getSession();
		User u = (User) hs.getAttribute("user");
	//处理请求信息
	//响应处理结果
		resp.getWriter().write("<html>");
		resp.getWriter().write("<head>");
		resp.getWriter().write("</head>");
		resp.getWriter().write("<body>");
		resp.getWriter().write("<h3>欢迎"+u.getUname()+"访问JAVA管理系统</h3>");
		resp.getWriter().write("当前访问人数:"+nums);
		resp.getWriter().write("<hr>");
		resp.getWriter().write("<form action='show' method='get'>");
		resp.getWriter().write("<input type='submit' value='查看个人信息'>");
		resp.getWriter().write("</form>");
		resp.getWriter().write("</body>");
		resp.getWriter().write("</html>");
	}
}
第一次访问
http://localhost:8000/test/ck 
输入密码登录
第二访问
http://localhost:8000/test/page
输入密码登录

第一天servlet

再次访问ck
http://localhost:8000/test/ck 

第一天servlet

问题:应为cookie校验通过–>没有走login验证–>没有进行nums加1

解决:在cookie验证通过中也加入+1操作

//cookie验证 ck
public class CookieServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		Cookie[] cks = req.getCookies();
		//处理请求信息
		if(cks!=null) {
			//遍历cookie信息
			String uid="";
			for(Cookie c:cks) {
				//遍历cookie名为uid的key
				if("uid".equals(c.getName())) {
					//获取key为uid的值
					uid=c.getValue();
				}
				//检验uid是否存在
				if("".equals(uid)) {
					req.getRequestDispatcher("page").forward(req, resp);
					return;
				}else {
					//校验UID用户信息
					//获取业务层对象--查库
					LoginService ls = new LoginServiceImpl();
					User u = ls.checkUidService(uid);
					if(u!=null) {
						//获取计数器数据
						int nums = (int) this.getServletContext().getAttribute("nums");
						nums+=1;
						//存入数据
						this.getServletContext().setAttribute("nums", nums);
						//重定向
						HttpSession hs = req.getSession();
						hs.setAttribute("user", u);
						resp.sendRedirect("/test/main");
						return;
					}else {
						//响应处理结果
						req.getRequestDispatcher("page").forward(req, resp);
						return;
					}
				}
			}
		}else {
			//响应处理结果
			req.getRequestDispatcher("page").forward(req, resp);
			return;
		}
	}
}
第一次访问
http://localhost:8000/test/ck 
输入密码登录
第二次访问
http://localhost:8000/test/ck 
第三次访问
http://localhost:8000/test/ck 

第一天servlet

问题:当服务器重启或关闭的时候数据就失效

解决:新建一个servlet加入初始化方法和销毁方法,当服务器开启时读入数据,销毁时存入到文件中

第一天servlet

//销毁方法--关闭服务器将数据存入nums.txt
public void destroy() {
		//获取计数器
		ServletContext sc = this.getServletContext();
		int nums = (int)sc.getAttribute("nums");
		//获取文件路径
		String path = sc.getRealPath("/nums/nums.txt");
		//声明流对象
		BufferedWriter bw = null;
		FileWriter fw = null;
		try {
			fw=new FileWriter(path);
			bw=new BufferedWriter(fw);
			bw.write(nums+"");
			bw.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				fw.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				bw.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
//初始化方法---将从nums中读入数据
public void init() throws ServletException {
		//获取文件中的计数器数据
			//获取文件路径
			String path=this.getServletContext().getRealPath("/nums/nums.txt");
			//声明流对象
			FileReader fr=null;
			BufferedReader br=null;
			try {
				fr=new FileReader(path);
				br=new BufferedReader(fr);
				int nums=Integer.parseInt(br.readLine());
				System.out.println(nums);
				this.getServletContext().setAttribute("nums", nums);
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
	}
<!--<load-on-startup>1</load-on-startup>初始化加载-->
<servlet>
  <description></description>
  <display-name>NumServlet</display-name>
  <servlet-name>NumServlet</servlet-name>
  <servlet-class>com.zh.servlet.NumServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

第一天servlet

七、servlet学习-servletConfig对象

  • ServletConfig对象学习:
  • 问题:如何获取在web.xml中给每个servlet单独配置的数据呢?
  • **解决:**使用ServletConfig对象
  • **使用:**获取ServletConfig对象获取web.xml中的配置数据
  <!--web.xml配置
  	注意:需要配置到servlet里面
  -->
  <servlet>
    <description></description>
    <display-name>ServletConfigServlet</display-name>
    <servlet-name>ServletConfigServlet</servlet-name>
    <servlet-class>com.zh.servlet.ServletConfigServlet</servlet-class>
    <init-param>
    	<param-name>name</param-name>
    	<param-value>config</param-value>
    </init-param>
  </servlet>
//获取ServletConfig对象
ServletConfig sc = this.getServletConfig();
//获取web.xml中配置的数据
String name = sc.getInitParameter("name");
public class ServletConfigServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取ServletConfig对象
		ServletConfig sc = this.getServletConfig();
		//获取web.xml中配置的数据
		String name = sc.getInitParameter("name");
		System.out.println(name);
	}
}
浏览器:
http://localhost:8000/ServletConfig/config
控制台:
config