扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
目录
创新互联公司-专业网站定制、快速模板网站建设、高性价比囊谦网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式囊谦网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖囊谦地区。费用合理售后完善,10年实体公司更值得信赖。回顾
一.优化表白墙代码
二.Cookie 和 Session
1.Servlet中操作Cookie和Session Api
2.案例1:写一个模拟登录的案例:
3. 案例2:上传文件
1.Servlet API
2.HttpServlet
DoXXX处理哪种Http方法会调用到对应的方法
init/destroy/service--->servlet的生命周期
3.HttpServletRequest Http请求 get系列方法
协议名(版本号)
url
query string
header
query String/body
HttpServletResponse Http响应 set系列方法
状态码
各种header
body
当前表白墙写了多个DataSourse,使用单例模式优化
饿汉:类加载创建实例
懒汉:效率更高(首次调用创建实例)
public class DBUtil {
private static DataSource dataSource=null;
public DataSource getDataSource(){
//首次调用的时候创建实例
if(dataSource==null){
dataSource=new MysqlDataSource();
((MysqlDataSource)dataSource).setURL("jdbc:/mysql://127.0.0.1:3306/java105?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
//数据库的密码
((MysqlDataSource)dataSource).setPassword("1309411303");
}
return dataSource;
}
}
还要注意线程安全问题:
多个线程同时判定dataSouce为null,会创建多个实例
Servlet代码中,涉及到多线程/线程安全问题,
Servlet写的是一个服务器,同一时刻,可能要处理多个客户端的请求,一旦有多个客户端发送多个请求,服务器务必需要同时处理多个请求
Tomcat内部正式使用了多线程的方式
解决方案:
1.加上volatile
private static volatile DataSource dataSource=null;
2.加锁
3.构造方法私有
Cookie 是浏览器在本地持久化保存数据的一种方案
一个典型的使用方式,存储登录信息
在Servlet中也专门提供了相关的Api,让我们来操作Cookie和Session
方法 | 描述 |
HttpSession getSession() | 使用模式有俩中 参数填写 false 判定当前会话是否存在,如果不存在,直接返回对应的HttpSession对象 参数填写true,判定当前会话是否存在,如果不存在,就创建一个新的键值对,保存到哈希表中,并把生成的sessionId 返回到浏览器这里, 都是根据请求中的Cookie里的sessionId来查哈希表,如果存在则直接返回HttpSeeion对象 |
Cookie[]getCookie() | 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对 |
方法 | 描述 |
void addCookie(Cookie cookie) | 返回响应,你想给浏览器返回哪些cookie,都可以通过这个方法来添加 在这里添加的键值对,都会体现在Http响应报文的SetCookie字段上 |
方法 | 描述 |
Object getAttribute(String name) | 该方法返回在该 session 会话中具有指定名称的对象,如果没 有指定名称的对象,则返回 null |
void setAttribute(String name, Object value) | 该方法使用指定的名称绑定一个对象到该 session 会话 |
boolean isNew() | 判定当前是否是新创建出的会话 |
方法 | 描述 |
String getName() | 该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 Set Cooke 字段设置给浏览器的) |
String getValue() | 该方法获取与 cookie 关联的值 |
void setValue(String newValue) | 该方法设置与 cookie 关联的值。 |
一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息.
每个 Cookie 对象就是一个键值对
理解会话机制
服务器同一时刻收到的请求是很多的. 服务器需要清除的区分清楚每个请求是从属于哪个用户, 就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系
构思内容:
1.登录页面,用户可以填写用户名+密码
2.Servlet来处理登录请求
3.使用另一个Servlet来生成主页内容(登录成功后,跳转到的页面)
具体步骤
1.构造form表单发给Servlet处理(注意三点匹配关系)
name(getParameter),method ,action
2.Servlet进行判定
当用户点击提交的时候,就会把刚才input框的name的值作为key,把input框里用户的输入,作为value,把这个键值对,放到body中提交给服务器,name属性决定了键值对中的建,通过服务器getParameter获取值
这里将字符串写到前面,肯定不是空的,一定不会出现空指针异常(好处double check),虽然equls内部已经针对参数为null进行从处理了
3.登录成功创建新的会话(SessionId),设置键值对,并重定向到指定的页面
if("zhangsan".equals(username)&&"123".equals(password)){
//登陆成功
//a)创建一个会话,用户刚登录成功,之前是没有会话的,重新分配一个新的会话给用户
//创建sessionId和一个HttpSession 对象
//把这俩个内容以键值对的形式插入到内存的哈希表中
//把sessionId通过 set-cookie 写到响应中
HttpSession session=req.getSession(true);
//随意的设置键值对了(HttpSession 对象也相当于一个哈希表)
session.setAttribute("username","zhangsan");
//让响应重定向到主页
resp.sendRedirect("index");
}
4.登录失败
//登录失败
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("登录失败,用户名或密码错误");
5.重定向后生成的主页内容
//登录成功后,跳转到的主页
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//首页中先获取session,此处的session正是刚才登录页的时候,登录成功的逻辑中创建出来的
//此处参数写作false即可,表示不新建,如果不存在,就返回null即可
HttpSession session=req.getSession(false);
if(session==null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("你尚未登陆,不能访问主页");
return;
}
String username=(String) session.getAttribute("username");
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("欢迎来到主页!" +username);
}
}
理解3,5步骤
完整代码:处理登录请求+登录页面+跳转后的服务器响应
package login;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//使用这个类来处理登录请求
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.从请求中获取到页面提交的用户名和密码
String username=req.getParameter("username");
String password=req.getParameter("password");
//2.验证用户名密码是否正确
//正常这个操作是要查数据库,此处为了简单,直接写成硬编码了(把正确的用户名和密码写死了)
//假定正确的密码是 zhangsan 123
if("zhangsan".equals(username)&&"123".equals(password)){
//登陆成功
//a)创建一个会话,用户刚登录成功,之前是没有会话的,重新分配一个新的会话给用户
//创建sessionId和一个HttpSession 对象
//把这俩个内容以键值对的形式插入到内存的哈希表中
//把sessionId通过 set-cookie 写到响应中
HttpSession session=req.getSession(true);
//随意的设置键值对了(HttpSession 对象也相当于一个哈希表)
session.setAttribute("username","zhangsan");
//让响应重定向到主页
resp.sendRedirect("index");
}else{
//登录失败
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("登录失败,用户名或密码错误");
}
}
}
package login;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//登录成功后,跳转到的主页
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//首页中先获取session,此处的session正是刚才登录页的时候,登录成功的逻辑中创建出来的
//此处参数写作false即可,表示不新建,如果不存在,就返回null即可
HttpSession session=req.getSession(false);
if(session==null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("你尚未登陆,不能访问主页");
return;
}
String username=(String) session.getAttribute("username");
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("欢迎来到主页!" +username);
}
}
3. 案例2:上传文件前端,搭配form表单,允许通过浏览器选中一个文件,上传给服务器
方法 | 描述 |
Part getPart(String name) | 获取请求中给定 name 的文件 |
Collection | 获取所有的文件 |
String getSubmittedFileName() | 获取提交的文件名 |
String getContentType() | 获取提交的文件类型 |
long getSize() | 获取文件的大小 |
void write(String path) | 把提交的文件数据写入磁盘文件 |
方法 | 描述 |
String getSubmittedFileName() | 获取提交的文件名 |
String getContentType() | 获取提交的文件类型 |
long getSize() | 获取文件的大小 |
void write(String path) | 把提交的文件数据写入磁盘文件 |
注意对应关系
完整代码
@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part part=req.getPart("myfile");
System.out.println(part.getSubmittedFileName());
System.out.println(part.getSize());
System.out.println(part.getContentType());
part.write("c/program/result.jpg");
}
}
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流