“ 人生的游戏不在于拿了一副好牌,而在于怎样去打好坏牌,世上没有常胜将军,勇于超越自我者才能得到最后的奖杯。”
你好,我是梦阳辰!快和我一起学习吧!
精彩回放:
Servlet入门详细教程(你不得不知道的Servlet知识点)
文章目录
01.适配器模式
02.GET和POST
保证前端请求方式和后端程序处理方式一致
HttpServlet原理
03.HttpServletRequest接口
Servlet线程安全问题
04.登录
05.Cookie
关于路径的总结
06.HttpSession
07.实现记录登录状态
01.适配器模式
1.适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
**2.意图:**将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
**3.主要解决:**主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
我们可以在适配器中提供大量的方法,子类继承后,可以在子类中直接使用。
4.例如:
1、系统需要使用现有的类,而此类的接口不符合系统的需要。
2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
当然我们也可以让适配器实现接口,然后将部分需要的方法改为抽象方法。子类继承后,只需要实现抽象方法。代码不会出现冗余。
使用适配器的优点:
1、可以让任何两个没有关联的类一起运行。
2、提高了类的复用。
3、增加了类的透明度。
4、灵活性好。
缺点:
1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。
比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
例如:如果当前程序中A,B,C类只需要使用CommonIn接口中的m1,m2,m3方法。让这些类直接事先这个接口,需要实现更多的方法。当只要使用其中部分方法时,这样做,代码冗余。
解决方案:
1.写一个类F,实现这个接口。(类F即为适配器)
并将部分需要用的方法,用abstract修饰。(即抽象方法)。
2.A,B,C类继承F类即可。
设计模式的分类:
创建型:解决对象的创建问题。
行为型:该模式与方法,行为,算法有关的设计模式。
结构型:更多类,更多对象组合成更大的结构解决某个特定的问题。
常见的设计模式:
Gof95:(1995年,四人组提出的23种设计模式)
单例模式
工厂模式
适配器模式
迭代模式【集合】
策略模式【集合】
装饰器模式【IO流】
了解更多
JavaEE模式
**【问题描述】**我们之前所有的Servlet类直接实现了javax.servlet。Servlet接口。但是这个接口有很多方法是目前不需要的,我们可能只需要编写service方法。直接实现Servlet接口代码,使得代码冗余,有必要在中间添加一个适配器。以后所有的Servlet类不再直接实现Servlet接口,应该去继承适配器类。
02.GET和POST
1.HTTP协议的详细内容。
1.1什么是HTTP协议?
超文本传输协议。
浏览器和服务器之间的一种通讯协议。
该协议是W3C负责指定的,其实本质上就是数据传送格式提前制定好了。浏览器和服务器都必须按照这种数据格式进行接收和发送。
1.2HTTP协议包括几部分?
请求协议:从Browser发送到Server的时候采用的数据传送格式。
响应协议:从Server发送到Browser的时候采用的数据传送格式。
1.3请求协议
请求协议包括四部分
请求行
消息报头
空白行
请求体
请求行包括:请求方式 ,URI ,协议版本号
空白行:专门用来分离消息报头和请求体的。
1.4响应协议
响应协议包括四部分:
状态行
响应报头
空白行
响应体
状态行:协议版本号、状态码、状态描述信息(状态码:200响应正常结束,404资源为找到,500服务器内部错误…)
空白行:分离响应报头和响应体
2.GET请求和POST请求的区别。
2.1 什么情况下浏览器发送的请求是GET请求。什么情况下浏览器发送的去请求是POST请求。
只有当使用表单from,并且将from标签的method属性设置为method="post"才是POST请求,其余剩下所有请求方式都是基于GET请求方式。
2.2 GET请求在请求行上提交数据,格式:uri?name=value&name=value
这种提交方式最终提交的数据会显示到浏览器的地址栏上。
2.3 POST请求在请求其中提交数据,相对安全,提交格式:name=value&name=value…
这种提交方式最终不会再浏览器地址栏上显示。
2.4 POST请求再请求体中提交数据,所以POST请求提交数据没有长度的限制【POST可以提交大数据】
2.5 GET请求在请求行上提交数据,所以GET请求提交的数据长度有限制。
2.6 GET请求只能提交字符串数据,POST请求可以提交任何类型的数据,包括视频…,所以文件上传必须使用POST请求提交。
2.7 GET请求最终的结果,会被浏览器缓存收纳。
3 POST请求和GET请求该如何选择?
有敏感数据,必须使用POST
传送数据不是普通字符串,必须使用POST
传送的数据非常多,使用POST
这个请求是为了修改服务器端资源,使用POST
GET请求多数情况下是从服务器读取资源,这个读取的资源在短时间之内是不会发生变化的,所以GET请求最终的结果浏览器缓存起来了。
POST请求是为了修改服务器端的资源,而每一次修改的结果都是不同的,最终结果没有必要被浏览器缓存。
数据和请求以问号隔开,数据之间以&符号连接。
4.安装httpwatch工具,进行HTTP协议的监测。
5.缓存的解决方案
浏览器将资源缓存之后,缓存的资源是和某个特定的路径绑定在一起的,只要浏览器再发送这个相同的请求路径,这个时候回去缓存中获取资源,不再访问服务器,以这种方式降低服务器的压力,提高用户的体验。但是有的时候,我们不希望走缓存,希望每一次都访问服务器,可以在请求路径后面添加时间戳。
例如:
http://ip:port/xxx/xxx?timestamp=23423424
JS怎么获取毫秒:new Date().getTime();
保证前端请求方式和后端程序处理方式一致
1.前端的页面发送的请求方式应当和服务器端需要的请求方式一致。
服务器需要前端发送POST请求,那前端就应该发送POST请求,若发送GET请求,服务器端应当提示错误信息。
服务器需要前端发送GET请求,那前端就应该发送GET请求,若发送POST请求,服务器应当提示错误信息。
如何完成以上的请求?
在javaweb程序中想办法获取该请求是什么类型的请求,POST?还是GET?
当我们获取到请求方式之后,在javaweb程序中可以使用java语言中if语句进行判断。
if(“POST”.equals(method)){
}else if(“GET”.equals(method)){
}
如何获取请求方式呢?
HTTP的请求协议全部信息被全部封装到javax.servlet.http.HttpServletRequest对象中。
在HttpServletRequest接口类型中有一个方法叫做:String getMethod();可以获取请求方式。
public interface javax.servlet.http.HttpServletRequest extends ServletRequest{
}
代码示例:
public class LoginServlet extends GenericServlet {
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
//将ServletRequest,ServletResponse强制类型转换成带有Http的接口类型
HttpServletRequest request1 =(HttpServletRequest)request;
HttpServletResponse response1 =(HttpServletResponse)response;
response1.setContentType("text/html;charset=UTF-8");
PrintWriter out = response1.getWriter();
//获取浏览器的请求方式
String method=request1.getMethod();
//LoginServlet是处理登录的,要求必须发送POST请求
if("GET".equals(method)){
//后台报出错误,前台报出错误
out.print("你应该发送POST请求!");
throw new RuntimeException("405-你应该发送POST请求");
}
if("POST".equals(method)) {
out.print("正在登录!");
}
//若程序执行到这里说明用户发送的是PUT请求,程序应该正常执行
out.print("当前使用的是"+method+"请求!");
}
}
HttpServlet原理
总结servlet编程(重点)
1.刚开始我们需要实现servlet接口。
2.后面我们开始使用适配器Adapter(GenericServlet,自定义的父类。)
3.现在我们使用开始继承HttpServlet类。重写什么方法取决于你的请求方式。
因此我们编写一个类应当继承HttpServlet,get请求重谢doGet方法,post请求重谢doPost方法。
doPost/doGet方法可以等同看做main方法。
405状态表示前后台请求方式不同。
HttpServlet是一个典型的模板方法设计模式。
其中的service(HttpServletRequest,HttpServletResponsee方法是典型的模板方法。
该方法定义了核心算法骨架,doGet,DoPost…具体的实现延迟到子类中完成。
模板类一般是抽象类。
2.核心算法得到复用。
03.HttpServletRequest接口
1.继承关系:
pulbic interface HttpServletRequest extends ServletRequest{
}
2.HttpServletRequest接口的实现类是WEB容器负责实现的。Tomcat服务器有自己的实现。程序员只需要面向接口调用方法。
3.HttpServletRequest这个对象封装了哪些信息呢?
封装了HTTP请求协议的全部内容。
如:
请求方式
URI
协议版本号
表单提交的数据
…
4.HttpServletRequest一般变量的名字叫做:request,表示请求。
HttpServletRequest对象代表一次请求。一次请求对应一个request对象。所以request对象的生命周期是短暂的。
5.什么是一次请求。
网页上点击超链接,到最终网页停下来。如输入地址访问。
6.HttpServletRequest接口常用的方法。
表单提交的数据,会自动被封装到request对象中,request对象中有Map集合存储这些数据,Map集合的key是name,value是一个字符串类型的一维数组。
//1.通过key获取value这个一维数组的元素(通常一维数组只有一个元素,所以这个方法用得较多
String getParameter(String name)
//2.获取整个Map对象
Map getParameterMap()
//3.获取整个Map集合中的所有key
Enumeration getParameterNames()
//4.通过Map集合key获取value.
String[] getParameterValues(String name)
public class SaveUserServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取用户信息,表单提交的这些数据被自动封装到request对象中
//从request获取这些信息
//表单数据是这样提交的,POST请求,在请求体中提交,数据格式:username=admin&password=123...
/* Map
* key value
* ---------------------------
*username {"admin"}
*password {"134"}
*interest {"sport","music"}
*......
* */
String username= request.getParameter("username");
String password= request.getParameter("password");
String sex=request.getParameter("sex");
//String interest=request.getParameter("interest");
String grade= request.getParameter("grade");
String introduce=request.getParameter("introduce");
System.out.println(username);
System.out.println(password);
System.out.println(sex);
//System.out.println(interest);
System.out.println(grade);
System.out.println(introduce);
//获取所有的兴趣爱好
String[] interest=request.getParameterValues("interest");
for(String in:interest) {
System.out.println(in);
}
//获取整个参数Map集合
MapparameterMap=request.getParameterMap();
Set names=parameterMap.keySet();
for(String name:names) {
String[] values = parameterMap.get(name);
System.out.println(name+"=");
for(String value :values) {
System.out.print(value+" ");
}
System.out.println();
}
//获取参数Map集合所有的key
Enumeration names1=request.getParameterNames();
while(names1.hasMoreElements()) {
String name=names1.nextElement();
System.out.println(name);
}
}
}
HttpServletRequest是一个怎样的范围呢?
HttpServletRequest类型的变量通常命名为:request,代表当前的本次请求一次请求对应一个request对象,100个请求对应100个请求对象。
请求范围是极小的,request只能完成在同一次请求中传递数据。
ServletContext 应用范围,可以跨用户传递数据。
ServletRequest 请求范围,只能在同一个请求中传递数据【可以跨Servlet传递数据,但是这个Servlet必须在同一个请求中】优先选择request范围。
解决项目中的中文乱码问题:
1.乱码出现在什么位置?
数据 “传递”过程中的乱码
数据 “展示”过程中的乱码
数据 “保存”过程中的乱码
2.数据保存过程中的乱码
最终保存到数据库表中的时候,数据出现乱码。
导致数据保存过程中的乱码包括以下两种情况:
第一种情况:在保存之前,数据本身是乱码,保存到数据表中的时候一定是乱码。
第二种情况:保存之前,数据不是乱码,但是由于数据库不支持中文,保存后出现乱码。
3.数据展示过程中的乱码:
显示数据出现乱码。
解决方案:
设置响应的内容类型,以及对应的字符编码方式:
response.setContextType(“text/html;charset=UTF-8”);
如果没有执行java程序的html
设置为
4.数据传递过程中的乱码:
将数据从浏览器发送给服务器的时候,服务器接收到的数据是乱码。
“市场部”对应的ISO-8859-1的编码:%E5%B8%…
ISO-8859-1是国际标准编码,不支持中文编码,兼容ASCII码,又被称为latin1编码。
不管哪个国家的文章,在浏览器发送给服务器的时候,都会采用ISO-8859-1的编码方式发送。
发送给web服务器之后,web服务器不知道这些数据之前是什么类型的文字。所以会出现乱码。
Servlet线程安全问题
1.Servlet是单实例多线程环境下运行的。
2.什么时候程序存在线程安全问题。
多线程并发
有共享的数据
共享数据有修改操作
3.在JVM中,哪些数据可能会存在线程安全问题?
局部变量内存空间不共享,一个线程一个栈,局部变量在栈中存储,局部变量不会存在线程安全问题
常量不会被修改,所以常量不会存在线程安全问题。
所有的线程共享一个堆。
堆内存中new出来的对象在其中存储,对象内部有“实例变量”,所以“实例变量”的内存多线程是共享的。实例变量多线程共同访问,并且涉及到修改操作的时候就会存在线程安全问题。
所有线程共享一个方法区
方法区中有静态变量,静态变量的内存也是共享的,若涉及到修改操作,静态变量也存在线程安全问题。
**4.线程安全问题不止是体现在JVM中,**还有可能发生在数据库中,例如:多个线程共享同一张表,并且同时去修改表中的记录,那么就存在线程安全问题。
怎么解决数据库表中数据的线程安全问题?
第一种方案:使用synchronized关键字
第二种方案:行级锁【悲观锁】
第三种方案:事务隔离级别,如:串行化
第四种方案:乐观锁。
5.怎么解决线程安全问题?
不使用实例变量,尽量使用局部变量。
若必须使用实例变量给,那么我们可以考虑将该对象变成多例对象,一个线程一个java对象,实例变量的内存也不会共享。
若必须使用单例,那就只能使用synchronized线程同步机制,线程一旦排队执行,则吞吐量降低,降低用户体验。
6.Servlet怎么解决线程安全问题?
不使用实例变量,尽量使用局部变量。
Servlet必须是单例的,所以剩下的方式只能考虑synchronized,线程同步机制。
关于web系统中资源跳转
跳转包括两种方式:
转发:forward
重定向:redirect
转发:(你向朋友借钱,朋友没钱,他去借钱然后给你)
从一个java源程序转到另一个源程序。
重定向的路径需要加webapp的根路径
转发是在本项目内部完成资源跳转。
重定向可以完成跨app跳转资源。
跳转的下一个资源可以是什么?
web服务器任何资源。
什么时候采用转发,什么时候采用重定向?
若想跨app跳转,必须使用重定向。
希望在下一个资源中从request范围中将数据取出,必须使用转发。
解决浏览器刷新问题
重定向可以解决页面刷新的问题:
刷新只会刷新第二个请求:执行第二条请求语句。
04.登录
练习:完成网页端员工信息的增删改查。
05.Cookie
1.什么是 Cookie?
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。
Cookie 是一些数据, 存储于你电脑上的文本文件中。
当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息。
Cookie 的作用就是用于解决 “如何记录客户端的用户信息”:
当用户访问 web 页面时,他的名字可以记录在 cookie 中。
在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。
Cookie 以名/值对形式存储,如下所示:
username=John Doe
当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中。服务端通过这种方式来获取用户的信息。
也可以将数据保存在服务器端,但是需要用户登录。
2.网站上的十天免登录功能:
将账户信息保存在客户端硬盘上,并且寿命为10天。
网吧有还原卡,进行还原。无需担心。
3.Cookie的保存位置
Cookie是保存在浏览器客户端上的
Cookie也可以保存在浏览器的缓存中,浏览器关闭Cookie消失。
Cookie也可以保存在客户端的硬盘文件中,浏览器关闭Cookie还在,除非Cookie失效。
4.Cookie只有在javaweb中才有吗?
Cookie不止在javaweb中存在。
只要是web开发,只要是B/S架构的系统,只要是HTTP协议,就有Cookie的存在。
Cookies这种机制是Http协议规定的。
5.Cookie实现的功能,常见的有哪些?
十天免登录
购物车数据等。
6.Java中Cookie被当作类来处理,使用new运算可以创建Cookie对象,而且Cookie由两部分组成,分别是Cookie的name和value,name和value都是字符串类型String。
7.java程序中怎么创建Cookie?
Cookie cookie=new Cookie(String CookieName,String cookieValue);
8.服务器可以一次向浏览器发送多个Cookie.
9.默认情况下,服务器发送Cookie给浏览器之后,浏览器将Cookie保存在缓存中,只要不关闭浏览器,Cookie永远存在,并且有效。当浏览器关闭之后,缓存中的Cookie被清除了。
10.在浏览器客户端无论是硬盘文件中还是缓存中保存的Cookie,什么时候会再次发送给服务器呢?
浏览器会不会提交发送这些Cookie给服务器,和请求路径有关系。
不同的路径会发送提交不同的Cookie。
11.默认情况下Cookie会和哪些路径绑在一起?
/webapps/test/xxx
请求服务器,服务器生成Cookie,并将Cookie发送给浏览器客户端。
这个浏览器中的Cookie会默认和“test/”这个路径绑定在一起。
也就是说,以后只要发送“test/”请求,Cookie一定自动提交给服务器。
如果是:/webapps/test
请求服务器,服务器生成Cookie,并将Cookie发送给浏览器客户端。
这个浏览器中的Cookie会默认和“webapps/”这个路径绑定在一起。
也就是说,以后只要发送“webapps/”请求,Cookie一定会提交给服务器。
14.浏览器提交Cookie给服务器,服务器怎么接收Cookie?
从request对象中获取所有提交的Cookie。
Cookie[] cookies = request.getCookies();
if(cookies!=null)
for(Cookie cookie :cookies){
String cookieName=cookie.getName();
String cookieValue=cookie.getValue();
System.out.println(cookieName+"="+cookievalue);
}
15.cookies存在有效时间,决定了存放位置,浏览器可以禁用Cookie。
表示服务器发送过来的Cookie,浏览器不做处理。
关于路径的总结
1.关于url-pattern的编写方式和路径的总结
1.路径的编写形式:
//超链接
//表单
//重定向
response.sendRedirect("项目名/资源路径");
//转发
request.getRequestDispatcher("/资源路径").forward(request,response);
//欢迎页面
资源路径
//servlet路径
hello
part1.Helloservlet
hello
/资源路径
//Cookie设置Path
cookie.setPath("/项目名/资源路径");
//ServletContext
ServletContext application =config.getServletContext();
application.getRealPath("/WEB-INF/Classes/db.properties");
application.getRealPath("/资源路径");
2.url-pattern路径的编写方式
1.url-pattern可以编写多个
精确匹配的方式
hello
/hello
/system/hello
扩展匹配的方式
以abc开始的即可。
/abc/*
后缀匹配
*.action
全部匹配
/*
06.HttpSession
HttpSession简介
HttpSession是Java平台对session机制的实现规范,因为它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有规定的细微差异。
JSP利用servlet提供的HttpSession接口来识别一个用户,存储这个用户的所有访问信息。
默认情况下,JSP允许会话跟踪,一个新的HttpSession对象将会自动地为新的客户端实例化。禁止会话跟踪需要显式地关掉它,通过将page指令中session属性值设为false来实现
1.Session表示会话,不止是在javaweb中存在,只要是web开发,都有会话这种机制。
2.在java中会话对应的类型是:javax.servlet.http.HttpSession,简称session
3.Cookie可以将会话保存在客户端,HttpSession可以将会话状态保存在服务器端。
4.HttpSession对象是一个会话级别的对象,一次会话对应一个HttpSession对象。
6.在会话过程中,web服务器一直为当前这个用户维护着一个会话对象/HttpSession
7.在WEB容器中,WEB容器维护了大量的HttpSession对象,换句话说,在WEB容器中应该有一个"session列表"。
思考:为什么当前会话中的每一次请求可以获取到属于自己的会话对象?
浏览器首次发送请求,服务器会创建一个HttpSession对象,该对象代表一次会话。
同时生成HttpSesion对象对应的Cookie对象,并且Cookie对象的name是JSESSIONID。Cookie的value是32位长度的字符串。
服务器将Cookie的value和HttpSession对象绑定到session列表中。
服务器将Cookie完整的发送给浏览器客户端。
浏览器客户端将Cookie保存到缓存中,只要浏览器不关闭,Cookie不会消失,当再次发送请求的时候,会自动提交缓存当中的Cookie.服务器收到Cookie,验证Cookie的的name确实是:JSESSIONID,获取Cookie的value,通过Cookie的value区检索session列表。
浏览器发送Cookie给服务器,通过Cookie的值去找session对象。
8.和HttpSession对象关联的这个Cookie的name是比较特殊的,在java中叫做:jsessionid。
** 9.浏览器禁用Cookie会出现什么问题?怎么解决?**
浏览器禁用Cookie,则浏览器缓存中不再保存Cookie。
导致在同一个会话中,无法获取到对应的会话的对象。每次获取的会话对象都是新的。
浏览器禁用Cookie之后,若还想拿到Session对象,必须重写URL机制,怎么重写URL?
URL;jsessionid=xxxxxxxxxxxxxxxxx
重写URL会给编程带来难度。所以尽量不要禁用。
10.浏览器关闭之后,服务器对应的session对象会被销毁吗?为什么?
不会!
因为B/S架构的系统基于HTTP协议,而HTTP协议是一种无连接/无状态的协议。
请求的瞬间和服务器之间的通道是打开的,请求响应结束后,通道关闭。
这样做的目的是降低服务器的压力。
11.session对象在什么时候被销毁?
web系统中引入session超时的概念。
当很长一段时间(这个时间可以配置)没有用户在访问该session对象,此时session对象超时,web服务器自动回收session对象。
12.什么是一次会话?
一般讲:浏览器打开进行一些操作后,关闭浏览器。
本质上:浏览器session被创建到session对象超时之后销毁。
web.xml设置超时时间,默认为30分钟
120
13.HttpSession接口常用的方法
//获取当前的session,获取不到则新建session
HttpSession session = request.getSession();
//获取当前的session,获取不到,则新建session
HttpSession session = request.getSession(true);
//获取当前的session,获取不到,则返回null
HttpSession session = request.getSession(flase);
//
void setAttribute(String name Object value);
//
Object getAttribut(String name)
//
void removeAttribute(String name);
//销毁session
void invalidate();
14.ServletContext,HttpSession,HttpServletRequest接口的对比:
14.1 以上都是范围对象:
ServletContext application;是应用范围。
HttpSession session是会话范围。
HttpServletRequest request;是请求范围。
14.2 三个范围的排序
application>session>request
14.3 application完成跨会话共享数据、session完成跨请求传递数据,但是这些请求必须在同一个会话当中。
request完成跨Servlet共享数据,但是这些Servlet必须在同一个请求当中【转发】。
14.4 使用的原则:从小到大尝试,优先使用小范围。
如:登入成功这个状态保存至sessoin对象中。
登录成功状态不能保存到request范围中,因为一次请求对应一个新的request对象。
登录成功状态也不能保存到application范围中,因为登录成功状态是属于会话级别的,不能所有用户共享。
“ 生活是不公平的,不管你的境遇如何,你只能全力以赴。任何时候,不要过分去纠结公平与否,全力以赴,无怨无悔,轻松笑对得与失。”我是梦阳辰,与你共进退!别忘记素质三连哦!
关注公众号【轻松玩编程】回复关键字“电子书”,“计算机资源”,“Java从入门到进阶”,”JavaScript教程“,“算法”,“Python学习资源”,“人工智能”等即可获取学习资源。