自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(231)
  • 收藏
  • 关注

原创 toString方法

https://stackoverflow.com/questions/8410294/why-does-printlnarray-have-strange-output-ljava-lang-string3e25a5类对象的ToString方法返回一个字符串,该字符串由对象是实例的类名称,签名字符`@'以及对象的哈希代码的unsigned十六进制表示。换句话说,此方法返回等于值的字符串:getClass().getName() + '@' + Integer.toHexString(hashCode(

2021-03-30 09:52:08 169

原创 java连接Mysql

参考链接:菜鸟教程导入Mysql驱动包Java 连接 MySQL 需要驱动包,最新版下载地址为:http://dev.mysql.com/downloads/connector/j/解压后得到 jar 库文件,在对应的项目创建一个libs文件夹,直接将jar库文件复制到该文件夹下右键点击创建数据库直接在mysql下运行如下代码:CREATE TABLE `websites` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(20

2021-03-27 10:22:59 174

原创 Web开发——部署

对一个Web应用程序来说,除了Servlet、Filter这些逻辑组件,还需要JSP这样的视图文件,外加一堆静态资源文件,如CSS、JS等。合理组织文件结构非常重要。我们以一个具体的Web应用程序为例:我们把所有的静态资源文件放入/static/目录,在开发阶段,有些Web服务器会自动为我们加一个专门负责处理静态文件的Servlet,但如果IndexServlet映射路径为/,会屏蔽掉处理静态文件的Servlet映射。因此,我们需要自己编写一个处理静态文件的FileServlet:@WebServl

2021-03-27 09:57:18 180

原创 Web开发——使用Listener

除了Servlet和Filter外,JavaEE的Servlet规范还提供了第三种组件:Listener。Listener顾名思义就是监听器,有好几种Listener,其中最常用的是ServletContextListener,我们编写一个实现了ServletContextListener接口的类如下:@WebListenerpublic class AppListener implements ServletContextListener { // 在此初始化WebApp,例如打开数据库连接

2021-03-27 09:54:44 204

原创 Web开发——修改响应

既然我们能通过Filter修改HttpServletRequest,自然也能修改HttpServletResponse,因为这两者都是接口。我们来看一下在什么情况下我们需要修改HttpServletResponse。假设我们编写了一个Servlet,但由于业务逻辑比较复杂,处理该请求需要耗费很长的时间:@WebServlet(urlPatterns = "/slow/hello")public class HelloServlet extends HttpServlet { protecte

2021-03-27 09:54:27 161

原创 Web开发——修改请求

Filter可以对请求进行预处理,因此,我们可以把很多公共预处理逻辑放到Filter中完成。考察这样一种需求:我们在Web应用中经常需要处理用户上传文件,例如,一个UploadServlet可以简单地编写如下:@WebServlet(urlPatterns = "/upload/file")public class UploadServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServ

2021-03-27 09:54:03 239

原创 Web开发——使用Filter

在一个比较复杂的Web应用程序中,通常都有很多URL映射,对应的,也会有多个Servlet来处理URL。我们考察这样一个论坛应用程序:各个Servlet设计功能如下:IndexServlet:浏览帖子;SignInServlet:登录;SignOutServlet:登出;ProfileServlet:修改用户资料;PostServlet:发帖;ReplyServlet:回复。其中,ProfileServlet、PostServlet和ReplyServlet都需要用户登录后才能操作,

2021-03-27 09:53:46 234

原创 Web开发——MVC开发

我们通过前面的章节可以看到:Servlet适合编写Java代码,实现各种复杂的业务逻辑,但不适合输出复杂的HTML;JSP适合编写HTML,并在其中插入动态内容,但不适合编写复杂的Java代码。能否将两者结合起来,发挥各自的优点,避免各自的缺点?答案是肯定的。我们来看一个具体的例子。假设我们已经编写了几个JavaBean:public class User { public long id; public String name; public School scho

2021-03-26 08:51:01 264 3

原创 Web开发——JSP开发

我们从前面的章节可以看到,Servlet就是一个能处理HTTP请求,发送HTTP响应的小程序,而发送响应无非就是获取PrintWriter,然后输出HTML:PrintWriter pw = resp.getWriter();pw.write("<html>");pw.write("<body>");pw.write("<h1>Welcome, " + name + "!</h1>");pw.write("</body>");pw.wr

2021-03-26 08:50:46 404

原创 Web开发——使用Session和Cookie

在Web应用程序中,我们经常要跟踪用户身份。当一个用户登录成功后,如果他继续访问其他页面,Web程序如何才能识别出该用户身份?因为HTTP协议是一个无状态协议,即Web应用程序无法区分收到的两个HTTP请求是否是同一个浏览器发出的。为了跟踪用户状态,服务器可以向浏览器分配一个唯一ID,并以Cookie的形式发送到浏览器,浏览器在后续访问时总是附带此Cookie,这样,服务器就可以识别用户身份。...

2021-03-26 08:50:07 140

原创 Web开发——重定向与转发

Redirect重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令,告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。例如,我们已经编写了一个能处理/hello的HelloServlet,如果收到的路径为/hi,希望能重定向到/hello,可以再编写一个RedirectServlet:@WebServlet(urlPatterns = "/hi")public class RedirectServlet extends HttpServlet { protected vo

2021-03-26 08:49:52 793

原创 Web开发——Servlet进阶

一个Web App就是由一个或多个Servlet组成的,每个Servlet通过注解说明自己能处理的路径。例如:@WebServlet(urlPatterns = "/hello")public class HelloServlet extends HttpServlet { ...}上述HelloServlet能处理/hello这个路径的请求。早期的Servlet需要在web.xml中配置映射路径,但最新Servlet版本只需要通过注解就可以完成映射。因为浏览器发送请求的时候,还会

2021-03-26 08:49:37 131

原创 Web开发——Servlet开发

在上一节中,我们看到,一个完整的Web应用程序的开发流程如下:编写Servlet;打包为war文件;复制到Tomcat的webapps目录下;启动Tomcat。这个过程是不是很繁琐?如果我们想在IDE中断点调试,还需要打开Tomcat的远程调试端口并且连接上去。我们需要一种简单可靠,能直接在IDE中启动并调试webapp的方法。因为Tomcat实际上也是一个Java程序,我们看看Tomcat的启动流程:启动JVM并执行Tomcat的main()方法;加载war并初始化Servlet;

2021-03-26 08:49:24 75

原创 Web开发——Servlet入门

在上一节中,我们看到,编写HTTP服务器其实是非常简单的,只需要先编写基于多线程的TCP服务,然后在一个TCP连接中读取HTTP请求,发送HTTP响应即可。但是,要编写一个完善的HTTP服务器,以HTTP/1.1为例,需要考虑的包括:识别正确和错误的HTTP请求;识别正确和错误的HTTP头;复用TCP连接;复用线程;IO异常处理;…这些基础工作需要耗费大量的时间,并且经过长期测试才能稳定运行。如果我们只需要输出一个简单的HTML页面,就不得不编写上千行底层代码,那就根本无法做到高效而可靠

2021-03-26 08:49:07 92

原创 Web开发——Web基础

今天我们访问网站,使用App时,都是基于Web这种Browser/Server模式,简称BS架构,它的特点是,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器,获取Web页面,并把Web页面展示给用户即可。Web页面具有极强的交互性。由于Web页面是用HTML编写的,而HTML具备超强的表现力,并且,服务器端升级后,客户端无需任何部署就可以使用到新的版本,因此,BS架构升级非常容易。HTTP协议在Web应用中,浏览器请求一个URL,服务器就把生成的HTML网页发送给浏览

2021-03-26 08:48:52 112 1

原创 行为型模式——访问者

访问者模式(Visitor)是一种操作一组对象的操作,它的目的是不改变对象的定义,但允许新增不同的访问者,来定义新的操作。访问者模式的设计比较复杂,如果我们查看GoF原始的访问者模式,它是这么设计的:上述模式的复杂之处在于上述访问者模式为了实现所谓的“双重分派”,设计了一个回调再回调的机制。因为Java只支持基于多态的单分派模式,这里强行模拟出“双重分派”反而加大了代码的复杂性。这里我们只介绍简化的访问者模式。假设我们要递归遍历某个文件夹的所有子文件夹和文件,然后找出.java文件,正常的做法是写.

2021-03-26 00:04:34 47

原创 行为型模式——模板方法

模板方法(Template Method)是一个比较简单的模式。它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤。因此,模板方法的核心在于定义一个“骨架”。我们还是举例说明。假设我们开发了一个从数据库读取设置的类:public class Setting { public final String getSetting(String key) { String value = readFromD.

2021-03-25 08:45:47 49

原创 行为型模式——策略

策略模式:Strategy,是指,定义一组算法,并把其封装到一个对象中。然后在运行时,可以灵活的使用其中的一个算法。策略模式在Java标准库中应用非常广泛,我们以排序为例,看看如何通过Arrays.sort()实现忽略大小写排序:import java.util.Arrays;public class Main { public static void main(String[] args) throws InterruptedException { String[] ar.

2021-03-25 08:45:18 50

原创 行为型模式——状态

什么是状态?我们以QQ聊天为例,一个用户的QQ有几种状态:离线状态(尚未登录);正在登录状态;在线状态;忙状态(暂时离开)。如何表示状态?我们定义一个enum就可以表示不同的状态。但不同的状态需要对应不同的行为,比如收到消息时:if (state == ONLINE) { // 闪烁图标} else if (state == BUSY) { reply("现在忙,稍后回复");} else if ...状态模式的目的是为了把上述一大串if…else…的逻辑给分拆到不.

2021-03-25 08:44:49 45

原创 行为型模式——观察者

观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。要理解观察者模式,我们还是看例子。假设一个电商网站,有多种Product(商品),同时,Customer(消费者)和Admin(管理员)对商品上架、价格改变都感兴趣,希望能第一时间获得通知。于是,Store(商场)可以这么写:public class Store { Customer custom.

2021-03-25 08:44:28 51

原创 行为型模式——备忘录

备忘录模式(Memento),主要用于捕获一个对象的内部状态,以便在将来的某个时候恢复此状态。其实我们使用的几乎所有软件都用到了备忘录模式。最简单的备忘录模式就是保存到文件,打开文件。对于文本编辑器来说,保存就是把TextEditor类的字符串存储到文件,打开就是恢复TextEditor类的状态。对于图像编辑器来说,原理是一样的,只是保存和恢复的数据格式比较复杂而已。Java的序列化也可以看作是备忘录模式。在使用文本编辑器的时候,我们还经常使用Undo、Redo这些功能。这些其实也可以用备忘录模式实现.

2021-03-25 08:44:02 47

原创 行为型模式——中介

中介模式(Mediator)又称调停者模式,它的目的是把多方会谈变成双方会谈,从而实现多方的松耦合。有些童鞋听到中介立刻想到房产中介,立刻气不打一处来。这个中介模式与房产中介还真有点像,所以消消气,先看例子。考虑一个简单的点餐输入:这个小系统有4个参与对象:多选框;“选择全部”按钮;“取消所有”按钮;“反选”按钮。它的复杂性在于,当多选框变化时,它会影响“选择全部”和“取消所有”按钮的状态(是否可点击),当用户点击某个按钮时,例如“反选”,除了会影响多选框的状态,它又可能影响“选择全.

2021-03-25 08:43:34 30

原创 行为型模式——迭代器

迭代器模式(Iterator)实际上在Java的集合类中已经广泛使用了。我们以List为例,要遍历ArrayList,即使我们知道它的内部存储了一个Object[]数组,也不应该直接使用数组索引去遍历,因为这样需要了解集合内部的存储结构。如果使用Iterator遍历,那么,ArrayList和LinkedList都可以以一种统一的接口来遍历:List<String> list = ...for (Iterator<String> it = list.iterator(); it.

2021-03-25 08:43:11 33

原创 行为型模式——解释器

解释器模式(Interpreter)是一种针对特定问题设计的一种解决方案。例如,匹配字符串的时候,由于匹配条件非常灵活,使得通过代码来实现非常不灵活。举个例子,针对以下的匹配条件:以+开头的数字表示的区号和电话号码,如+861012345678;以英文开头,后接英文和数字,并以.分隔的域名,如www.liaoxuefeng.com;以/开头的文件路径,如/path/to/file.txt;…因此,需要一种通用的表示方法——正则表达式来进行匹配。正则表达式就是一个字符串,但要把正则表达式解析为.

2021-03-25 08:42:37 62

原创 行为型模式——命令

命令模式(Command)是指,把请求封装成一个命令,然后执行该命令。在使用命令模式前,我们先以一个编辑器为例子,看看如何实现简单的编辑操作:public class TextEditor { private StringBuilder buffer = new StringBuilder(); public void copy() { ... } public void paste() { String text = getFrom.

2021-03-25 08:41:49 63

原创 tomcat配置乱码+端口占用

乱码打开tomcat文件夹到conf目录下打开logging.properties找到java.util.logging.ConsoleHandler.encoding = utf-8更改为java.util.logging.ConsoleHandler.encoding = GBK端口占用用管理员身份打开cmd,找到占用8080端口的进程号PID:netstat -ano | findstr 8080kill掉这个进程taskkill /F /PID 8472问题解决。

2021-03-25 08:41:18 40

原创 JAVA笔记——Web开发

从本章开始,我们就正式进入到JavaEE的领域。什么是JavaEE?JavaEE是Java Platform Enterprise Edition的缩写,即Java企业平台。我们前面介绍的所有基于标准JDK的开发都是JavaSE,即Java Platform Standard Edition。此外,还有一个小众不太常用的JavaME:Java Platform Micro Edition,是Java移动开发平台(非Android),它们三者关系如下:JavaME是一个裁剪后的“微型版”JDK,现在使用

2021-03-24 10:02:50 223

原创 Stream——其他操作

我们把Stream提供的操作分为两类:转换操作和聚合操作。除了前面介绍的常用操作外,Stream还提供了一系列非常有用的方法。排序对Stream的元素进行排序十分简单,只需调用sorted()方法:import java.util.*;import java.util.stream.*;public class Main { public static void main(String[] args) { List<String> list = List.of

2021-03-24 10:01:59 44

原创 Stream——输出集合

我们介绍了Stream的几个常见操作:map()、filter()、reduce()。这些操作对Stream来说可以分为两类,一类是转换操作,即把一个Stream转换为另一个Stream,例如map()和filter(),另一类是聚合操作,即对Stream的每个元素进行计算,得到一个确定的结果,例如reduce()。区分这两种操作是非常重要的,因为对于Stream来说,对其进行转换操作并不会触发任何计算!我们可以做个实验:import java.util.function.Supplier; impo

2021-03-24 10:01:40 1309

原创 Stream——使用reduce

map()和filter()都是Stream的转换方法,而Stream.reduce()则是Stream的一个聚合方法,它可以把一个Stream的所有元素按照聚合函数聚合成一个结果。我们来看一个简单的聚合方法:import java.util.stream.*;public class Main { public static void main(String[] args) { int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).r

2021-03-24 10:01:27 1440

原创 Stream——使用filter

Stream.filter()是Stream的另一个常用转换方法。所谓filter()操作,就是对一个Stream的所有元素一一进行测试,不满足条件的就被“滤掉”了,剩下的满足条件的元素就构成了一个新的Stream。例如,我们对1,2,3,4,5这个Stream调用filter(),传入的测试函数f(x) = x % 2 != 0用来判断元素是否是奇数,这样就过滤掉偶数,只剩下奇数,因此我们得到了另一个序列1,3,5:用IntStream写出上述逻辑,代码如下:import java.util.s

2021-03-24 10:01:12 2385

原创 Stream——使用map

Stream.map()是Stream最常用的一个转换方法,它把一个Stream转换为另一个Stream。所谓map操作,就是把一种操作运算,映射到一个序列的每一个元素上。例如,对x计算它的平方,可以使用函数f(x) = x * x。我们把这个函数映射到一个序列1,2,3,4,5上,就得到了另一个序列1,4,9,16,25:可见,map操作,把一个Stream的每个元素一一对应到应用了目标函数的结果上。Stream<Integer> s = Stream.of(1, 2, 3, 4, 5

2021-03-24 10:00:56 5145

原创 Stream——创建Stream

要使用Stream,就必须现创建它。创建Stream有很多种方法,我们来一一介绍。Stream.of()创建Stream最简单的方式是直接用Stream.of()静态方法,传入可变参数即创建了一个能输出确定元素的Stream:import java.util.stream.Stream;public class Main { public static void main(String[] args) { Stream<String> stream = Stre

2021-03-24 10:00:44 86

原创 函数式编程——使用Stream

Java从8开始,不但引入了Lambda表达式,还引入了一个全新的流式API:Stream API。它位于java.util.stream包中。划重点:这个Stream不同于java.io的InputStream和OutputStream,它代表的是任意Java对象的序列。两者对比如下:有同学会问:一个顺序输出的Java对象序列,不就是一个List容器吗?再次划重点:这个Stream和List也不一样,List存储的每个元素都是已经存储在内存中的某个Java对象,而Stream输出的元素可能并没有预先

2021-03-24 10:00:30 68

原创 函数式编程——方法引用

使用Lambda表达式,我们就可以不必编写FunctionalInterface接口的实现类,从而简化代码:Arrays.sort(array, (s1, s2) -> { return s1.compareTo(s2);});实际上,除了Lambda表达式,我们还可以直接传入方法引用。例如:import java.util.Arrays;public class Main { public static void main(String[] args) {

2021-03-24 10:00:15 110

原创 函数式编程——lambda基础

在了解Lambda之前,我们先回顾一下Java的方法。Java的方法分为实例方法,例如Integer定义的equals()方法:public final class Integer { boolean equals(Object o) { ... }}以及静态方法,例如Integer定义的parseInt()方法:public final class Integer { public static int parseInt(String s) {

2021-03-24 09:59:45 49

原创 行为型模式——责任链

责任链模式(Chain of Responsibility)是一种处理请求的模式,它让多个处理器都有机会处理该请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递:在实际场景中,财务审批就是一个责任链模式。假设某个员工需要报销一笔费用,审核者可以分为:Manager:只能审核1000元以下的报销;Director:只能审核10000元以下的报销;CEO:可以审核任意额度。用责任链模式设计此报销流程时,每个审核者只关心自己责任范围内的请求,并且处理它。对于超出自.

2021-03-23 11:06:55 42

原创 结构型模式——代理

代理模式,即Proxy,它和Adapter模式很类似。我们先回顾Adapter模式,它用于把A接口转换为B接口:public BAdapter implements B { private A a; public BAdapter(A a) { this.a = a; } public void b() { a.a(); }}而Proxy模式不是把A接口转换成B接口,它还是转换成A接口:public AProxy imple.

2021-03-23 10:49:05 38

原创 结构型模式——享元

享元(Flyweight)的核心思想很简单:如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。享元模式在Java标准库中有很多应用。我们知道,包装类型如Byte、Integer都是不变类,因此,反复创建同一个值相同的包装类型是没有必要的。以Integer为例,如果我们通过Integer.valueOf()这个静态工厂方法创建Integer实例,当传入的int范围在-128~+127之间时,会直接.

2021-03-23 09:50:35 35

原创 结构型模式——外观

外观模式,即Facade,是一个比较简单的模式。它的基本思想如下:如果客户端要跟许多子系统打交道,那么客户端需要了解各个子系统的接口,比较麻烦。如果有一个统一的“中介”,让客户端只跟中介打交道,中介再去跟各个子系统打交道,对客户端来说就比较简单。所以Facade就相当于搞了一个中介。我们以注册公司为例,假设注册公司需要三步:向工商局申请公司营业执照;在银行开设账户;在税务局开设纳税号。以下是三个系统的接口:// 工商注册:public class AdminOfIndustry {

2021-03-23 09:37:49 34

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除