互联网项目三高问题:高性能,高并发,高可用.
互联网服务提供商(Internet Service Provider),简称ISP,指的是面向公众提供下列信息服务的经营者.
浏览器地址栏输入www.baidu.com后按下回车之后会发生什么事情?
-
检查本机的hosts配置文件下有没有这个域名映射;有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
127.0.0.1 www.ling111.top
没有:去DNS服务器里找,找到的话就返回,找不到就返回找不到(400);
-
Tcp的三次握手(来确认信息);
-
找到相对应的资源库;
-
返回相对应的页面及进行页面的解析(比如里面有html,js,css时会找到对应的服务器);
-
解析完毕后返回客户端.
tcp三次握手四次挥手
为什么A要先进入TIME-WAIT状态,等待2MSL时间后才进入CLOSED状态?
MSL 是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。2MSL,2倍MSL.
为了保证B能收到A的确认应答。
若A发完确认应答后直接进入CLOSED状态,那么如果该应答丢失,B等待超时后就会重新发送连接释放请求,但此时A已经关闭了,不会作出任何响应,因此B永远无法正常关闭- 可靠的终止TCP连接;
- 保证让迟来的TCP报文段有足够的时间被识别并丢弃.
https://www.cnblogs.com/cenglinjinran/p/8482412.html
https://blog.csdn.net/yu876876/article/details/81560122
TCP中的time_wait状态
dos拒绝服务和ddos分布式拒绝服务
dos:少量进行攻击
ddos:多台进行攻击
- SYN FLOOD缓冲区攻击
- IP欺骗DOS攻击,攻击时,伪造大量的IP地址,向目标发送RST数据,使服务器不对合法用户服务。
- 带宽DOS攻击
- 自身消耗的DOS攻击,把请求客户端IP和端口弄成主机的IP端口相同,发送给主机。使得主机给自己发送TCP请求和连接。这种主机的漏洞会很快把资源消耗光。直接导致当机。这中伪装对一些身份认证系统还是威胁巨大的。
- 塞满服务器的硬盘,ftp,发送垃圾邮件,日志记录满.
CDN(内容分发网络)
CDN的全称是Content Delivery Network,即内容分发网络.CDN是构建在网络上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡,内容分发,调度等功能模块;使用户就近索取所需内容,降低网络拥堵,提高用户访问响应速度和命中率.
原理:广泛采用各种缓存服务器将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网络中利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,用缓存服务器直接相应用户请求.
网站应该有的结构
--webapp:Tomcat服务器的web目录
-root
-ling111:网站的目录名
-WEB-INF
-classes:Java程序
-lib:web应用所需要的依赖jar包
-web.xml:网站配置文件
-index.html 默认的首页
-static
-css
-js
-img
...
get:请求能够携带的参数比较少,大小有限,会在浏览器的URL地址显示数据内容,不安全,但高效.
post:请求能够能够携带的参数没有限制,大小没有限制,不会再浏览器的URL地址栏显示数据内容,安全但不高效.
maven:自动导入和配置jar包,约定大约配置.
Servlet
1997年Servlet1.0到现在Servlet4.0(Java EE 8),servlet3.0推出Filter,Listener,注解(无需再web.xml中配置).
Applet:这是纯客户端(浏览器)方案,applet就是浏览器中的Java插件,浏览器通过它就能够解释执行WEB服务器发过来的Java代码,从而实现动态。但是,显然这种方案不好,既需要浏览器必须安装插件,又受限于浏览器,所以Java代码不能太多和太复杂。
Servlet :既然浏览器不方便执行Java代码,那自然还是服务端来执行了,所以Servlet出现了,Servlet就是server端的applet的意思。
Servlet生命周期三个阶段:
-
init()方法(初始化): 仅执行一次;
-
Service(): 负责相应客户端请求;
Servlet是线程不安全的,在Servlet类中可能会定义共享的类变量,这样在并发的多线程访问的情况下,不同的线程对成员变量的修改会引发错误。 -
destory()方法:控制所有运行在Servlet中的线程在Servlet实例被销毁之前能正常运行结束.
- 恢复一些初始化的变量
- 释放资源
- 控制所有运行在Servlet中的线程在Servlet实例被销毁之前能正常运行结束
- 记录日志信息
注意: 1) destroy()在生命周期中仅被调用一次
2) 用户定义的Servlet中可以不覆盖destroy()
注解:@WebServlet({"/AdministratorsServlet"}),不要忘记"/"
写的Servlet类要extends HTTPServlet
Service()
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 获取请求数据
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 获取操作类型
String method = req.getParameter("method");
if ("add".equals(method)) {
add(req, resp);
} else if ("list".equals(method)) {
list(req, resp);
} else if ("search".equals(method)) {
search(req, resp);
} else if ("delete".equals(method)) {
delete(req, resp);
} else if ("Jumpup".equals(method)) {
Jumpup(req, resp);
} else if ("update".equals(method)) {
update(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
idea自动生成的doget和dopost,要把super改成this(或不要this.).
Servlet原理
Mapping问题
在web.xml里面写
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
ServletContext,共享数据
//存数据
ServletContext context = this.getServletContext();
String username = "秦疆"; //数据
context.setAttribute("username",username); //将一个数据保存在了 ServletContext中,名字为:username 。值 username
//取数据
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字"+username);
请求转发和重定向
//转发:由服务器端进行的页面跳转
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
//requestDispatcher.forward(req,resp); //调用forward实现请求转发;
context.getRequestDispatcher("/gp").forward(req,resp);
}
//重定向:由浏览器端进行的页面跳转
response.sendRedirect("login.jsp");
-
什么时候使用转发和重定向?
如果要保留请求域中的数据,使用转发,否则使用重定向.
访问数据库增删改查使用重定向,查询使用转发.
-
转发或重定向后续的代码是否还会运行?
无论转发还是重定向后续的代码都会执行.
-
转发和重定向的区别
区别 转发forwar() 重定向sendRedirect() 根目录 包含项目访问地址 没有项目访问地址 地址栏 不变 改变 跳转 服务器端进行跳转 浏览器端进行跳转 请求域的数据 不会丢失 会丢失 HttpServletRequest和HttpServletResponse
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应一些信息:找HttpServletResponse
Cookie和Session
session:服务器登记你来过了,下次你来的时候我来匹配你.(登记表)
保存用户的会话信息,把信息或者数据放到session中.
登录网站之后下次不用登录,session的默认时间是30分钟.
cookie:服务器端给客户端一个新建,客户端下次访问服务器带上信件就可以.(介绍信)
session使用场景:
-
保存一个登录用户的信息;
-
购物车信息;
-
在整个网站中经常使用的数据.
cookie:一般会保存在本地的 用户目录下 appdata;
- 一个cookie只能保存一个信息;
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
- cookie大小限制4kb;
- 300个cookie浏览器上限.
删除cookie:
-
不设置有效期,关闭浏览器,自动失效;
-
设置有效期时间为0.
Session和cookie的区别:
- cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个);
- session把用户的数据写到用户独占的session中,服务器端保存(保存重要信息,减少服务器的资源浪费);
- session对象由服务创建.
cookie
服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得Cookie cookie.getName(); //获得cookie中的key cookie.getValue(); //获得cookie中的vlaue new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie cookie.setMaxAge(24*60*60); //设置cookie的有效期 resp.addCookie(cookie); //响应给客户端一个cookie
cooki编码和解码:
URLEncoder.encode("上海","utf-8") URLDecoder.decode(cookie.getValue(),"UTF-8")
session
创建Session:
package com.kuang.servlet; import com.kuang.pojo.Person; import javax.servlet.ServletException; import javax.servlet.http.*; import java.io.IOException; public class SessionDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码问题 req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=utf-8"); //得到Session HttpSession session = req.getSession(); //给Session中存东西 session.setAttribute("name",new Person("秦疆",1)); //获取Session的ID String sessionId = session.getId(); //判断Session是不是新创建 if (session.isNew()){ resp.getWriter().write("session创建成功,ID:"+sessionId); }else { resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId); } //Session创建的时候做了什么事情; // Cookie cookie = new Cookie("JSESSIONID",sessionId); // resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
获取session:
//得到Session HttpSession session = req.getSession(); Person person = (Person) session.getAttribute("name"); System.out.println(person.toString()); HttpSession session = req.getSession(); session.removeAttribute("name"); //手动注销Session session.invalidate();
会话自动过期:web.xml配置
<!--设置Session默认的失效时间--> <session-config> <!--15分钟后Session自动失效,以分钟为单位--> <session-timeout>15</session-timeout> </session-config>
JSP
Java Service Pages:Java服务器端页面,和Servlet一样,用户动态Web技术.
特点:
-
写jsp就像在写HTML
-
HTML只能提供静态的数据,jsp页面中可以嵌入Java代码
原理:jsp到底怎执行的
-
代码层面没有任何问题
-
服务器内部工作
tomcat中有一个work目录
index.jps 页面变成Java程序,index_jsp.java index_jsp.class
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet.
jsp最终也会被转换成为一个Java类.
jsp本质上就是一个Servlet
//初始化 public void _jspInit() { } //销毁 public void _jspDestroy() { } //JSPService public void _jspService(.HttpServletRequest request,HttpServletResponse response)
9大内置对象
- PageContext 存数据
- Request 存数据
- Response
- session 存数据
- Application [ServletContext]存数据
- config [ServletConfig]
- out
- page 不用了解
- Exception
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效 request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据 session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器 application.setAttribute("name4","秦疆4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;
EL表达式${}
-
获取数据
-
执行运算
-
获取web开发的常用对象
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!
JavaBean
实体类(POJO,entity)
JavaBean特定的写法:
-
必须要有一个无参构造器(也可以不写但不建议)
-
属性必须私有化
-
必须有对应的get/set方法
在 JavaBean 里,一般参数在4个以上的,极不推荐使用带参数构造函数赋值:
1. 对于一个实体类,对于多个参数,降低可读性
2. 需要记住构造参数的顺序
3. 一个参数无效就会造成整个构造函数失效
4. 当我们要添加新的属性时,不仅要传参数,还要修改构造函数,同时之前所有的构造都要修改
5. 必须在对象创建之前给参数赋值,而不可以在对象创建后赋值
使用set方法的优势:
1. 我们可以显式的看到赋值元素的名称
2. 可以以任何顺序赋值
3. 可以忽略一些元素的初始化
4. 添加新属性时,不需要修改类
5. 可以在对象创建后赋值
所以对于javaBean,最好的方法就是只定义一个无参数构造函数,然后用set方法来赋值
一个类可以重载多个构造函数,只要他们的参数不同,当没有声明构造函数时,java将自动创建构造函数,若已声明带参数构造函数,必须声明无参数构造函数
否则当你调用无参数构造函数时,将会编译错误对于一个普通的没有父类的类:
TO a class that has not a explicit super class then it has an implicit superclass of Object,which does have a no-argument constructor.
一般用来和数据库的字段做映射ORM;
JavaBean作用:开发中的可重用组件,减少重复代码,使jsp代码的开发更简洁.
MVC
以前的架构MV
MVC架构
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
↑
JDBC (实现该接口)
↑
Mysql Oracle SqlServer ....(不同厂商)
Model
- 业务处理 :业务逻辑(Service)
- 数据持久层:CRUD (Dao - 数据持久化对象)
View
- 展示数据
- 提供链接发起Servlet请求 (a,form,img…)
Controller (Servlet)
- 接收用户的请求 :(req:请求参数、Session信息….)
- 交给业务层处理对应的代码
- 控制视图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库
Filter (重点)
Shiro安全框架技术就是用Filter来实现的.
Filter过滤器,用来过滤网站的数据,处理中文乱码,登录验证,过滤网上骂人的话.
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain : 链
/*
1. 过滤中的所有代码,在过滤特定请求的时候都会执行
2. 必须要让过滤器继续同行
chain.doFilter(request,response);
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
System.out.println("CharacterEncodingFilter执行后....");
}
//销毁:web服务器关闭的时候,过滤器会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
web.xml中的Filter配置
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是 /servlet的任何请求,会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
<!--<url-pattern>/*</url-pattern>-->
<!-- 别偷懒写个 /* -->
</filter-mapping>
Listerner监听器
监听器统计网站在线人数
//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {
//创建session监听: 看你的一举一动
//一旦创建Session就会触发一次这个事件!
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//销毁session监听
//一旦销毁Session就会触发一次这个事件!
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
Session销毁:
1. 手动销毁 getSession().invalidate();
2. 自动销毁
*/
}
web.xml中注册监听器
<!--注册监听器-->
<listener>
<listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
JDBC Java数据库连接
JDBC固定步骤:
- 加载驱动
- 连接数据库
- 向数据库发送SQL的对象Statement:CRUD
- 编写SQL
- 执行SQL
- 关闭连接(先开后关,写连接的时候就把关闭写好)
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users";
//5.执行查询SQL,返回一个 ResultSet : 结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id="+rs.getObject("id"));
System.out.println("name="+rs.getObject("name"));
System.out.println("password="+rs.getObject("password"));
System.out.println("email="+rs.getObject("email"));
System.out.println("birthday="+rs.getObject("birthday"));
}
//6.关闭连接,释放资源(一定要做) 先开后关
rs.close();
statement.close();
connection.close();
}
}
预编译SQL
public class TestJDBC2 {
public static void main(String[] args) throws Exception {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.编写SQL
String sql = "insert into users(id, name, password, email, birthday) values (?,?,?,?,?);";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,2);//给第一个占位符? 的值赋值为1;
preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
preparedStatement.setString(4,"24736743@qq.com");//给第四个占位符? 的值赋值为1;
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());
//5.执行SQL
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功@");
}
//6.关闭连接,释放资源(一定要做) 先开后关
preparedStatement.close();
connection.close();
}
}
ACID事务管理:
开启事务->事务提交->事务回滚->关闭事务
原子性:食物中的操作要么都发生,要么都不发生.
隔离性:多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事物之间要相互隔离.
持久性:一个事物一旦被提交,数据库中的数据改变是永久性的.
一致性:事务前后数据的完整性必须保持一致.
https://blog.csdn.net/dengjili/article/details/82468576
typora+picgo上传网络图片
PicGo下载:https://molunerfinn.com/PicGo/ 安装的是2.3bate
sm.ms床图获取token:https://sm.ms/home/apitoken