某关于整合mod部落冲突无限资源版的求助帖(带Java崩溃日志

我写了一个触发器,请问在Java里怎样调用?
[问题点数:40分,结帖人cljlove]
本版专家分:0
结帖率 96.88%
CSDN今日推荐
本版专家分:4691
本版专家分:0
本版专家分:247
本版专家分:291
本版专家分:57
本版专家分:1744
本版专家分:1451
本版专家分:10110
本版专家分:1653
本版专家分:991
本版专家分:3531
2010年6月 多媒体/设计/Flash/Silverlight 开发大版内专家分月排行榜第三
本版专家分:253
本版专家分:285
本版专家分:402
本版专家分:2508
本版专家分:164
本版专家分:217
本版专家分:144
本版专家分:10
本版专家分:123
本版专家分:6
本版专家分:2816
本版专家分:296
本版专家分:3362
本版专家分:2
本版专家分:7059
本版专家分:0
本版专家分:378
本版专家分:4047
本版专家分:310
本版专家分:310
本版专家分:0
匿名用户不能发表回复!
其他相关推荐某关于整合mod冲突的求助帖(带Java崩溃日志望不沉)【minecraft吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:1,646,115贴子:
某关于整合mod冲突的求助帖(带Java崩溃日志望不沉)
1.9预览都出了,最近无聊想弄一个1.8的小型整合(1.7.10迟早过时)可是莫名其妙的冲突.....没加几个mod也没有稀奇古怪的mod(均为较主流mod的稳定版)forge用的14.1.13332楼是崩溃日志~
*** Launching Game ***[20:52:53] [launcher/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLTweaker[20:52:53] [launcher/INFO] [LaunchWrapper]: Using primary tweak class name net.minecraftforge.fml.common.launcher.FMLTweaker[20:52:53] [launcher/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLTweaker[20:52:53] [launcher/INFO] [FML]: Forge Mod Loader version 8.0.37.1333 for Minecraft 1.8 loading[20:52:53] [launcher/INFO] [FML]: Java is Java HotSpot(TM) 64-Bit Server VM, version 1.7.0_79, running on Windows 8.1:amd64:6.3, installed at D:[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]: java.lang.NoClassDefFoundError: cpw/mods/fml/relauncher/IFMLLoadingPlugin[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.ClassLoader.defineClass1(Native Method)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.ClassLoader.defineClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.security.SecureClassLoader.defineClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.net.URLClassLoader.defineClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.net.URLClassLoader.access$100(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.net.URLClassLoader$1.run(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.net.URLClassLoader$1.run(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.security.AccessController.doPrivileged(Native Method)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.net.URLClassLoader.findClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:117)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.ClassLoader.loadClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.ClassLoader.loadClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.Class.forName0(Native Method)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.Class.forName(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.relauncher.CoreModManager.loadCoreMod(CoreModManager.java:447)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.relauncher.CoreModManager.discoverCoreMods(CoreModManager.java:371)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.relauncher.CoreModManager.handleLaunch(CoreModManager.java:239)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupHome(FMLLaunchHandler.java:90)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupClient(FMLLaunchHandler.java:67)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.relauncher.FMLLaunchHandler.configureForClientLaunch(FMLLaunchHandler.java:34)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraftforge.fml.common.launcher.FMLTweaker.injectIntoClassLoader(FMLTweaker.java:125)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraft.launchwrapper.Launch.launch(Launch.java:115)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.reflect.Method.invoke(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at org.jackhuang.hellominecraft.launcher.Launcher.main(Launcher.java:120)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]: Caused by: java.lang.ClassNotFoundException: cpw.mods.fml.relauncher.IFMLLoadingPlugin[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.ClassLoader.loadClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at java.lang.ClassLoader.loadClass(Unknown Source)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
... 28 more[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]: Caused by: java.lang.NullPointerException[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182)[20:52:53] [launcher/INFO] [STDERR]: [java.lang.Throwable$WrappedPrintStream:println:-1]:
... 30 more[20:52:53] [launcher/ERROR] [FML]: An error occurred trying to configure the minecraft home at F:\Magic craft\.minecraft for Forge Mod Loaderjava.lang.NoClassDefFoundError: cpw/mods/fml/relauncher/IFMLLoadingPlugin
at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.7.0_79]
at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.7.0_79]
at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.7.0_79]
at java.net.URLClassLoader.defineClass(Unknown Source) ~[?:1.7.0_79]
at java.net.URLClassLoader.access$100(Unknown Source) ~[?:1.7.0_79]
at java.net.URLClassLoader$1.run(Unknown Source) ~[?:1.7.0_79]
at java.net.URLClassLoader$1.run(Unknown Source) ~[?:1.7.0_79]
at java.security.AccessController.doPrivileged(Native Method) ~[?:1.7.0_79]
at java.net.URLClassLoader.findClass(Unknown Source) ~[?:1.7.0_79]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:117) ~[launchwrapper-1.11.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_79]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_79]
at java.lang.Class.forName0(Native Method) ~[?:1.7.0_79]
at java.lang.Class.forName(Unknown Source) ~[?:1.7.0_79]
at net.minecraftforge.fml.relauncher.CoreModManager.loadCoreMod(CoreModManager.java:447) ~[forge-1.8-11.14.1.1333.jar:?]
at net.minecraftforge.fml.relauncher.CoreModManager.discoverCoreMods(CoreModManager.java:371) ~[forge-1.8-11.14.1.1333.jar:?]
at net.minecraftforge.fml.relauncher.CoreModManager.handleLaunch(CoreModManager.java:239) ~[forge-1.8-11.14.1.1333.jar:?]
at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupHome(FMLLaunchHandler.java:90) [forge-1.8-11.14.1.1333.jar:?]
at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupClient(FMLLaunchHandler.java:67) [forge-1.8-11.14.1.1333.jar:?]
at net.minecraftforge.fml.relauncher.FMLLaunchHandler.configureForClientLaunch(FMLLaunchHandler.java:34) [forge-1.8-11.14.1.1333.jar:?]
at net.minecraftforge.fml.common.launcher.FMLTweaker.injectIntoClassLoader(FMLTweaker.java:125) [forge-1.8-11.14.1.1333.jar:?]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:115) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_79]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_79]
at org.jackhuang.hellominecraft.launcher.Launcher.main(Launcher.java:120) [HMCL-2.3.5.0.exe:?]Caused by: java.lang.ClassNotFoundException: cpw.mods.fml.relauncher.IFMLLoadingPlugin
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.11.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_79]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_79]
... 28 moreCaused by: java.lang.NullPointerException
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.11.jar:?]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_79]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_79]
... 28 more[20:52:54][launcher/ERROR] Cought exception!Minecraft崩溃了!请认真阅读建议。Minecraft不完整或Mod冲突,如果有未能下载的文件请下载成功后重试或是客户端损坏请重试请重新制作客户端或下载整合包解决问题。java.lang.reflect.InvocationTargetExceptionat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)at java.lang.reflect.Method.invoke(Unknown Source)at org.jackhuang.hellominecraft.launcher.Launcher.main(Launcher.java:120)Caused by: java.lang.NoClassDefFoundError: cpw/mods/fml/relauncher/IFMLLoadingPluginat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(Unknown Source)at java.security.SecureClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.access$100(Unknown Source)at java.net.URLClassLoader$1.run(Unknown Source)at java.net.URLClassLoader$1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(Unknown Source)at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:117)at java.lang.ClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Unknown Source)at net.minecraftforge.fml.relauncher.CoreModManager.loadCoreMod(CoreModManager.java:447)at net.minecraftforge.fml.relauncher.CoreModManager.discoverCoreMods(CoreModManager.java:371)at net.minecraftforge.fml.relauncher.CoreModManager.handleLaunch(CoreModManager.java:239)at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupHome(FMLLaunchHandler.java:90)at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupClient(FMLLaunchHandler.java:67)at net.minecraftforge.fml.relauncher.FMLLaunchHandler.configureForClientLaunch(FMLLaunchHandler.java:34)at net.minecraftforge.fml.common.launcher.FMLTweaker.injectIntoClassLoader(FMLTweaker.java:125)at net.minecraft.launchwrapper.Launch.launch(Launch.java:115)at net.minecraft.launchwrapper.Launch.main(Launch.java:28)... 5 moreCaused by: java.lang.ClassNotFoundException: cpw.mods.fml.relauncher.IFMLLoadingPluginat net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191)at java.lang.ClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)... 28 moreCaused by: java.lang.NullPointerExceptionat net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182)... 30 more[20:52:55] [launcher/INFO] [STDOUT]: [org.jackhuang.hellominecraft.launcher.Launcher:println:46]: *** Game Exited ***
贴吧热议榜
使用签名档&&
保存至快速回贴4212 条评论分享收藏感谢收起sourceforge.net很遗憾,都是英文的,国内的估计这两个链接基本解决了学习资料问题或者 帮51CTO做广告了。还有CSDN、博客园、开源中国和pudn这几个网站都不错。关于学习JAVA的网站,先说明一下:stackoverflow一个IT的问答网站很多人推荐不懂去stackoverflow,英语好的真不错,但是你看一下吧对于广大英语不好的人来说,这就想当尴尬了。如果你能为了解决JAVA问题,达到废寝忘食的地步,至少睡下去以后还在思考JAVA问题,那么恭喜你,你已进入状态,成功就在不远处。---------------------------------------------------小贴士3:安卓为什么要用Java来改造大家知道安卓是google公司在Java的基础上改造而来的,现在Google和Oracle公司还在打官司,那么为什么安卓要选Java呢,这得回到Java的起源了,大家知道Java当初叫Oak,Oak语言当初真正的目的是为了解决消费电子产品(电视机顶盒、面包烤箱、移动电话)的智能化,由于没有市场需求,Sun公司才拼命让其适应互联网的发展,你瞧,30年以前这些人已经想到并为此设计出语言了,所以Java从开始就非常适合嵌入式设备、移动设备,Java就是为它们量身定制的。只是过于超前,市场没有这种需求,所以现在市场出现需求以后,Java的优点就立即被发现,同时也为Java创造出另外一片天地。本来应该有个JAVA学习路径,但是这个网上到处都有,各位答主也给出了详细的说法,路径基本上都一样,所以不再详细阐述了,大家网上搜一下就可以了。-----------------------------------------------------赞同 12914 条评论分享收藏感谢收起&figure&&img src=&https://pic1.zhimg.com/v2-a0204c24bfd0da5cdda01df77509de8a_b.jpg& data-rawwidth=&691& data-rawheight=&565& class=&origin_image zh-lightbox-thumb& width=&691& data-original=&https://pic1.zhimg.com/v2-a0204c24bfd0da5cdda01df77509de8a_r.jpg&&&/figure&本篇文章来自我的回答:&a href=&https://www.zhihu.com/question//answer/& class=&internal&&GitHub 上有哪些优秀的 Java 爬虫项目?&/a& 但是在此回答上做了一些修改以及增加了一些项目,这些项目来自github和开源中国,希望这些开源Java爬虫项目对大家有帮助。阅读源码可以帮你得到一个质的提升。&br&&br&1、Gecco&br&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/xtuhcy/gecco& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&xtuhcy/gecco&/a&&br&&blockquote&Gecco是一款用java语言开发的轻量化的易用的网络爬虫。整合了jsoup、httpclient、fastjson、spring、htmlunit、redission等框架,只需要配置一些jquery风格的选择器就能很快的写出一个爬虫。Gecco框架有优秀的可扩展性,框架基于开闭原则进行设计,对修改关闭、对扩展开放。&br&&/blockquote&&br&2、WebCollector&br&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/CrawlScript/WebCollector& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&CrawlScript/WebCollector&/a&&br&&blockquote&WebCollector是一个无须配置、便于二次开发的JAVA爬虫框架(内核),它提供精简的的API,只需少量代码即可实现一个功能强大的爬虫。WebCollector-Hadoop是WebCollector的Hadoop版本,支持分布式爬取。&/blockquote&&figure&&img src=&https://pic2.zhimg.com/v2-99b4ea7cfa280c1f1e5f37073fcb78f1_b.png& data-rawwidth=&710& data-rawheight=&577& class=&origin_image zh-lightbox-thumb& width=&710& data-original=&https://pic2.zhimg.com/v2-99b4ea7cfa280c1f1e5f37073fcb78f1_r.jpg&&&/figure&&br&3、Spiderman&br&码云地址:&a href=&http://link.zhihu.com/?target=http%3A//git.oschina.net/l-weiwei/Spiderman2& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&l-weiwei/Spiderman2 - 码云 - 开源中国&/a&&br&使用案例:&a href=&http://link.zhihu.com/?target=https%3A//my.oschina.net/laiweiwei/blog/100866& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&展现垂直爬虫的能力 - 像风一样自由&/a&&br&&blockquote&Spiderman 是一个基于微内核+插件式架构的网络蜘蛛,它的目标是通过简单的方法就能将复杂的目标网页信息抓取并解析为自己所需要的业务数据。&br&&/blockquote&&br&4、WebMagic&br&码云地址:&a href=&http://link.zhihu.com/?target=https%3A//git.oschina.net/flashsword20/webmagic& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&flashsword20/webmagic - 码云 - 开源中国&/a&&br&&blockquote&webmagic的是一个无须配置、便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫。webmagic采用完全模块化的设计,功能覆盖整个爬虫的生命周期(链接提取、页面下载、内容抽取、持久化),支持多线程抓取,分布式抓取,并支持自动重试、自定义UA/cookie等功能。&/blockquote&&figure&&img src=&https://pic3.zhimg.com/a0204c24bfd0da5cdda01df77509de8a_b.jpg& data-rawwidth=&691& data-rawheight=&565& class=&origin_image zh-lightbox-thumb& width=&691& data-original=&https://pic3.zhimg.com/a0204c24bfd0da5cdda01df77509de8a_r.jpg&&&/figure&&br&5、Heritrix&br&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/internetarchive/heritrix3& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&internetarchive/heritrix3&/a&&blockquote&Heritrix是一个开源,可扩展的web爬虫项目。用户可以使用它来从网上抓取想要的资源。Heritrix设计成严格按照robots.txt文件的排除指示和META robots标签。其最出色之处在于它良好的可扩展性,方便用户实现自己的抓取逻辑。&br&&/blockquote&&figure&&img src=&https://pic3.zhimg.com/v2-2a7bf15d574fa947687da_b.jpg& data-rawwidth=&699& data-rawheight=&531& class=&origin_image zh-lightbox-thumb& width=&699& data-original=&https://pic3.zhimg.com/v2-2a7bf15d574fa947687da_r.jpg&&&/figure&&br&6、crawler4j&br&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/yasserg/crawler4j& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&yasserg/crawler4j · GitHub&/a&&blockquote&crawler4j是Java实现的开源网络爬虫。提供了简单易用的接口,可以在几分钟内创建一个多线程网络爬虫。&br&&/blockquote&&br&&p&7、Nutch&/p&&p&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/apache/nutch& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&apache/nutch&/a&&/p&&blockquote&Nutch 是一个开源Java 实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。&br&&br&在Nutch的进化过程中,产生了Hadoop、Tika、Gora和Crawler Commons四个Java开源项目。如今这四个项目都发展迅速,极其火爆,尤其是Hadoop,其已成为大规模数据处理的事实上的标准。Tika使用多种现有的开源内容解析项目来实现从多种格式的文件中提取元数据和结构化文本,Gora支持把大数据持久化到多种存储实现,Crawler Commons是一个通用的网络爬虫组件。&/blockquote&&br&&p&8、SeimiCrawler&/p&&p&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/zhegexiaohuozi/SeimiCrawler& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&zhegexiaohuozi/SeimiCrawler&/a&&/p&&blockquote&SeimiCrawler是一个敏捷的,独立部署的,支持分布式的Java爬虫框架,希望能在最大程度上降低新手开发一个可用性高且性能不差的爬虫系统的门槛,以及提升开发爬虫系统的开发效率。在SeimiCrawler的世界里,绝大多数人只需关心去写抓取的业务逻辑就够了,其余的Seimi帮你搞定。设计思想上SeimiCrawler受Python的爬虫框架Scrapy启发,同时融合了Java语言本身特点与Spring的特性,并希望在国内更方便且普遍的使用更有效率的XPath解析HTML,所以SeimiCrawler默认的HTML解析器是JsoupXpath(独立扩展项目,非jsoup自带),默认解析提取HTML数据工作均使用XPath来完成(当然,数据处理亦可以自行选择其他解析器)。并结合SeimiAgent彻底完美解决复杂动态页面渲染抓取问题。&br&&/blockquote&&figure&&img src=&https://pic2.zhimg.com/v2-deddde4ba45fec45_b.png& data-rawwidth=&972& data-rawheight=&309& class=&origin_image zh-lightbox-thumb& width=&972& data-original=&https://pic2.zhimg.com/v2-deddde4ba45fec45_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-ce7d5cb896c9d0fdf0be12efa892e83a_b.png& data-rawwidth=&632& data-rawheight=&318& class=&origin_image zh-lightbox-thumb& width=&632& data-original=&https://pic3.zhimg.com/v2-ce7d5cb896c9d0fdf0be12efa892e83a_r.jpg&&&/figure&&br&&p&9、Jsoup&/p&&p&github地址:&a href=&http://link.zhihu.com/?target=https%3A//github.com/jhy/jsoup/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&jhy/jsoup&/a&&/p&&p&中文指南:&a href=&http://link.zhihu.com/?target=http%3A//www.open-open.com/jsoup/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&jsoup开发指南,jsoup中文文档&/a&&/p&&blockquote&jsoup 是一款Java 的HTML解析器,可直接解析URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。&br&&/blockquote&&figure&&img src=&https://pic2.zhimg.com/v2-2eabca585e938a_b.jpg& data-rawwidth=&1023& data-rawheight=&424& class=&origin_image zh-lightbox-thumb& width=&1023& data-original=&https://pic2.zhimg.com/v2-2eabca585e938a_r.jpg&&&/figure&
本篇文章来自我的回答: 但是在此回答上做了一些修改以及增加了一些项目,这些项目来自github和开源中国,希望这些开源Java爬虫项目对大家有帮助。阅读源码可以帮你得到一个质的提升。 1、Gecco github地址:
&figure&&img src=&https://pic2.zhimg.com/v2-155bbc3e7c52a66c0c51c0_b.jpg& data-rawwidth=&1196& data-rawheight=&826& class=&origin_image zh-lightbox-thumb& width=&1196& data-original=&https://pic2.zhimg.com/v2-155bbc3e7c52a66c0c51c0_r.jpg&&&/figure&&p&先写别忙着颤抖,这篇并不是那种“我坚持每天早上4点起床,然后进行20km长跑…”的励志鸡汤,我也不希望让别人觉得自己必须变成琦玉老师那种超人,才能做一个好程序员。&/p&&p&&br&&/p&&p&&b&有些人可能知道我,就是 Instagram 上那个“每天沉迷编程的妹子”,&/b&但我之前可从来没有跟人分享过自己真实的日常生活,也从没提过为了成为一名软件开发者,我都做出过哪些努力,今天我就来和大家分享一下~&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a5a18e6cc7008f1caa8626fbe85f9f97_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&626& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-a5a18e6cc7008f1caa8626fbe85f9f97_r.jpg&&&/figure&&p&&br&&/p&&h2&我是如何爱上写代码的&/h2&&p&&br&&/p&&p&&b&我叫 Lydia,是个住在瑞典斯德哥尔摩的19岁女生,而且我也是一名 JavaScript (React) 程序员!&/b&我在社交媒体上相当活跃,一直通过分享我在技术社区的日常生活,尝试鼓励更多的人加入到编程世界中来。&/p&&p&&br&&/p&&p&&b&我开始学着写代码的时候才15岁。那时我就开始学着编写一个我自己的响应式设计布局,用的就是通常的 HTML、CSS 和 jQuery 等。&/b&在那之后,我不断尝试磨练自己的技术,拓展自己的知识面,培养对编程的兴趣。然而,我当时完全不知道这个已经就算是编程,而且我完全可以靠这个技术养活自己,当时我单纯是沉迷于这种从头开始创造自己独有设计的成就感,同时还发现人们喜欢我做的这些设计,甚至愿意为此付钱!&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-ec3d5210158beedc062fe664b4f4456f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&386& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/v2-ec3d5210158beedc062fe664b4f4456f_r.jpg&&&/figure&&p&&br&&/p&&p&我上高中一直上到18岁,在高中毕业后,我打算不去上大学。对我来说这是非常可怕的一个决定,我当时也觉得只有上大学才能让我拥有一个光明的未来:我身边的人都去了那些最顶级的大学呢!何况,我在高中阶段付出了那么多的努力,尝试取得最好的成绩,最终不就是为了能上一所好的大学么?我是不是真的白白浪费了生命中的这好多年时光?&/p&&p&&br&&/p&&p&嗯,差不多是这样,但我并不完全为此感到后悔!我周围的大部分人并不理解我,认为我犯了巨大的错误,但也有一小部分人能理解并全力地支持了我,这真的给了我很大的动力。&/p&&p&&br&&/p&&p&我一直非常独立自主:18岁那年我就独自去另一个国家居住,十几岁的时候就自己一个人四处旅行,我从来不会因为别人希望我做什么事,就让自己被迫去做那件事,我总是做好我自己的事情。在我最终决定不去上大学,&b&而是花上110%的努力去学编程之后,我跑去美国弗洛里达州坦帕湾,参加了一次为期3个月的编程训练营。&/b&&/p&&p&&br&&/p&&p&我也不是非得去报这种班,但这确实让我受益良多。这让我对编程有了系统性的认识,还让我得以身处许许多多热爱编程的人之中,这些都是我从未经历过的。这期间,我集中精力编写代码,不断突破自己的心理舒适区(这是我喜欢的),在我个人的项目上花费大量的努力,提升编程水平,还掌握了非常多的新技术。&/p&&p&&br&&/p&&p&猜猜怎么着?即使就在那三个月里,多得吓人的猎头电话拼命打进来,问我能不能去某个公司上班。这都是在我创建了 LinkedIn 账户,把我花费许多努力完成的工作展示出来之后。对于我这样一名没有任何工作经验的19岁女生来说,这有点太让我不知所措了。我无法理解的是,他们没有看我的 LinkedIn 页面内容吗?我根本没有上过什么大学,那些公司为什么要我?&/p&&p&&br&&/p&&p&因为单是在学校念书是没法真正学会编程的。你必须通过实际编写程序来学会编程。大部分公司根本不关心你有没有一张证书来证明你在某个冠冕堂皇的大学里学过编程。人们关心的是你展示出来的良好编程水平,以及对编程的热爱。&/p&&p&&br&&/p&&p&&b&但别误解我的意思。如果你喜欢大学生活,或者只是需要生活中多一点有序,那么去大学念书当然是个很棒的决定。&/b&然而,不要觉得有压力。编程社区的生活可能会很艰苦:人们因为对方使用的编程语言而相互鄙视,他们觉得什么每天彻夜编程只睡两个小时,什么整天坐着一动不动吃些垃圾食品都是很正常的,好像程序员都是这样的。这完全就不是那么一回事。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-bb81a1c6ff1b9de74106_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&379& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-bb81a1c6ff1b9de74106_r.jpg&&&/figure&&p&&br&&/p&&h2&我的日常生活&/h2&&p&&br&&/p&&p&在编程训练营结束后,我飞回了斯德哥尔摩。我极度兴奋地想要开始这人生的新篇章,等不及要让自己继续成长。&b&那么,如今我的日常生活中,都做些什么呢?&/b&&/p&&p&&br&&/p&&p&&b&1、我尝试早晨起来先伸展一下。&/b&这听起来是不是超像开头说到的那种“励志鸡汤”(这种心灵垃圾在 LinkedIn 上似乎到处都是,简直要把我逼疯!),但这其实非常重要。平时的你一坐就是好几个小时,如果你对此漠不关心的话,你的身体肯定有够受的了。同时,这也很能让你清醒,因为在伸展运动的时候,你的心率增加,血液循环更好了,大脑也能获得更多的氧气。&/p&&p&&br&&/p&&p&&b&2、我尝试每天起码花2小时参加在线编程课。&/b&我特爱看那些在线课程,因为在看老师写这类简单的代码时,我总是能学到新知识,获得新灵感。我也尝试过一个类似的项目,希望能给这类在线课程带来一些我自己的风格,当然会有些不同,我并不是简单地照抄别人的做法。同时,这类课程可以让我不需要从温暖的被窝中爬出来,也还能觉得自己充满生产力。&/p&&p&&br&&/p&&p&&b&3、我尝试每天花至少4小时在我个人的项目上。&/b&这些项目让我超级不舒服。我经常试着采用一些我从未用过的语言或者技术,这样我能积累更多关于它们的经验。&/p&&p&&br&&/p&&p&&b&我实话实说,这有时简直是太恐怖了!&/b&我可不是要骗你说什么“如果你足够努力就一定能达到目的”之类的(当然你能达到目的,但重点不在这里),但我也还是想要强调一句:&b&事实上,学习某种新东西真的会导致某种情绪上的大崩溃。你会觉得意气消沉,觉得好像你永远也无法理解它,还对自己的编程水平表示深深的疑惑。如果你也遇到这样的情况,那恭喜你!你非常正常,每个人都是这样的!&/b&&/p&&p&&br&&/p&&p&体验到这样的挫折其实不是重点,你如何应对它才是最重要的部分。研究它,向其他人求助,在 StackOverflow 描述你遇到的问题(对许多同样遇到这问题的人,你就是个英雄),不断尝试直到你找到解决方案。即使你没能找到,这样完全没关系。在一段时间以后,你或许会回来看看,并意识到“我干嘛不把这个东西弄回来呢?”&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-feda86ad4ee68bf3b0c3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&403& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-feda86ad4ee68bf3b0c3_r.jpg&&&/figure&&p&&br&&/p&&p&&b&4、我尝试每天阅读2篇文章。&/b&我特别喜欢从不同的观点看问题。这些文章可能关于任何事情:如何解决某个特定的编程问题,为什么 JavaScript 有时很烂,或者最酷炫的新技术都是啥……重要的是,不要让你的脑子卡在某种思维定势里!&/p&&p&&br&&/p&&p&&b&5、我尝试每天解决 5 个 CodeWars 的谜题。&/b&如果你是刚涉足编程,CodeWars 将是你的最佳伴侣,但即使你已经敲了几十年代码,它依旧可以是你的好朋友!他们提出的那些问题的解法往往非常实用,即使你只是阅读别人提交的答案,也能学到很多,大大优化你自己的代码风格。而且这还有额外福利:当你参加技术面试的时候,他们拿出来考你的问题就常常和 CodeWars 上的很相似!&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-afd59aa95adbb87b1331c1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&530& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-afd59aa95adbb87b1331c1_r.jpg&&&/figure&&p&&br&&/p&&p&我花了很长时间,才学会当自己没有整天工作的时候,不要为此内疚。特别是当我开了 Instagram 之后:我总是看到别人贴出自己在写代码的帖子,让我觉得我也该这样,怎么可以有时间让自己一整天无所事事呢。但当我将放松作为我生活中的一个重要部分之后,一切都好多了。&b&我感觉自己更加快乐,而且也更有动力进行许多工作。&/b&&/p&&p&&br&&/p&&p&&b&写这篇文章的初衷是,希望能鼓舞更多的人也加入这个技术世界来,这里并不像它看起来那么可怕。&/b&编程并不是只有电影中那些脑力无敌的超级英雄才能参与的活动。编程是为那些热爱创造、勇于离开心理舒适区的人,以及所有希望改善自己生活的人准备的!&/p&&p&&br&&/p&&p&综上所述,我最后的建议是:&/p&&p&&br&&/p&&p&1、只要你能真正推动自己去学习,并展示出你编程的热情就行。&/p&&p&&br&&/p&&p&2、总是尽110%的努力去付出,向世界展示你的能力,让大家看到你的名字。然而,一定要把身体健康摆在前面。睡眠是很重要的!&/p&&p&&br&&/p&&p&3、觉得不舒服,或者觉得自己在编程上特别烂,都是完全正常的,不要被这种挫折感打趴下。每个人都时不时会有这样的感觉。&/p&&p&&br&&/p&&p&4、总是提醒自己,你已经成功走出了这么远。人们很容易忘记自己比过去提高了多少,但你只需要和一个月前的自己比一比,我确定,你学到的一定比你自己认为的多。&/p&&p&&br&&/p&&p&5、别受其他人影响,觉得自己用的编程语言不好。基本上它并不会不好,而且很可能是非常必须而且有用的!&/p&&p&&br&&/p&&p&最后放出妹子的Instagram,有兴趣的朋友可以去粉下交流下~&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-0dd63cfe72a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&148& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/v2-0dd63cfe72a_r.jpg&&&/figure&&blockquote&文/ Lydia Hallie&br&译/ 欧剃&br&编辑/ 编辑去打羊胎素了&br&来源/ &a href=&https://link.zhihu.com/?target=https%3A//medium.com/%40lydiahallie/advice-from-a-19-y-o-girl-software-developer-88737bcc6be5& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&medium.com/@lydiahallie&/span&&span class=&invisible&&/advice-from-a-19-y-o-girl-software-developer-88737bcc6be5&/span&&span class=&ellipsis&&&/span&&/a&&/blockquote&&p&&b&本文首发于微信订阅号优达学城Udacity(id:youdaxue),关注订阅号,回复关键字“学习资料”,获取来自硅谷的包括“机器学习”、“深度学习”、“数据分析”和“前端开发”在内的独家学习资料。&/b&&a href=&https://link.zhihu.com/?target=https%3A//cn.udacity.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&优达学城 (Udacity) - 传授硅谷的名企官方课程&/a&&/p&&p&欢迎大家踊跃投稿~可以通过私信联系优达菌~&/p&
先写别忙着颤抖,这篇并不是那种“我坚持每天早上4点起床,然后进行20km长跑…”的励志鸡汤,我也不希望让别人觉得自己必须变成琦玉老师那种超人,才能做一个好程序员。 有些人可能知道我,就是 Instagram 上那个“每天沉迷编程的妹子”,但我之前可从来没…
&p&最简单的答案:利用JDBC driver和MySQL数据库建立TCP连接之后的连接对象放在池中,当需要操作数据库的时候从池中取出一个连接,发送SQL到MySQL,MySQL经过SQL语法解析、查询优化、生成实际物理计划及执行、连接处理与类型处理等一系列的过程之后返回要查询的数据给JDBC driver的resultset。把连接对象重新放到池子中&/p&&p&面试官会加深问一些东西,那可以问就太多了,如下:&/p&&ul&&li&首先是tcp建立连接的过程,什么握手挥手这些问题都要准备好,什么tcp udp也要准备好,什么7层网络也要准备好,最好连每一层的数据包格式都准备好。&/li&&li&拿到一个连接之后放在对象池中,以及为什么要用“池”,可以扩展到线程池以及各种池化好处。也可以说一下池子的各种参数min、max、active等最好和线程池结合起来,和常用的数据库连接池&/li&&li&如果是JAVA岗位,面试官一般都关注在java层面,可以问一些PreparedStatement和Statement的区别和注意事项,SQL注入等&/li&&/ul&&p&如果是基础面试回答上面的就差不多了,都能回答上基本上基础就不错了&/p&&p&如果是考察深度的面试这个问题可以说是一个非常好的面试题,可以从下面几个点开展对面试者的考察&/p&&ul&&li&网络(把从物理层到应用层的包结构都讲一遍,下图的网关是什么意思知道吗,为什么要设置,为什么要子网掩码等等。反正太多,我也答不上来【尴尬脸】),tcp\ip、I/O(阻塞非阻塞,同步非同步),reactor、proactor&/li&&/ul&&figure&&img src=&https://pic1.zhimg.com/50/v2-7bc0ebdb9f53e54ed1b32f7b3e1ea358_b.jpg& data-caption=&& data-size=&small& data-rawwidth=&774& data-rawheight=&886& class=&origin_image zh-lightbox-thumb& width=&774& data-original=&https://pic1.zhimg.com/50/v2-7bc0ebdb9f53e54ed1b32f7b3e1ea358_r.jpg&&&/figure&&ul&&li&jdbc driver 工作原理,分布式数据库中间件(可以问的太多不列举),分库分表,主备&/li&&li&数据库ACID(事务隔离级别、redolog undolog、各种锁 eg,悲观、乐观、间隙锁等等),索引,附带一些数据结构 B-TREE、2-3树、红黑树、 AVL树都可以问一遍&/li&&/ul&
最简单的答案:利用JDBC driver和MySQL数据库建立TCP连接之后的连接对象放在池中,当需要操作数据库的时候从池中取出一个连接,发送SQL到MySQL,MySQL经过SQL语法解析、查询优化、生成实际物理计划及执行、连接处理与类型处理等一系列的过程之后返回要查询…
这几天比较忙。加个插曲。&br&
前两天面试了一个四年工作经验的Java工程师,挺失望的。工作换了四五家,大多浅尝则止,基础太差了。面试别人,一般基于其项目经历和简历的技能栈交流。没想到,这次交流成了授课了。“大处着眼,小处落手”,一个技术人员既要具备技术视野,也要理解技术细节。&br&&br&比较有感触的有下面几个问题。首先,我问了一个很多人平时意识不到的问题:一个.java文本文件,是如何运行起来的?本来是想检查下对Jave程序语言的运行机制的理解。如果回答可以就可以切入到虚拟机和java程序性能调优。没想到大失所望,该同学对此几乎没有概念。接下来,我问,HashMap的内部实现,不清楚,key是否可以是null,不知道。让其写一个简单的栈Stack类,实现基本的存取功能,我把结构都写了,让他下笔,写不出来。本来是考察对基本数据结构的理解,可能的话切入内存泄露。&br&&br&
到此,我已经基本确认该同学之前基本不写代码了。但他应聘的是中高级工程师,本着负责的态度。该问的还得继续。看项目经历吧,有个做OA系统的经验,熟悉Jbpm,看简历写着熟悉设计模式。好吧,我问:如果让你设计一个简单的流程引擎,你怎么设计,大概会用到什么设计模式。我想着,怎么着,你也应该知道责任链模式和观察者模式吧,退一步讲,一个好的系统,工厂模式、建造者模式不可能没有。对方一脸懵逼,说,没去了解过。说实在的,当时真的是有点不耐烦了。&br&&br&看到简历有mybatis技能,问动态sql拼装有哪些常用标签,回答差强人意。问得深一点:平时使用mybatis基本都是使用接口声明,然后注入直接调用接口方法,即可完成数据库操作。有没有疑惑过,为什么没看到实现该接口的类,就可以调用方法。要知道接口是不能实例化的。本意是考察对代理类生成(代理模式)的理解,不出所料,完全没有概念。随后简单问了下数据库,居然不知道索引是一棵树,,,&br&&br&随后草草收场。&br&&br&简单描述本次面试经历,我是觉得该面试者是一个典型。“大处着眼”,他不知道技术和框架出现的背景是什么,技术视野窄,不知道用什么技术解决实际问题,也没有关心前沿技术(分布式、服务化、大数据);“小处着手”,他没有探究内部原理的好奇心和意识,小一点说连“点进去JDK类的实现方法”的欲望都没有。&br&&br&我不知道这样技术深度和广度都没有的水平,怎么能实现他所说的“三年成为一个优秀的架构师”的愿望。&br&&br&感慨万千啊。&br&&br&###&br&多线程和虚拟机。实际工作中,大部分程序员可能几乎不用,但这两项技能是你面试所谓高级工程师的敲门砖,也是你在机会到来的时候能否顶上去的弹药库。很多人,把这两部看的太高深,望而却步,我觉得一个重要原因就是大部分博客和书籍写的太差,只讲结果不谈背景。比如,讲到虚拟机,上来就以hotspot为例,内存模型,各种分区、回收算法;讲到多线程,上来就各种synchronized关键字、各种锁、线程池怎么用。新手看到就蒙了。要知道,一切技术的出现都是有背景的。所有技术的出现都是基于计算机原理和体系结构的。为了解决特定问题,人们基于计算机理解的语言才创造了各种解决问题的方法,也就是说这些解决方案不过是践行某种思想的一种体现罢了。&br&&br&
先说虚拟机,我们都知道Java程序运行在虚拟机上,虚拟机又和操作系统打交道,最终通过二进制指令操纵电子电路运行。完成数据的读取,存储,运算和输出。&br&
虚拟机在加载.class文件的时候,会在内存开辟一块区域“方法区”,专门用来存储类的基本信息,同时在“堆”区为这些类生成一个Class对象,作为类的“镜像”或“模具”,为反射提供基础。程序运行过程中,对象不断的生成和死亡,有的朝生暮死(大多数对象都这样,最常见的是方法内部生成的临时对象),有的壮年而亡,有的长命百岁,有的长生不死除非世界毁灭(虚拟机关闭,典型的如servlet)。对象生要吃喝,死了得埋,所以虚拟机就不停的申请内存、回收内存。对象的生成方法很多,new、反射等,对象回收的方法也有很多,这就是GC,标记-清除、复制、标记-整理等等。&br&&br&垃圾回收,顾名思义,得确定垃圾是什么、在那里、如何回收。对象的生命周期不同,回收的方法不一样。假如让你设计垃圾回收,你该怎么做?大多数人都会想到,后台启动一个线程,隔一段时间(或达到某种状态,去堆用掉了80%),扫描垃圾对象,然后清除,然后继续执行原来的程序(串行收集器)。恭喜你,你也可以设计虚拟机了。但不幸的是,情况往往比你想象的复杂。效率、安全性、对原程序的影响,都是你要考虑的。人们最先发现,对象生命周期不同,用同一种GC方法,实在是效率差,怎么办?就如hotspot的方案,堆区根据对象生命周期不同,分成了Eden、Survivor0、Survivor1和Old区。每个区采用了不同的清理算法。多核的出现,自然人们会想到并行收集器,即多个回收线程一起跑;为了将对原程序影响降到最低(STW),又出现了并发收集器。这些,本质上,就是抽象分层思想的体现。类似于,重构代码中的,抽离属性和抽离方法。这种思想,我认为是计算机最重要的思想。可以讲三天三夜。如分布式服务中,根据业务模型,分拆用户服务、商品服务、订单服务。&br&&br&到此为止,虚拟机优化就涉及到两大方面,各个区的大小怎么划分最优、垃圾回收算法怎么选择最优。直接点,就是JVM参数调整。但关键在于,给你一个系统(可能是一个陌生的系统,我说的陌生可能就是你开放的系统,只是每个人负责的只是一个模块,对系统整体不熟悉),你怎么样能恰当估算系统业务情况,进而有针对性的收集系统数据,根据场景,确定优化的方向点,然后找到这个点对应的虚拟机参数,调整参数,或者,优化代码。注意,一切优化必须基于业务模型。不同业务系统、甚至同一套系统不同用户基数调整的方向都不一样。平时,我遇到的情况大概分为两种,一种是堆的问题,比如代码问题导致List或map越来越大,或者是string使用不当,造成频繁old gc;某个外部组件调用,生成大量代理类无法销毁。还有一种是线程栈,线程阻塞甚至死锁的问题。多线程使用不当,比不使用还坑爹。&br&&br&多线程,任何一个程序员都知道,但实际工作中,大部分程序员每天面对的基本是业务问题的CRUD和Bug定位,貌似没有直接接触多线程的机会。&br&&br&大家知道程序运行的时候,最关键的是内存和cpu,而cpu运算的时候,是要从内存取值,当然很多时候是从缓存取值的,然后放入寄存器,参与运算,得到结果,先放入寄存器,然后放入内存。程序执行的指令也放在寄存器,它记录了当前程序执行的地址。用一句话概括:程序=数据结构+算法。CPU运算需要知道,我要执行什么程序、我的程序数据怎么获取。&br&&br&大家应该看出问题来了吧?首先,线程执行是语言指令寄存器的,也就是当你切换线程的时候,得从虚拟机的程序计数器(PC)把该线程的执行指令放到指令寄存器,当然线程涉及的其他资源也要切换,比如IO设备。这些都是需要耗费资源的,这就是所谓的线程上下文切换。大学时候,记得很清楚的一句话:线程是CPU执行的最小单位。当时没怎么理解,后来想CPU执行程序,总得知道执行什么吧,那得准备指令寄存器的值,原材料得有吧,就可能涉及文件系统、网络资源吧,运算结果得输出到内存、文件或者网络吧。这些都是资源啊。所以,线程创建是一笔很大的开销。当然,如果你就一个线程,那就无所谓了,反正资源都是我的,想怎么用就怎么用。所以,很多时候,单线程比多线程快。&br&&br&很多面试宝典,有这么一道题:Java线程的start和run方法有什么区别?通过我上面关于线程执行的分析,应该一目了然。我用一个做饭的例子说明,start需要你买菜、准备锅碗瓢盆油盐酱醋、洗菜切肉,而run则是往锅里放油放菜炒。大家可以看到,Thread源码的start0是个native方法,也就是资源准备是虚拟机帮你做了。你不用管我菜是怎么买的、价钱多少。当然了,如果菜市场很远,一直没买到,或者排队很长,甚至被别人插队,那你这顿饭就一直做不上。这就是所谓的线程阻塞了。如果两个厨师都在做饭,一个拿着酱油想要醋,一个拿着醋想要酱油,互不相让,就出现所谓的死锁。不好意思,扯远了。关于start和run,如果把方法名改为:applyResourceAndPerformAction和doConcreteActions,是不是很容易理解?很多人面试的时候,背一下宝典,原理根本不清楚。你能指望他处理复杂问题?线程必须的资源虚拟机帮你做了,你需要的就是告诉线程你具体做什么,所以实现线程的几种方式就有了,1、继承Thread目的重写run方法;2、实现Runnable接口,实现run方法;3实现Callable接口,回调获取线程结果。1使用了继承,2和3使用了组合,内部持有了你所实现的类,更加灵活。你看,多用组合少用继承的原则就这么体现了。&br&&br&第二点,上面说到了,一个数值,进入CPU运算,经过了内存、多级缓存、寄存器,也就是说,当多线程运算同一个值的时候,是需要把值从主内存拿到该线程工作内存(寄存器)中的,当一个线程计算完毕(CPU首先把运算结果放到寄存器),还没刷新到主内存的时候,另一个线程从主内存取到的是旧值。JVM运行的每个线程都有自己的线程栈,不同线程运行的时候,都要复制主内存的一份副本到工作内存。怎么保证每个线程拿到的数据是最新的,这就是同步机制。volatile和synchronized,就是为了解决这个问题的。&br&&br&首先,谁都能想到的最直接的办法就是:共享变量同一时刻只允许有一个线程操作。这样就保证了所有线程要么拿不到值,要么拿到的值是“纯粹”的。于是有了synchronized,用来告诉虚拟机:这个地方是圣地,不允许多个人同时涉足。这里有一把锁,必须拿到锁才能进入,其他人要想进来必须等待。Java中的锁,可以是this对象、方法、类,也可以是声明的某个变量。锁的范围,可以是小块代码段,可以是整个方法区,甚至是所有方法。一定要注意锁和锁的范围,这是两个维度的事情。虚拟机会在锁对象和线程之间建立联系,其他线程跑到锁对象的时候,会看到:哦,其他哥们已经来了,我先等着吧。特别注意,不要以为对象和类的定义一样,不过是属性和方法的集合,类和对象是两回事。类似模具和产品的关系。虚拟机生成一个对象,这个对象有很多额外信息,起码有对象内存地址你是知道的吧?所以,要标识这个对象当前被哪个线程占有,是一件很容易的事情。感兴趣的同学,可以去看看对象在内存中的布局。&br&&br&我们很快发现,上面的方法有点粗暴,也不够灵活。很多时候,我们不关心共享值在被谁操作,我只关当前这个值“到底”是什么。所以,就有了volatile,大部分博客提到volatile,就一句话:保证可见性,不保证原子性。这什么鬼?实际上,如果一个共享变量声明为volatile,等于告诉虚拟机控制的所有线程:这个变量有点帅,要请他出山必须亲自去他老家——主内存去请,回来的时候也要尽快送回老家。所以,CPU计算的时候要从主内存取值,计算完毕,直接就写入主内存,不会写到高速缓存了。这就是所谓的“可见性”,也就是当前这个值是什么,你是完全知道的。至于不保证原子性,就很明显了,这个值谁都可以取来运算,从计算机角度来讲,跟普通变量的区别就在于:效率差了。因为写入和读取高速缓存,效率远远高于内存。一路题外话,不要以为数据库插入数据就直接到磁盘了,其实写入的也是缓存,由后台线程刷到磁盘的。这样既可以起到缓冲的作用,又可以提高效率。不然你以为怎么能那么快。其实,从底层到高层,从硬件到软件,很多原理都是相通的。&br&&br&———————————— &br&感谢朋友们的认可和指正。本文是有感而发,因为看过了太多坑人的博客和书籍,感慨自己走过的弯路,不希望其他初学者被网上互相抄袭的博客和东拼西凑的书籍浪费时间,想以一个相对宏观的视野来描述一个概念,力求通俗易懂,所以没有深入太多细节,简化了很多模型,给部分朋友造成了疑惑,说声抱歉。也没有配图,都是抽时间手机码字,打个分割线都费劲,图呢,其实网上都有。
&br&&br&记得我在另外一篇答案中提到,计算机程序(不仅仅各种语言的代码,一切能向计算机发出指令的序列都是程序,当然包括Java虚拟机)的努力方向:最大化利用计算机资源。多线程就是如此,一个CPU密集型的任务在跑,你让IO干等着,这不是浪费吗?所以,这时候你启动一个IO密集型的任务,资源利用率就提升了。当然,这是一种简化模型,实际上一个人任务的不同阶段,需要的计算机资源是不同的,如果你能合理安排多个任务的执行逻辑,资源利用率就会很大提升。&br&&br&我们学习程序语言,一定不要被束缚到语言细节和规范上去,而要从计算机逻辑执行层面思考问题。因为细节和规范都是人为设定的,是大牛抽象计算机逻辑后的加工品,你囿于此,其实是在理解别人的思想,而不是理解计算机。我们常说的高层依赖于抽象而不依赖于底层,是一样的意思。说了这么多,想表达的就是,对技术问题,要有思考的深度,要寻根溯源,要高屋建瓴。
&br&&br&回到多线程。上面提到synchronized,必须多说几句,这对理解锁的本质至关重要。多线程和锁,首先请大家记住一个场景:多人上厕所。&br&&br&多线程和锁,一个是线程,一个是对象。一个在私有的线程栈中,一个在共享的堆中。如何标识某个线程持有某个锁对象?如何如何标志某个对象被某个线程锁定?很显然,线程栈中开启一片区域“栈帧”存储对象锁记录,堆中对象有对象头(对象头主要保存了对象的类元数据,以及对象的运行时状态,其中就包括了锁线程和GC分代等信息。)可以标识被哪个线程锁定。实际上,虚拟机就是利用对象头和monitor(后面讲)来实现锁的。&br&&br&回到多人上厕所,人比做线程,厕所比做共享对象,锁比做对象头,monitor比做钥匙。&br&&br& synchronized锁的是一个对象,或者是类的某个实例,或者是类本身(即常量池的Class)。
synchronized内部原理是通过对象内部的一个叫做监视器(monitor)来实现的。本质又是依赖于底层的操作系统的Mutex Lock来实现的。而操作系统实现线程之间的切换需要从用户态转换到核心态,这个成本非常高,这就是为什么synchronized效率低的原因。比如Hashtable(再次吐槽小写t,浑身难受)和用Collections.synchronizedMap装饰的HashMap,内部都使用了 synchronized,所以性能差,不是因为“它性能差”,而是因为“它使用的同步方式”性能差,那天人家底层重写了性能高了你怎么办?很多时候,点下鼠标进入源码看几眼就知道的东西,没必要死记硬背。&br&&br&synchronized这种依赖于操作系统所实现的锁我们称之为“重量级锁”。JDK中对Synchronized做的种种优化,其核心都是为了减少这种重量级锁的使用。JDK1.6以后,为了减少获得锁和释放锁所带来的性能消耗,提高性能,引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。别被这些名词砸晕了,这些锁的名字很有误导性,其实是对获取锁的方式的优化,不是锁。&br&&br& 所谓锁的优化,主要方向是优化获取锁的方式和加锁(释放)的方式。我不想一一解释枯燥名词。还是用上厕所举例。重量级锁可以认为是,你去上厕所,得先去管理处(人或者机器)登记并拿到钥匙上厕所,这个过程可以认为存在一次“用户态”到“内核态”的切换。是非常重量级的。 &br&&br& 这里我必须强调一下,你的目标是上厕所,不是加锁,加锁只是为了你更好的上厕所。线程也一样,目的是为了完成某项任务。加锁是不得以为之的。&br&&br&假如一层楼就你一个人,一个厕所, 你觉得还有必要去登记吗?要什么自行车?直接上啊。这就是无锁状态;如果这层楼还有一个哥们,但他尿泡比较强悍,一天不上厕所。厕所门上有个显示器,能显示上次上厕所的是谁、期间有没有其他人上厕所,那你上的时候,只要看下显示器就知道:没别人上过,还是我,照片都没变,不用刷脸,此厕可直接上。这就是偏向锁,因为“偏向你”;假如这个哥们偶尔也上一次,这次你发现厕所有别人上过,因为显示器上有他照片,那你就得重新刷脸,好吧,那我再刷了上吧,大部分时候,里面都没这哥们,你可顺利上厕所,这叫轻量级锁;如果某天这哥们腹泻(我一同事吃湖南蒸菜有过一次),那你悲剧了,你每次上的时候,不仅显示器不是你,你想刷脸进入,发展里面还有人。没办法,只能去管理处登记等待了,变成了重量级锁。锁升级是不会降级的。这里,重量级锁涉及操作系统的处理,而偏向锁和轻量级锁涉及CAS,硬件可以搞定,效率更高。&br&&br&上述锁状态转移和加锁(解锁不讲了)是由虚拟机(配合操作系统)完成的,我们不可见,既然是虚拟机控制,当然就有相关参数,如是否启用偏向锁,我忘了参数名字,但我知道肯定有这样的参数。如果面试我的面试官因为我不知道参数名字鄙视我,我能反怼死他。记个别人定的名字很自豪?&br&&br&上面讲到重量级锁的时候,其实就是锁竞争很激烈的时候。比如早上高峰期,厕所坑位紧缺,排队的人很多,如果你一直等,等待的状态就叫“自旋”,当然你可以自旋十分钟左右后离开(虚拟机自旋也有参数控制),因为你觉得里面的哥们玩手机不知道啥时候结束,你有更重要的事情要干,还不如去外面登记等通知。显然,自旋的前提是你知道上一个哥们不会很久。多次之后,你会摸清这些人上厕所的时间后,你自旋起来就更有针对性了,这叫“适应性自旋”。&br&&br&还有,锁消除,锁粗化,比如基本没人用的StringBuffer、Vector,你用在某个方法中,其实根本没必要加锁,或者说比如连续的append,没必要每次都加锁,虚拟机就会进行锁消除或者锁粗化处理。&br&&br&上面讲了这么多,主体是线程和锁对象,核心是获取锁的方式和锁定的方式,还有,不加锁或者“伪加锁”是不是能搞定?再次强调一遍,线程生来是为了完成任务的,不是为了和锁纠缠的。&br&&br&多线程竞争锁的时候,肯定涉及到线程的排队,新来的线程怎么处理,是去竞争锁还是直接排队?排队中的线程,那些有资格竞争锁?有资格的线程,那个拿到锁(只是拿到锁,还未执行共享区)?不管怎么实现,这些东西是必须要考虑的。你在synchronized没见到,是因为虚拟机帮你处理了,涉及的队列也是虚拟机在维护。重量级锁的时候,又涉及和操作系统信号的交互。当然,要是你不用和操作系统进行如Mutex Lock这样“重量级的”交互也能更好、更快、更好的处理同步,那你就是大牛了。&br&&br&大牛当然是存在,比如李老头。下面会开始讲更加灵活的、细粒度、可定制的Lock锁。可以认为是把synchronized加锁的过程、锁定的方式等流程中细节拆分出来,用灵巧的实现方式实现线程同步。再后面会讲对象的wait、notify,线程的sleep,主体不一样,思考的角度不一样。今天先到这里——&br&&br&手机码字,持续更新,,,&br&——————知乎什么鬼,说是保存为草稿,切了个微信,回来没了,在草稿里面也没有,玩我呢?刚写的关键的几段没了!&br&&br&有时间再写吧。
这几天比较忙。加个插曲。 前两天面试了一个四年工作经验的Java工程师,挺失望的。工作换了四五家,大多浅尝则止,基础太差了。面试别人,一般基于其项目经历和简历的技能栈交流。没想到,这次交流成了授课了。“大处着眼,小处落手”,一个技术人员既要具…
&p&那就做一个模仿个天猫官网的J2EE项目,来练手吧&/p&&p&&br&&b&1. 项目演示地址&/b&&br&前台 &a href=&//link.zhihu.com/?target=http%3A//how2j.cn/tmall& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&how2j.cn/tmall&/span&&span class=&invisible&&&/span&&/a&&br&后台: &a href=&//link.zhihu.com/?target=http%3A//how2j.cn/tmall/admin& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&how2j.cn/tmall/admin&/span&&span class=&invisible&&&/span&&/a&&/p&&p&&b&2. 学习思路&/b&&br&其实呢,要在网上找一个J2EE项目是很容易的,随便在百度或者git搜索,都是一大把。 但是拿到这样的搜索来的J2EE项目,其中包含了上百个java文件,jsp文件,各种配置信息,如果没有好几个实践过的J2EE项目经验,会觉得无从看起,难以下手,最后影响学习的效果。&br&为了使学习的曲线变得更平滑,逐渐建立学习的信心,我为这个模仿个天猫官网项目制作了由浅入深的学习教程。&/p&&p&&u&2.1 首先下载一个跑起来&/u&&/p&&p&看了演示地址之后,第一步总是要下载下来,把项目配置起来,自己也跑跑看看效果的。 如果下载出来的项目不能运行,为什么要跟着你做呢?&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-fea8659661_b.jpg& data-rawwidth=&189& data-rawheight=&52& class=&content_image& width=&189&&&/figure&&br&&p&为了顺利的演示,不仅需要项目代码,还需要数据库中的数据, 所以提供了导入数据的SQL文件&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-1ed8ad7d372c36128e6c_b.jpg& data-rawwidth=&313& data-rawheight=&76& class=&content_image& width=&313&&&/figure&&p&而导入的数据量比较大,上万条数据,使用工具导入不仅慢,还有可能出错,所以专门准备了一个命令行的方式导入,以保证导入的顺利进行&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-00e249b696b4de0df988a_b.jpg& data-rawwidth=&842& data-rawheight=&63& class=&origin_image zh-lightbox-thumb& width=&842& data-original=&https://pic3.zhimg.com/50/v2-00e249b696b4de0df988a_r.jpg&&&/figure&&p&配置tomcat也是比较容易出错的环节,特意准备了一个完整的server.xml,直接复制粘贴,然后启动tomcat,就一定能够成功配置了。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-3f792aa489a08dfac492d_b.jpg& data-rawwidth=&314& data-rawheight=&110& class=&content_image& width=&314&&&/figure&&p&如此这般,便可以顺利的自己也搭建一个模仿天猫的J2EE项目,在自己的机器上看到效果。&/p&&p&&u&2.1 由浅入深,从零开始构建整个项目 &/u&&/p&&p&在确定了这个项目确实可用的前提下,就可以开展对这个项目的学习。但是这个项目里有许多的java,jsp.xml 等等各种类型的文件,彼此之间又有着各种关联关系,从哪里开始着手好呢? 其实,从哪里着手,都不好着手,毕竟项目有着相当的复杂度。 最好的方式,就是从零开始,由浅入深地构建出整个项目出来。&/p&&ul&&li&从需求分析开始,明确要做哪些功能。&/li&&li&然后分析表结构,确定什么样的表结构,表关系,可以支撑需求中的业务功能。&/li&&li&接着再做持久层的实体类和DAO设计&/li&&li&最后才开始进行前后台的功能开发&/li&&/ul&&figure&&img src=&https://pic3.zhimg.com/50/v2-cf8f7b0ce3a_b.jpg& data-rawwidth=&160& data-rawheight=&589& class=&content_image& width=&160&&&/figure&&br&&p&&u&2.2 表结构设计&/u&&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-ff779bbe1a4c68266f6aae5e0e75da36_b.jpg& data-rawwidth=&172& data-rawheight=&300& class=&content_image& width=&172&&&/figure&&br&&p&表结构设计是非常重要的,如果这一步没有做正确,将无法支持业务功能的需求,所以放在第一步来做。 &br&在这部分列出了表与表之间的关系,建表的SQL语句等等。 &br&值得一提的是,因为表比较多,为了便于理解每张表的作用,特意把表和前台页面截图做了对应,从感性上理解这些表都是干什么用的。 &/p&&p&比如这个产品表与产品页面的截图,这样表的每个字段在界面上分别对应什么样的显示数据,对于这个表有什么用,心里就会有底很多。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-c8d602aac04b9408942acfaac7e60e87_b.jpg& data-rawwidth=&720& data-rawheight=&693& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic3.zhimg.com/50/v2-c8d602aac04b9408942acfaac7e60e87_r.jpg&&&/figure&&br&&p&&u&2.3 每个类的源代码,细致到方法级的讲解&/u&&/p&&p&项目里有非常多的类,如实体类,DAO类,Servlet类,Filter,JSP等等,不仅每个类提供源代码,而且每个类的每个方法有什么作用,与业务有什么关系,都有细致到方法级别的讲解, 力求把代码吃透,消化明白。 &/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-bcde423d893fcd726f0ee9_b.jpg& data-rawwidth=&165& data-rawheight=&116& class=&content_image& width=&165&&&/figure&&p&&u&2.4 业务类与界面的对应关系&/u&&/p&&br&&p&稍复杂的方法,还有与项目截图的一一对应关系,辅助理解。&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-04fb58ff626d999a0facc6c_b.jpg& data-rawwidth=&447& data-rawheight=&150& class=&origin_image zh-lightbox-thumb& width=&447& data-original=&https://pic2.zhimg.com/50/v2-04fb58ff626d999a0facc6c_r.jpg&&&/figure&&br&&p&&u&2.5 后台第一个功能精讲&/u&&/p&&p&在功能开发环节,比如后台功能,通常来说,大部分后台功能是比较接近的,主要是业务数据的CRUD操作。 而做第一个的时候,不仅需要规范化,对于不熟悉的同学,也会略感吃力。 所以在讲解如何做后台第一个分类管理功能的时候,把其拆的特别细,碾碎到很小的颗粒,这样消化起来就容易多了。&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-c10bbc44f52a7148dcc97_b.jpg& data-rawwidth=&166& data-rawheight=&555& class=&content_image& width=&166&&&/figure&&br&&p&&u&2.6 其他后台功能&/u&&br&在完成了第一个后台功能,并消化理解之后,再做其他的后台功能就会顺畅很多&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-fa4b32c766c30a8d2a4516617ffb227c_b.jpg& data-rawwidth=&176& data-rawheight=&338& class=&content_image& width=&176&&&/figure&&br&&p&&u&2.7 前台第一个功能精讲&/u&&/p&&p&前台功能与后台功能的做法会有区别,所以与后台功能类似的,前台第一个功能也讲得很细致,便于理解与消化&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-ad5c5c955d6b41f08181d68_b.jpg& data-rawwidth=&168& data-rawheight=&334& class=&content_image& width=&168&&&/figure&&br&&p&&u&2.8 其他前台功能&/u&&/p&&p&在完成了第一个前台功能,并消化理解之后,再做其他的前台功能就会顺畅很多&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-ffee8888c75_b.jpg& data-rawwidth=&388& data-rawheight=&637& class=&content_image& width=&388&&&/figure&&p&2.9 视频讲解&/p&&p&光有文字讲解有时候也无法把一些较为复杂的概念、思路表达清楚。 所以在各个关键点,都有视频讲解,加深理解。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-cbddfc206f6_b.jpg& data-rawwidth=&632& data-rawheight=&322& class=&origin_image zh-lightbox-thumb& width=&632& data-original=&https://pic3.zhimg.com/50/v2-cbddfc206f6_r.jpg&&&/figure&&br&&br&&p&&b&3. 可运行项目&/b&&/p&&p&
每个知识点都有当前的可运行项目下载,以确保项目一定可以运行,保障持续学习的信心。&/p&&p&
学习一个较为复杂的项目,会有这样的体验:各个步骤差不多都跟着做了呀,但是为什么就是不能正确运行呢? 而且花很多时间,翻来覆去的改,越改越糟糕,越改越乱,犹如进入了茂密的丛林一般,几乎失去了方向。
如果进入这样的状态,真正可怕的是一点点丢失的学习的信心和动力,自然而然地开始怀疑项目本身是不是有问题喔,各种疑虑加上止步不前, 最后实在是学习不动了,只好放弃了。&/p&&p&
其实之所以跑不出来,大部分原因都是因为某个细节没有处理好。为了面对这种情况,我特意在每个学习步骤的右上角,准备当前学习进度对应的可以运行的项目。 如果自己老是搞不出来,那么就把右上角的项目下载下来,部署,运行,就跑通了。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-b381fe697bc644bd16097b_b.jpg& data-rawwidth=&538& data-rawheight=&173& class=&origin_image zh-lightbox-thumb& width=&538& data-original=&https://pic3.zhimg.com/50/v2-b381fe697bc644bd16097b_r.jpg&&&/figure&&br&&p&
这样做的作用是什么呢?&/p&&ul&&li&第1,确保了项目是可以运行的,教程没问题,打消了项目本身就有问题的疑虑&/li&&li&第2,此时就可以把自己写的代码与“标准答案” 代码进行比较,很快就能定位自己的问题所在了。 为此还特意在对应位置,为每个源代码提供了一个文件比较功能, 方便快速定位自己哪些 “细节” 不一样。&/li&&/ul&&figure&&img src=&https://pic3.zhimg.com/50/v2-4be2ff0b9da83ea3b5280d_b.jpg& data-rawwidth=&373& data-rawheight=&54& class=&content_image& width=&373&&&/figure&&br&&figure&&img src=&https://pic4.zhimg.com/50/v2-fc12ddda358ff59c85624_b.jpg& data-rawwidth=&1047& data-rawheight=&566& class=&origin_image zh-lightbox-thumb& width=&1047& data-original=&https://pic4.zhimg.com/50/v2-fc12ddda358ff59c85624_r.jpg&&&/figure&&br&&ul&&li&第3,定位到自己错误的地方,修改后,再回过头去部署自己的项目,并运行通过。 这样不仅技术上成长了,也能逐步增强了学习完整个项目的信心。&/li&&/ul&&br&&p&&b&4. 可以期待的收获&/b&&/p&&p&看上去这个项目也不短嘛,那么真正学完这个项目后,能够得到什么呢? &/p&&p&&u&4.1 典型业务场景的掌握&/u&&/p&&p&所谓的典型业务场景就是各种商业项目里,都会有类似或者接近的功能。 在这个项目里你掌握了这些业务场景的开发,去工作之后,做类似的就能驾轻就熟。 那么都有哪些业务场景呢?&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-afb0a638def90_b.jpg& data-rawwidth=&397& data-rawheight=&723& class=&content_image& width=&397&&&/figure&&br&&br&&p&&u&4.2 设计模式的掌握&/u&&/p&&p&设计模式的书和文章有很多,从我自己学习和工作的经验来看,如果一种设计模式,我只是在书上看过,却没有在实际工作中运用的话,那么犹如无根之树,打一把dota就忘记了,即无法深入理解其中的原理,也不能在真正工作的时候,灵活地运用到他们。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-87a4fdbfc6_b.jpg& data-rawwidth=&934& data-rawheight=&367& class=&origin_image zh-lightbox-thumb& width=&934& data-original=&https://pic3.zhimg.com/50/v2-87a4fdbfc6_r.jpg&&&/figure&&br&&p&而通过这个项目,基于实践所运用到的项目,就会变成你真正的技能,因为这些都会是你一行一行代码敲出来的设计模式,在面试的时候如果被问到相关问题,你也会对答如流,因为这些会是你真正“实践过”的设计模式&/p&&p&&b&5. 教程地址: &a href=&//link.zhihu.com/?target=http%3A//how2j.cn/k/tmall-j2ee/tmall-j2ee-894/894.html%3Ftid%3D2& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&how2j.cn/k/tmall-j2ee/t&/span&&span class=&invisible&&mall-j2ee-894/894.html?tid=2&/span&&span class=&ellipsis&&&/span&&/a&&/b&&/p&&p&教程由个人完成,局限于个人的经验和视野,有诸多不足之处,请各位多多指点,谢谢。&/p&&p&收藏的同学,请记得点个赞~&/p&
那就做一个模仿个天猫官网的J2EE项目,来练手吧 1. 项目演示地址 前台
后台: 2. 学习思路 其实呢,要在网上找一个J2EE项目是很容易的,随便在百度或者git搜索,都是一大把。 但是拿到这样的搜索来的J2EE…
&p&前提是搞好了基础,然后在学习框架,否则一脸懵逼,如果不是项目一定要用,Struts
就别学了,过时,现在基本用spring mvc ,这里有个列表给你&/p&&ul&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33438& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SpringMVC架构】SpringMVC介绍(一)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33437& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【持久化框架】Mybatis简介与原理&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33436& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【持久化框架】Mybatis与Hibernate的详细对比&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33435& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目+源码下载&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33434& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33433& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33432& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33431& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate映射——多对一单向关联映射(四)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33430& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33429& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate基本映射(三)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33428& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring的AOP逐层深入——采用注解完成AOP(七)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33427& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate搭建开发环境+简单实例(二)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33426& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring的AOP逐层深入——AOP的基本原理(六)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33425& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33424& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate基本原理(一)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33423& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】深入源码,详解Struts基本实现流程(七)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33422& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring的IOC逐层深入——依赖注入的两种实现类型(四)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33421& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring的IOC逐层深入——Spring的IOC原理[通俗解释一下](三)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33420& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&菜鸟程序员的成长之路(三)——2014,逝去的半年,奋斗的半年&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33418& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构MVC实现Struts框架——完善转向页面,大功告成(六)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33419& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring的IOC逐层深入——为什么要使用IOC[实例讲解](二)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33417& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Spring简介,搭建Spring环境——轻量级容器框架(一)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33416& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&记2014年暑假,一个项目,三个框架&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33415& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate系列——总结篇(九)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33414& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构MVC实现Struts框架——彻底去掉逻辑判断(五)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33413& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate映射——多对多关联映射(八)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33412& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构MVC实现Struts框架——封装业务逻辑和跳转路径(四)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33410& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33411& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Hibernate映射——一对多关联映射(七)&/a&&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//www.demoso.net/taview/33409& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【SSH进阶之路】Struts基}

我要回帖

更多关于 部落冲突破解版8.67.9 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信