张三和小四在一家厂里组织体检有问题会被开除吗人摆工如何让领导知道又不怀疑是我告密该用什么办法!

Markdown编辑器的语法
本Markdown编辑器使用修改而来,用它写博客,将会带来全新的体验哦:
Markdown和扩展Markdown简洁的语法
代码块高亮
图片链接和图片上传
LaTex数学公式
UML序列图和流程图
离线写博客
导入导出Markdown文件
丰富的快捷键
Markdown及扩展
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。
使用简单的符号标识不同的标题,将某些文字标记为粗体或者斜体,创建一个等,详细语法参考帮助?。
本编辑器支持 Markdown Extra ,  扩展了很多好用的功能。具体请参考.
Markdown Extra 表格语法:
可以使用冒号来定义对齐方式:
Markdown Extra 定义列表语法:
代码块语法遵循标准markdown代码,例如:
@requires_authorization
def somefunc(param1='', param2=0):
'''A docstring'''
if param1 & param2:
print 'Greater'
return (param2 - param1 + 1) or None
class SomeClass:
&&& message = '''interpreter
... prompt'''
生成一个脚注.
用 [TOC]来生成目录:
使用MathJax渲染LaTex 数学公式,详见.
行内公式,数学公式为:<span class="MathJax" id="MathJax-Element-1-Frame" tabindex="0" style="position:" data-mathml="&#x0393;(n)=(n&#x2212;1)!&#x2200;n&#x2208;N" role="presentation">Γ(n)=(n-1)!?n∈NΓ(n)=(n-1)!?n∈N。
块级公式:
<span class="MathJax" id="MathJax-Element-2-Frame" tabindex="0" style="text-align: position:" data-mathml="x=&#x2212;b&#x00B1;b2&#x2212;4ac2a" role="presentation">x=-b±b2-4ac-------√2ax=-b±b2-4ac2a
更多LaTex语法请参考 .
可以渲染序列图:
Created with Rapha?l 2.1.2张三张三李四李四嘿,小四儿, 写博客了没?李四愣了一下,说:忙得吐血,哪有时间写。
或者流程图:
Created with Rapha?l 2.1.2开始我的操作确认?结束yesno
关于 序列图 语法,参考 ,
关于 流程图 语法,参考 .
离线写博客
即使用户在没有网络的情况下,也可以通过本编辑器离线写博客(直接在曾经使用过的浏览器中输入即可。Markdown编辑器使用浏览器离线存储将内容保存在本地。
用户写博客的过程中,内容实时保存在浏览器缓存中,在用户关闭浏览器或者其它异常情况下,内容不会丢失。用户再次打开浏览器时,会显示上次用户正在编辑的没有发表的内容。
博客发表后,本地缓存将被删除。 
用户可以选择
把正在写的博客保存到服务器草稿箱,即使换浏览器或者清除缓存,内容也不会丢失。
注意:虽然浏览器存储大部分时候都比较可靠,但为了您的数据安全,在联网后,请务必及时发表或者保存到服务器草稿箱。
浏览器兼容
目前,本编辑器对Chrome浏览器支持最为完整。建议大家使用较新版本的Chrome。
IE9以下不支持
IE9,10,11存在以下问题
不支持离线功能
IE9不支持文件导入导出
IE10不支持拖拽文件导入
题记:今天刚好看到群里有人问,平时一向比较不是很喜欢这种脑残智力题的(喂),不过今天还是用程序写了个……没找到标准答案,所以有可能有错,随便了= =||已知:x和y都是自然数,且1我把x+y的结果告诉...
最近一直在搞这些东西
做了将近20道题目吧
也算是有感而发
写点东西记录一下自己的感受
如果您真的想学会莫比乌斯反演和杜教筛,请拿出纸笔,每个式子都自己好好的推一遍,理解清楚每一...
1-20的两个数把和告诉A,积告诉B,
A说不知道是多少,
B也说不知道,
这时A说我知道了,
B接着说我也知道了,
问这两个数是多少?
设和为S,积为M。
首先,A:我不知道...
  地点:北京
  咨询者:22岁,在某商务中心工作两年。很不满意目前的工作,但又不知道自己未来的道路在哪里。
  回答者:博主。
  咨询者:我现在真的特别...
在使用CSDN的博客写页面的时候,想转换成MarkDown的在线编辑器,在下面页面找了很久也没找到在哪里设置。后面发现在博客设置里面,将默认编辑器改成MarkDown编辑器就可以了。如果觉得对你有帮助...
如果喜欢不如给个star鼓励一下:ZYMarkdownEditor什么是正则表达式?
iOS开发如何使用正则表达式?
使用正则表达式匹配Markdown
性能劣势?
配合YYTextView实现语法高...
小学奥数思维训练题(八)
CSDN markdown编辑器使用的一些技巧吐槽一下CSDN markdown编辑器:
markdown编辑器的预览界面与显示效果的界面不完全一致。预览效果比发出来的效果要好一些。
用#开头的标题,...
之前一直不愿意使用MarkDown编辑器,主要是它的字体背景,颜色大小什么不太好设置,不愿意去使用,但是上篇文章不用MarkDown一直发不出去,无奈只好选择MarkDown,确实很麻烦,
The more you know, the more you know you don't know.
你知道的越多,你会发现你不知道的也就越多。
原文载于:爱词霸英语学习网-每日一句
没有更多推荐了,《我的美女总裁》小说简介:
&&萧云飞不认为自己是什么好人,但也不是什么坏人。喝个酒还不小心被美女给勾搭上,更不小心的是还被她给祸害了,可是没想到,她竟然是自己未来的顶头上司。。。。更没想到的是对方竟然来逼婚!开什么玩笑?婚姻是爱情的坟墓,他可不想这么早就入土为安。还有大把的人生等着他去享受,大把的美女等着他的滋润。。。。。“娶我!这钱就是你的了!”就在他宁死不从之际,...
《我的美女总裁》是作者五十二策精心创作的玄幻小说大作,恋上你看书网实时同步更新我的美女总裁最新章节纯文字无弹窗广告版,书友所发表的我的美女总裁评论,并不代表恋上你看书网赞同或者支持我的美女总裁读者的观点。
五十二策的其他作品:、、、、、
关键词:、、、
您要是觉得《我的美女总裁》还不错的话请点击顶部分享按钮分享到你的朋友圈!
推荐阅读:、、、、、、、
我的美女总裁最新章节列表
《我的美女总裁》正文weixin_的博客
https://blog.csdn.net/
https://static-blog.csdn.net/images/logo.gif
https://blog.csdn.net/weixin_
https://blog.csdn.net/
request对象常用的方法:
getMethod():返回HTTP请求信息中所使用到的方法名称(GET、POST等);
getServletPath():返回请求信息中调用Servlet的URL部分;
getQueryString():返回HTTP GET请求信息中URL之后的查询字符串;
getContentType():返回请求实体的MIME类型;
getProtocol():返回请求信息中的协议名名字与版本号;
getPathInfo():返回有关任何路径信息;
getServletName():返回接受请求的服务器主机;
getServletPort():返回服务器的端口号;
getRemoteHost():返回提交请求的客户机的规范名字;
getRemoteAddr():返回提交请求的客户机的IP地址;
getScheme():返回请求使用的模式(协议)名字;
getParameter():返回客户端通过表单提交过来的参数值。例如request.getParameter(“myname”),通过该语句来获取客户端传递过来的myname
getContextPath():返回HTTP 请求中指示请求上下文的部分。
getHeaderNames():返回一个枚举类型,此枚举集合中包含了请求所含有的所有请求名。
getAuthType():返回用于保护Servlet 的认证模式的名字。例如,BASIC,SSL 或者NULL(没有保护)。
gtRequestURL():返回HTTP 请求信息中的第一行从协议名开始直至查询字符串之间的URL 部分。例如,对HTTP GET
请求,这个方法将返回
gtCountLength():返回整数,表示请求实体的长度(以字节为单位)。
gtUestPrincipal():返回java.security 类的Principal 对象,其中包含有目前授权用户的名字。
iUserInRole(String role):返回一个布尔值,指示某个授权用户是否包含在某个具体的逻辑角色role 中。
gtRemoteHost():如果用户已经被授权,则返回提交请求的用户的注册名字,否则返回一个NULL。
response:服务器响应。response就是HTTP请求的响应信息,会放入缓冲区,只有在当前的jsp页面有效,作用范围就是page
response对象常用的方法:
setContentLength(int len):此方法用于设置响应头的长度。
setContentType(String type):用于设置HTTP响应的contentType中的MIME类型,其中可以包含字符编码的规则。例如可以把contentType设置为“text/charset=UTF-8”。在Servelet编写过程中,需要调用此方法进行设置,但是在JSP中一般都是使用page指令直接指定contentType的属性。
getOutputStream():此方法返回一个Servlet的输出流。用于在响应中写入二进制数据。Servlet容器不对二进制数据进行编码。
getWriter():此方法返回一个PrintWriter对象,在Servlet编写过程使用的比较频繁,而在JSP文件中,由于out是用getWriter()创建的PrintWriter对象的隐含对象,所以可以直接调用out对象作输出响应。
getCharacterEncoding():该方法获得此时响应所采用的字符编码类型。
sendError(int status):使用指定错误状态码向客户机发送相应的错误信息。
sendError(int status, String message):使用自定义的错误状态码以及描述信息向客户机发送错误的提示信息。
sendRedirect(String location):将请求重新定位到一个不同的URL(页面)上。此方法在实际开发过程中会经常使用到。
setDateHeader(String headername, long date):把指定的头名称以及日期设置为响应头信息。其中日期是用long值表示的,这是按照从新纪元开始算起的毫秒数。
ContainsHeader(String name):检测指定的头信息是否存在。返回一个布尔类型。
setHeader(String headername, String value):此方法使用指定的头名字以及相应的值来设置头信息。如果此头信息已经设置,则新的值会覆盖掉旧的值。如果头信息已经被发送出去,则此方法的设置将被忽略。
addheader(String headername, String value):把指定的头名字以及相应值添加到头信息当中去。
addIntHeader(String headername, int value):把指定的头名字以及整数值设置为头信息。如果头信息已经设置了,则新的设置值将覆盖掉以前的值。
setStatus(int sc):给响应设置状态的代码。
setStatus(int sc, String sm):为响应设置状态代码以及信息。这是在没有错误的时候使用的。
page:当前页面。page对象代表的就是jsp页面本身,有点类似于this,只有在jsp页面才有用。它是java.lang.Object类的对象。作用范围是page
page对象常用的方法:
getClass():返回当前Object的类。
hashCode():返回此Object的哈希代码。
toString():把此时的Object类转换成字符串。
equals(Object o):比较此对象是否和指定的对象是否相等。
copy(Object o):把此对象复制到指定的对象当中去。
clone():对此对象进行克隆。
pageContext:比较特殊,pageContext的作用域是本身的page页面,也就是page,但是它可以访问到所有的其它内置对象,比如getSession(),getRequest()等。
pageContext对象常用的方法:
getRequest():返回当前页面中的request对象。
getResponse():使用此方法将返回当前页面中的response对象。
getPage():此方法返回当前页面中的page对象。
getSession():返回当前页面中的session对象。
getOut():返回当前页面中的out对象。
getException():返回当前页面中的exception对象。
getServletConfig():返回当前页的config对象。
getServletContext():返回当前页中的application对象。
setAttribute(String name):给指定的属性名设置属性值。
getAttribute(String name):根据属性名称找到相应的属性值。
setAttribute(String name, Object obj, int scope):在给定的范围内设置相应的属性值。
getAttribute(String name, int scope):在指定的范围内获取到相应的属性值。
findAttribute(String name):寻找一个属性并返回,如果没有找到则返回一个null。
removeAttribute(String name):通过属性名删除掉某个属性。
removeAttribute(String name, int scope):在指定的某个范围内删除某个属性。
getAttributeScope(String scope):返回某属性的作用域。
getAttributeNamesInScope(int scope):返回指定范围内的所有属性名的枚举。
release():释放掉pageContext()所占的所有资源。
forward(String relativeURLpath):使用当前页面重导到另一个页面。
include(String relativeURLpath):使用当前位置包含的另一个页面。
Out:输出流。向客户端浏览器输出信息,也就是在页面输出信息,也可以管理页面的输出缓冲区。比较简单但是使用频繁。作用范围是page
config:上下文配置信息。config是配置对象是ServletConfig类的实例,一般是用来获取Servlet的相关配置信息,比如上下文,服务器初始参数等等
Out对象常用的方法:
print():在页面中打印出字符串信息,不换行;
println():在页面中打印出字符串信息,并且换行;
clear():清除掉缓冲区中尚存在的内容。
clearBuffer():此方法清除掉当前缓冲区中尚存在的内容。
flush():清除掉数据流。
getBufferSize():返回缓冲区的内存大小,单位为字节流。如果不进行缓冲区的设置,大小为0。
getRemaining():此方法返回缓冲区还剩下多少字节数可以使用。
isAutoFlush():检查当前缓冲区是设置为自动清空,还是满了就抛出异常。
close():关闭输出流。
config对象常用的方法:
getServletContext():此方法将返回一个含有服务器相关信息的ServletContext对象。
getInitParameter(String name):返回初始化参数的值。
getInitParameterNames():返回包含了Servlet初始化所需要的所有参数,返回类型是枚举型。
execption:异常信息,例外对象。就是针对异常做出响应处理的对象,如果在jsp页面中出现异常就会生成execption对象,然后根据指令跳转到错误页面,则需要在错误页面配置&%@
page isErrorPage=”true”%&,然后在错误页面使用execption
execption对象常用的方法:
getMessage()和getLocalizedMessage():这两种方法分别返回exception对象的异常消息字符串和本地化语言的异常错误。
printStackTrace():显示异常的栈跟踪轨迹。
toString():返回关于异常错误的简单消息描述。
fillInStackTrace():重写异常错误的栈执行轨迹。
3.常见问题
JSP隐式对象和EL表达式隐式对象的区别
2.EL不能访问局部变量,只能访问作用域中的属性,比如${applicationScope.total}访问的就是applicatopn对象中的属性
3.EL输出null的时候用空串("")代替 像:(empty)的empty运算符将""视为null $( empty null ) && $( empty "" ) 为true
4.EL表达式在计算时会将字符串转换成数字(null == 0)
5.jsp和EL表达式有一个共同的对象:pageContext 就是说&%pageContext%&和${gageContext}实际上是一个对象,余下的EL隐式对象都是Java映射(map),他们只是提供了更容易的途径来访问pageContext隐式对象的某些性质。
session的生命周期
在客户端是没办法销毁session的,要销毁session必须等到它的生命周期结束或者服务器销毁。也就是下面的两个方式:
一个是Session.invalidate()方法,不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;
一个是当前用户和服务器的交互时间超过默认或者设置的时间后,Session会失效。
我们知道Session是存在于服务器端的,当把浏览器关闭的时候浏览器并没有向服务器发送任何请求来关闭Session,自然Session也不会被销毁,Session一直都在服务器端,而当我们关闭浏览器时,此时的Cookie是存在于浏览器的进程中的,浏览器关闭后Cookie也就不存在了。session的Cookie是存在于浏览器的进程中,这种Cookie我们称为会话Cookie,当我们重新打开浏览器窗口时,之前的Cookie中存放的Sessionid已经不存在了,此时服务器从HttpServletRequest对象中没有检查到sessionid,服务器会再发送一个新的存有Sessionid的Cookie到客户端的浏览器中,此时对应的是一个新的会话,而服务器上原先的session等到它的默认时间到之后,便会自动销毁。
4.编码实战
5.扩展思考
EL表达式的内置对象
(1)pageScope:获取jsp中pageContext域属性,相当于pageContext.getAttribute("xxx")
(2)requestScope:获取request域属性,相当于request.getAttribute("xxx")
(3)sessionScope:获取session域属性,相当于session.getAttribute("xxx")
(4)applicationScope:获取application域属性,相当于application.getAttribute("xxx")
(5)param:对应参数,它是一个Map,其中key是参数,value是参数值,适用于单值的参数,相当于request.getParameter("xxx")
(6)paramValues:对应参数,它是一个Map,其中key是参数,value是多个参数值,适用于多值的参数,相当于request.getParameterValues("xxx")
(7)header:对应请求头,它是一个Map,其中key表示头名称,value是单个头值,适用于单值的请求头,相当于request.getHeader("xxx")
(8)headerValues:对应请求头,它是一个Map,其中key表示头名称,value是多个头值,适用于多值的请求头,相当于request.getHeaders("xxx")
(9)initParam:获取web.xml中&context-param&内的参数,${ initParam.xxx},xxx就是&param-name&标签内的值,进而得到&param-value&中的值
(10)cookie:用于获取cookie,Map&String,Cookie&,其中key是cookie的name,value是cookie对象,例如${cookie.JSESSIONID.value }就是获取sessionId
(11)pageContext:可以获取JSP九大内置对象,相当于使用该对象调用getxxx()方法,例如pageContext.getRequest()可以写为${pageContext.request)
6.参考文献
7.更多讨论
分享到此结束
欢迎大家讨论
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
拦截器可以分别通过继承下面的接口实现拦截的功能,下面这两个比MethodInterceptor先执行。实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法:
public class LoginInterceptor extends HandlerInterceptorAdapter { ... }
public class LoginInterceptor extends HandlerInterceptor { ... }
AbstractInterceptor(status2)的,不提。
常用于AOP的拦截器:
public class RestController implements
MethodInterceptor{ ... }
拦截器的三个方法,举例HandlerInterceptor:
public class OtherInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false;
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
这里使用的HandlerInterceptorAdapter接口,实现的是拦截跳转到职业页面,通过session判断是否有值,没有的话就跳到login登录页面,有session就可以直接访问。
@Controller
public class LoginInterceptor extends HandlerInterceptorAdapter {
private final Logger logger = Logger.getLogger(LoginInterceptor.class);
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/charset=UTF-8");
String url = request.getRequestURI();
logger.info("\n 拦截url:" + url + "\n");
if(url.contains("profession")){
logger.info("拦截了profession");
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
logger.info("\nsession.name:" + username + "\n");
if(username!=null){
return true;
request.getRequestDispatcher("/WEB-INF/jsp/body/login.jsp").forward(request,response);
return false;
return true;
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
return true是放行,return false是拦截。
然后在SpringMVC.xml里配置对应的拦截器:
path="/u/**"/&
"com.tiles.controller.LoginInterceptor"/&
这里通过urlpath判断是否拦截,配置的是拦截所有/u/**访问,可以看到所有的/u/都被拦截了:
没有session的情况下访问profession页面直接跳转到登录页面
登录后访问:
访问的时候就是通过session匹配来判断的。登录后储存了session,然后通过匹配到session拦截器就可以放行直接访问页面了。
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
session是什么:
session是一次浏览器和服务器的会话对象,session也是缓存,是内容,是块数据。
因为我们访问网页使用的HTTP协议是无状态的,没有任何关系,快速的。所以我们如果想要关联客户的信息就需要一种办法能够把客户的信息联系在一起,这个方法就是cookie。但是cookie是把信息储存在用户本地,它在一个域名下是全局的。不安全又很容易的被修改。所以session就出现了,它储存在服务器上,通过它关联同一个用户的信息,这样用户在访问不同的页面的时候我们就知道对方是同一个人,而不需要每次无状态的访问都需要用户登录/关联了。
默认情况下一个浏览器独占一个session对象,然后服务器通过sessionID匹配用户。
Session和Cookie的主要区别
Cookie是把用户的数据写给用户的浏览器。
Session技术把用户的数据写到用户独占的session中。
Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
session的会话过程:
HTTP请求一个页面后(第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器),如果用到开启session,会去读cookie中的PHPSESSID是否有,如果没有,则会新生成一个session_id,先存入cookie中的PHPSESSID中,再生成一个sess_前缀文件。当有写入$_SESSION的时候,就会往sess_文件里序列化写入数据。当读取的session变量的时候,先会读取cookie中的PHPSESSID,获得session_id,然后再去找这个sess_sessionid文件,来获取对应的数据。由于默认的PHPSESSID是临时的会话,在浏览器关闭后,会消失,所以,我们重新访问的时候,会新生成session_id和sess_这个文件。
session的获取:
session其实就是一个Map,键=值对,通过session.getAttribute(“name”);获得session中设置的参数
HttpSession session = request.getSession();
session.setAttribute("username",user.getName())
session.removeAttribute("username");
session.invalidate();
匹配是否新的:
session.isNew()
session.getId()
判断是不是空的:
一个是判断属性值
if(session.getAttribute('username')==null)
还有一个是传boolean值,如果session不存在就说明它过期了。
这里下面的boolean两种情况,
直接使用true:
如果当前request的session不可用(不存在),那么就创建新的session,如果存在就返回当前会话
使用false:
当前request的session不存在就返回null,也就是说if条件里的request.getSession(false)为null的时候session不存在。
request.getSeesion(boolean){...}
if(request.getSession(false)==null) {
logger.info("Session已经失效!");
logger.info("Session未失效!");
HttpSession的源码,可以清楚的看到session的方法、参数、返回值:
public interface HttpSession {
public long getCreationTime();
public String getId();
public long getLastAccessedTime();
public ServletContext getServletContext();
public void setMaxInactiveInterval(int interval);
public int getMaxInactiveInterval();
public HttpSessionContext getSessionContext();
public Object getAttribute(String name);
public Object getValue(String name);
public Enumeration&String& getAttributeNames();
public String[] getValueNames();
public void setAttribute(String name, Object value);
public void putValue(String name, Object value);
public void removeAttribute(String name);
public void removeValue(String name);
public void invalidate();
public boolean isNew();
Session对象的创建和销毁:
第一次调用request.getSession()方法的时候会创建一个新的Session。
HttpSession session = request.getSession();
session销毁是从session停止活动的时候开始计时的,如果一直处在活动中session就不会过期,默认情况下Session对象30分钟没有被访问/匹配服务器就会自动销毁session。销毁方式有下面几种
一是自动销毁,到期就自动销毁了:
可以在web.xml中配置session的失效时间:
或者手动设置失效时间:
session.setMaxInactiveInterval(30 * 60);
二是手动销毁:
session.removeAttribute("username");
session.invalidate();
使用监听器:HttpSessionListener 来决定session创建/过期后的方法
public class OnlineUserListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event){
HttpSession session=event.getS
String id=session.getId()+session.getCreationTime();
SummerConstant.UserMap.put(id,Boolean.TRUE);
public void sessionDestroyed(HttpSessionEvent event){
HttpSession session=event.getS
String id=session.getId()+session.getCreationTime();
synchronized(this){
SummerConstant.USERNum--;
SummerConstant.UserMap.remove(id);
然后在web.xml中配置监听器:
&com.tiles.UserListener&
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
简单(静态)工厂模式
一、背景介绍
工厂模式是设计模式的一种,设计模式是自程序开发逐渐就有的,提高开发效率的一种设计思路,先前的开发者们一直在用,只是后来这四个人出了一本书总结了下,就是现在的23种设计模式:
1994年由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版的 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素)书中首次提到的,所以叫GOF
书中共有三个层面的内容:
一、算是一个总结性的,把程序开发过程中在不同系统中多次使用过的成功设计的模式进行总结,用名称-问题-解决方案-实用效果这几个要素来描述;
二、提出了面向对象开发中“针对接口编程而不是针对实现编程”,“优先使用组合而不是继承”的总体设计思路;
三、就是基于上面的设计思路所形成的常用的设计模式,也就是现在流传最广的23种常见的设计模式;
设计模式是为了更好的实现开发,使代码更易懂,易维护。它也是为了解决大多数开发者们的问题而出现的,当然它也不是万能的。除了设计模式我们在开发过程中还需要遵循基本的设计原则,这里后面再说。
许多人通晓并且使用的经过分类的代码设计经验的总结。
设计模式是开发者们在开发过程中面临一般问题的解决方案,这些解决方案是经过相当长的一段时间的试验和错误总结出来的。设计模式几乎在所有的编程里都适用。
为了提高代码可重用性、可扩展性、健壮性、更容易被理解。
*当前说的设计模式是针对面向对象,而不是面向过程
二、知识剖析
工厂是为了实现对构造过程(创建过程)的封装。也是设计原则的体现。工厂模式是一种创建型的设计模式,主要思想就是替代new为我们创建对象,工厂可以选择创建对象的方法,对这个构造过程(创建方法)进行选择的逻辑就是工厂模式的逻辑。 这样也是为了给以后的系统带来更大的可扩展性,实现低耦合。
工厂模式大概有三种
简单工厂模式
工厂方法模式
抽象工厂模式
简单(静态)工厂模式
简单工厂模式是最初自然而然就有的设计思想,它只是把创建过程比较自然的封装了一下,又称为静态工厂模式,是直接根据条件决定创建的产品。
简单工厂模式由三部分组成:
工厂角色(工厂/工厂抽象类):它创建具体产品,实现了对创建过程(构造过程)的封装。也是设计原则的体现。工厂类里面是创建对象的逻辑,也就是对这个构造过程进行封装
抽象产品角色(产品抽象/接口类):工厂类所创建的产品的父类,或者说它们的共同接口
具体产品角色(产品实体类):工厂类所创建的任何对象都是这个角色的实例
工厂模式和抽象工厂则是多了一个共同的工厂接口,所有实例工厂都是这个接口工厂的实现类
三、常见问题
设计模式只是思路,并不能解决所有问题
不要强制使用,它是用来解决问题,而不是寻找问题
一定要在对的地方使用,不然只会适得其反
设计模式三大类:
1.创建型模式 : 专注于如何初始化对象,就是在创建对象的同时隐藏创建逻辑,避免去使用new直接实例化对象
模式有工厂、单例、建造者、原型模式等等
2.结构型模式 : 结构型模式是针对类和对象的组合,思想是如何组合类和对象以获得更大/更好的结构
模式有桥接、适配器、装饰、委托、享元、组合模式等等
3.行为型模式 :关心的是对象之间的责任分配,它不仅仅指定结构,而且还概述了它们之间的消息传递的模式
模式有命令、观察者、访问者、迭代器、中介者、策略模式等等
设计原则(不分先后)
一是开闭原则:
对扩展是开放的,对修改是关闭的。也就是只能添加,不能修改。比如:游戏/软件更新,只通过扩展修改,而不是更改原有的代码。
二是LoD(迪米特)法则:
一个对象尽可能对其它对象少了解,只关心自己。即尽可能少的与其它对象发生联系,尽量少依赖。或者说”只与直接的朋友通讯“。
三是依赖倒置(DIP)原则:
高层不应依赖低层模块,两者都应该依赖它们的抽象;抽象也不应该依赖细节,而是细节依赖抽象。
比如A依赖B,如果需求改了,需要修改A的依赖为C的话就必须修改A的代码。大多数情况下A属于高层模块,B和C属于低层模块。依赖倒置原则就是把A依赖的B和C都实现接口F,而让A通过接口F间接的依赖B或者C,这样就会降低修改A的情况
四是单一职责:
非常简单的概述:一个类只有一个职责,它只负责份内的事。在任何时候都应该遵循它,这是所有设计原则的基础。这个也算是所有原则的基本原则。
五是里氏替换原则:
通俗的来说就是子类可以扩展父类,但不能改变父类原有的方法。(因为修改很可能会造成整个继承体系的破坏,这也是继承的风险)
六是接口隔离原则:
客户端不应该依赖它不需要的接口,一个类的依赖应该建立在最小接口上
比如有一个接口I,它的实现类有两个:C和D,这时候A通过I去依赖C,B通过I依赖D.如果I对于A和B来说不是最小的接口(接口中还有其它方法),那么C和D这两个实现类就必须实现它们不需要实现的方法。比如A和B需要的都要在C里面有,这样C就会做额外的动作。这种情况就需要把I拆分为独立的几个更小的接口,然后把AC和BD都分离开来,让他们和自己需要的接口建立依赖。
七是合成复用原则(Composite Reuse Principle):
尽量首先使用组合的方式,而不是使用继承。在面向对象设计中,如果直接继承基类,会破坏封装,因为继承将基类的实现细节暴露给子类;如果基类的实现发生改变,则子类的实现也不得不发生改变;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性。于是就提出了合成/聚合复用原则,也就是在实际开发设计中,尽量使用合成/聚合,不要使用类继承。
四、编码实战
如果要通过xml配置实现工厂就需要在maven里导入commons-io的jar包,用来读取自定义xml:
maven导入:
&commons-io&
&commons-io&
public class FruitFactory {
private static Logger logger = Logger.getLogger(FruitFactory.class);
public static Fruit createFruit(String name){
if (name.equalsIgnoreCase("Apple")){
Fruit fruit = new Apple();
}else if (name.equalsIgnoreCase("banana")){
Fruit fruit = new Banana();
}else if (name.equalsIgnoreCase("orange")){
Fruit fruit = new Orange();
logger.debug("没有这种水果");
return null;
public static Fruit createFruitS(String name){
switch (name){
case "apple":
Fruit apple = new Apple();
case "banana":
Fruit banana = new Banana();
case "orange":
Fruit orange = new Orange();
logger.debug("没有找到这种水果");
return null;
public static Fruit createFruitForXML(){
String name = "";
XMLConfiguration xmlConfiguration = new XMLConfiguration("fruit.xml");
name = xmlConfiguration.getString("fruit.name");
} catch (ConfigurationException e) {
logger.debug("xml文件读取错误",e);
e.printStackTrace();
switch (name){
case "apple":
fruit = new Apple();
case "banana":
fruit = new Banana();
case "orange":
fruit = new Orange();
logger.debug("没有找到!");
fruit = null;
public static &T& T createFruitT(Class&T& cls){
T t = null;
t = (T) Class.forName(cls.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
logger.debug("Exception {}",e);
e.printStackTrace();
产品接口:
public interface Fruit {
void eat();
产品实例:
public class Apple implements Fruit {
public void eat() {
System.out.print("我是苹果,砸了牛顿,被乔布斯啃了一口的苹果\n");
public class Banana implements Fruit {
public void eat() {
System.out.print("吃香蕉,我是大香蕉,又软又甜的大香蕉\n");
public class Orange implements Fruit {
public void eat() {
System.out.print("我是橙子,细嫩多汁酸甜可口的橙子\n");
使用工厂去创建实例:
public class FactoryAction {
public static void main(String[] args){
Apple apple = new Apple();
apple.eat();
Fruit fruit = FruitFactory.createFruitForXML();
fruit.eat();
Fruit fruit1 = FruitFactory.createFruit("banana");
fruit1.eat();
Fruit fruit2 = FruitFactory.createFruitS("apple");
fruit2.eat();
Fruit fruit3 = FruitFactory.createFruitT(Orange.class);
fruit3.eat();
关于xml配置:
fruit.xml配置文件,通过name获取参数生产相应的产品:
简单(静态)工厂模式就是这样,直接创建个工厂再去通过工厂创建,是不是感觉比起new很麻烦,我需要的东西直接去new就行了,干嘛还要去创建一个工厂,再通过工厂去创建?再说工厂不也一样需要new吗。
这就是工厂模式的设计思想体现的地方,也是创建型设计模式的一个思想。它是为了实现对构造过程的封装。也是设计原则的体现。工厂可以选择创建对象的逻辑,对这个构造过程进行选择的逻辑就是工厂。
而且现在只是一个new,如果你有现在有json对象,有String对象,有数据对象,依赖对象,每个都要new吗?如果你都使new用了那以后维护的时候需要修改怎么办?在每个new依赖对象的地方修改吗?
还有之前我们也说了,开闭原则,不要修改原来的代码,而是添加新的。
多加一层工厂去封装的意义就在于:
第一,用户并不关心这个东西是如何创造出来的,只要能用就行了。就像前面的new
第二,工厂方法是可以扩展的,不需要用户再修改自己的代码,方便以后的添加
但是它的缺点就是如果需要新的产品就需要新建一个产品类,然后还要修改工厂类,在里面添加生产方法。但是这样就要修改已经写好的类,这也违反了开闭原则。怎么办呢,有几个办法:
一是使用反射,直接使用类,这样就不需要再修改工厂类,直接创建产品就能使用。
一个就是使用配置文件,通过配置文件添加,这跟springIOC读取xml来创建bean的方法非常相似。
如果这两个都不想用,都有缺点(配置文件需要加载配置文件,反射又有性能损耗,比直接new要多封装很多次层),怎么办,于是就有了工厂方法模式。
工厂方法模式不是这次讲的范围,这里就说一下,工厂方法模式就是对简单工厂也进行抽象,用父类工厂创建子类工厂,然后使用者再通过子类工厂获取到需要的对象,这样就不需要修改原有的代(工厂类)码,需要的时候创建产品model,再创建新的工厂类,直接继承工厂接口就可以了。
这里说的model产品什么的并不是单纯的pojo类,而是所有需要的依赖。就像面向对象,我们上班,出门需要穿衣(不出门也要穿)服穿衣服就需要有衣(这个衣服就是我们需要的依赖)服,这个衣服原先都是我们自己做,比如织毛衣,纺织布。现在交给了工厂,我们就不用去关心这个衣服用什么料子,什么样的样式
工厂就是封装了这个制作的过程拿给我们现成的依赖。
而工厂方法是遵循单一职责原则的,就是子类工厂只负责单一产品的生产。使用者需要什么产品就用什么工厂去创建。
工厂模式看似简单,简单工厂更是只是比较自然的封装了一下,甚至算不上设计模式,严格来说抽象工厂模式才算是设计模式,但是有可能我们一辈子都用不到。简单工厂模式虽然简单,但是它是用处最多用的最广的。就拿智能机器人来说,大街上看到的点菜机器人、智能扫地机,学习机器人,它算是严格意义上来说的智能机器人吗,明显不是啊,真正的智能机器人都在小罗伯特那里啊,还有阿尔法狗啊,但是你用的到吗,大家都在用的就是最方便而又容易使用的,只要对我有用就好啦
五、扩展思考
简单工厂模式的优点和缺点
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了和客户代码修改的可能性,更加容易扩展。
工厂类的职责比较大,如果修改需求或者需要添加新产品的话除了需要创建产品类,还要修改工厂类,而且如果工厂类出现问题的话所有的客户端(使用方)都会出现问题。 但是工厂模式完美的解决了这个问题,完全遵循了开闭原则,只需要添加新的工厂类实现抽象接口就可以了。
简单提一下面向过程
面向过程就是一种实际的思考方式,它关心的是某个事件,某个过程:比如起床-穿衣洗漱—吃饭-上班-工作-吃饭-下班-吃饭-睡觉这个过程。面向过程就是一步一步实现这些步骤,依照顺序,先有起床-然后穿衣-洗漱再接着继续实现后面的步骤。这就是大概的面向过程的开发思想
如果用面向对象可能就是抽象出一个上班族的类,然后实现这几个方法,它也一样可以实现这几个步骤,但是它的灵活性更强大,可以直接实现它的方法而不需要在意前后做了什么
六、参考文献
度娘/谷歌/知乎:
工厂模式/工厂设计模式有什么用?
七、更多讨论
A(王耀琪):与spring Ioc思想的区别
Q:springIOC也使用了工厂模式的思想,至少可以看到使用SpringIOC完全可以避免使用new创建对象。
A(韩亚博):在任务中 你是否使用了这种思想:
Q:在springIOC中有类似通过xml配置文件的方式(也就是bean注入)获取实例,跟工厂方式非常相似。
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
分享人:张强
1.背景介绍
什么是spring:
2002年,Rod Johnson在《Expert One-on-One J2EE Design and Development》书中首次推出了Spring框架雏形interface21框架。到现在将近20年了。最早Spring是为了解决企业级应用开发的复杂性而创建的。但是归根究底它的主要使命就是一点:简化java开发
Spring的开发策略:
基于POJO类的轻量级和最小侵入性编程;
通过依赖注入和面向接口实现松耦合;
基于切面和惯例进行声明式编程;
通过切面和模板减少样板式代码;
目的:解决应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了非常多的功能模块支持
范围:任何Java应用
java程序是通过很多类相互协作、相互调用来实现的,也就是说它们相互依赖。只要有了依赖就有了耦合,spring就是为了解决这些耦合,它致力于建造更容易维护、清晰度更高、更容易开发的代码。
Spring的优点:
低侵入式设计;
独立性强,能独立于各种应用服务器
兼容性强,能融合各种框架模块,比如hibernate/mybatis/redis/actuvemq/sgiro/quartz/kafka……
分层结构,模块化,可扩展性更好
开发效率高,易维护,易测试
Spring主要的核心:
SpringIOC 控制反转 容器管理
SpringAOP 切面编程
Spring ORM 对象关系映射
DAO 数据访问对象 (Transaction JDBC等等)
Spring Web MVC (web应用)
Spring Context (提供运行环境)
2.知识剖析
什么是SpringIOC?
SpringIOC是Spring框架的一个核心概念。
java程序中的类互相依赖,大量耦合。而SpringIOC(Inversion of Control)就是去创建管理这些依赖,从而尽可能的降低耦合,这些被它创建管理的类被称为bean。它是一个思想,从字面上看它是控制反转,但是直接说反转可能难以理解,我们可以从另一个角度去理解它,比如先理解正再理解反会更容易一些。什么是正,我们平常去new对象就是正面使用,我们使用Spring依赖注入(DI)去获取对象也是正面使用,new的时候是自己去创建依赖然后使用,但是这样我们的代码内部就有了它的实例,这就有了耦合。而spring容器是读取了配置元数据之后,通过java反射创建类并注入其依赖类。
为什么不使用new来创建实例?(参见演示)
1.增加耦合,会访问到内部属性
2.更新的地方比较多,难于维护
3.常见问题
SpringBean和javaBean
传统的javaBean基本上跟POJO类差不多,就是为了传值而存在,没有任何容器去管理它的生命周期,完全是靠回收机制回收。Spring沿用了Bean这个名称,但是Spring里只要是SpringIOC创建管理的任何类都可以称为Bean,而且它生成的bean完全由自己管理,生命周期可以自己控制;
Ref和Value
ref: 由IOC管理的其它bean
value:基本类型赋值
注解和扫描方式
context:component-scan
base-package=”com.xks.service”
& 不需要写bean,直接扫描
context:annotation-config
开启注解,需要写bean
4.编码实战
5.扩展思考
beanan生命周期
scope控制bean的生命周期,scope的取值有5种取值:
在Spring 2.0之前,有singleton和prototype两种;
在Spring 2.0之后增加另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用。
singleton 默认 单一实例 所有引用这个bean使用的都是一个,由spring控制。只要不销毁或者推出它就一直存在。
prototype 标准 每次引用spring都返回一个新的,这个对象完全属于引用者。一般用来定义不能共享使用的对象类型。
Spring的缺点
1)性能损耗,跟jsp+servlet+javabean性能差距很大
2)内存消耗大,缓存多
3)异常(bug)定位不是特别准确
4)越来越大,不容易理解知识体系(比如spring自己的测试体系,版本变更不清楚,配置和注解背后的原理、和j2EE自己的注解分不清,还有事务管理优越在哪里等等)
有没有更好的方式代替spring
因为spring已经被大家研究的比较透彻了,所以一般来说spring是最佳的选择,如果非要替代的话可以直接使用servlet + javaBean 或者 EJB
6.参考文献
Spring实战 第二版
7.更多讨论
Q:(郭超)Spring容器中的bean是容器启动就存在了吗?其中的bean默认是单例模式还是多例模式?
A:(张强)启动的时候会自动创建bean,其中的bean默认是单例模式,如果使用多例的话需要设置scope为prototype。
Q:(郭超)需要的时候才创建的话懒加载又是什么?
A:(张强)知道这个概念,但是没有尝试过……
设置default-lazy-init=”true”启动懒加载。
Q:(杨聪聪)有试过基于xml的自动装配吗?
A:(张强)没有……(原来基于xml的自动装配就是autowore)
xml的自动装配就是通过autowire配置(原来是直接@Autowired):
Q:(韩亚博)xml和注解 更倾向使用哪种 为什么?
A:(张强)都可以,更倾向于注解方式,因为注解方式比较方便,而且不用配置,直接标注就可以使用
Q:(王耀琪)注解的优点是什么?
A:(张强)便捷,快速,可以通过xml或者直接注解的方式配置。
Q: (杨聪聪)@Autowired 可以标注哪些成员?
A:(张强)可以标注使用扫描注解或者xml里配置的成员。
Q:(方逾阳)构造法和setter方法哪种更好的?有没有这种比较?
A:(张强)构造方法是固定的,加载的时候已经初始化好了的。setter是比构造方法后加载的。根据情况各有针对性。
Q:(常雷雷)SSM框架整合中Spring容器的加载顺序是咋样的?
A:(张强)加载顺序是xml配置,然后静态工厂配置,然后创建bean实例。
Q:(何东霖)ref和value使用上有什么区别?
A:(张强)ref是已经配置的bean,value是简单的基本属性。
Q:(娄文彬,常雷雷)@Autowired与@resouce的区别是什么?
A:(张强)@Autowired是spring的注解,默认为bytype,@resource是j2ee的注解,默认为byname。
Q:@Autowired @Resource分别在什么情况使用
A:(张强)@A是自动搜索通过bytype的顺序匹配,@R是j2ee的,通过name匹配,所以在通过不同形式装配的时候根据需要使用
Q:试过p命名空间吗?
A:(张强)没有试过……
p命名空间:
&bean id="id class="..classn" p:name="name" p:spouse-ref="beanname"/&
&bean id="beanname"/&
p:name,表示的是Class中定义的name属性
p:spouse-ref,表示的Class中的spouse属性,其对应下面的id为beanname的值。
Q:(王耀琪)控制反转与依赖注入的关系
A:(张强)同种情况的不同角度,这两个指的是一个情况。
技能树.IT修真院
“我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己学习的节奏,学习的路上不再迷茫”。
这里是技能树.IT修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄1对1免费指导。
快来与我一起学习吧~
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
欢迎使用Markdown编辑器写博客
本Markdown编辑器使用修改而来,用它写博客,将会带来全新的体验哦:
Markdown和扩展Markdown简洁的语法
代码块高亮
图片链接和图片上传
LaTex数学公式
UML序列图和流程图
离线写博客
导入导出Markdown文件
丰富的快捷键
Markdown及扩展
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。
使用简单的符号标识不同的标题,将某些文字标记为粗体或者斜体,创建一个等,详细语法参考帮助?。
本编辑器支持 Markdown Extra ,  扩展了很多好用的功能。具体请参考.
Markdown Extra 表格语法:
可以使用冒号来定义对齐方式:
Markdown Extra 定义列表语法:
代码块语法遵循标准markdown代码,例如:
@requires_authorization
def somefunc(param1='', param2=0):
'''A docstring'''
if param1 & param2:
print 'Greater'
return (param2 - param1 + 1) or None
class SomeClass:
&&& message = '''interpreter
... prompt'''
生成一个脚注.
用 [TOC]来生成目录:
使用MathJax渲染LaTex 数学公式,详见.
行内公式,数学公式为:<span class="MathJax" id="MathJax-Element-1-Frame" tabindex="0" data-mathml="&#x0393;(n)=(n&#x2212;1)!&#x2200;n&#x2208;N" role="presentation" style="position:">Γ(n)=(n-1)!?n∈NΓ(n)=(n-1)!?n∈N。
块级公式:
<span class="MathJax" id="MathJax-Element-2-Frame" tabindex="0" data-mathml="x=&#x2212;b&#x00B1;b2&#x2212;4ac2a" role="presentation" style="text-align: position:">x=-b±b2-4ac-------√2ax=-b±b2-4ac2a
更多LaTex语法请参考 .
可以渲染序列图:
Created with Rapha?l 2.1.2张三张三李四李四嘿,小四儿, 写博客了没?李四愣了一下,说:忙得吐血,哪有时间写。
或者流程图:
Created with Rapha?l 2.1.2开始我的操作确认?结束yesno
关于 序列图 语法,参考 ,
关于 流程图 语法,参考 .
离线写博客
即使用户在没有网络的情况下,也可以通过本编辑器离线写博客(直接在曾经使用过的浏览器中输入即可。Markdown编辑器使用浏览器离线存储将内容保存在本地。
用户写博客的过程中,内容实时保存在浏览器缓存中,在用户关闭浏览器或者其它异常情况下,内容不会丢失。用户再次打开浏览器时,会显示上次用户正在编辑的没有发表的内容。
博客发表后,本地缓存将被删除。 
用户可以选择
把正在写的博客保存到服务器草稿箱,即使换浏览器或者清除缓存,内容也不会丢失。
注意:虽然浏览器存储大部分时候都比较可靠,但为了您的数据安全,在联网后,请务必及时发表或者保存到服务器草稿箱。
浏览器兼容
目前,本编辑器对Chrome浏览器支持最为完整。建议大家使用较新版本的Chrome。
IE9以下不支持
IE9,10,11存在以下问题
不支持离线功能
IE9不支持文件导入导出
IE10不支持拖拽文件导入
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
什么是SpringIOC?为什么要用IOC而不是New来创建实例?1.背景介绍什么是spring: 2002年,Rod Johnson在《Expert One-on-One J2EE Design and Development》书中首次推出了Spring框架雏形interface21框架。到现在将近20年了。最早Spring是为了解决企业级应用开发的复杂性而创建的。但是归根究底它的主要使命就是一点:简化java开发
Spring的开发策略:
基于POJO类的轻量级和最小侵入性编程;
通过依赖注入和面向接口实现松耦合;
基于切面和惯例进行声明式编程;
通过切面和模板减少样板式代码;
◆目的:解决应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了非常多的功能模块支持
◆范围:任何Java应用
java程序是通过很多类相互协作、相互调用来实现的,也就是说它们相互依赖。只要有了依赖就有了耦合,spring就是为了解决这些耦合,它致力于建造更容易维护、清晰度更高、更容易开发的代码。
Spring的优点:
低侵入式设计;
独立性强,能独立于各种应用服务器
兼容性强,能融合各种框架模块,比如hibernate/mybatis/redis/actuvemq/sgiro/quartz/kafka……
分层结构,模块化,可扩展性更好
开发效率高,易维护,易测试
Spring主要的核心:
SpringIOC 控制反转 容器管理
SpringAOP 切面编程
Spring ORM 对象关系映射
DAO 数据访问对象 (Transaction JDBC等等)
Spring Web MVC (web应用)
Spring Context (提供运行环境)2.知识剖析
什么是SpringIOC?
SpringIOC是Spring框架的一个核心概念。
java程序中的类互相依赖,大量耦合。而SpringIOC(Inversion of Control)就是去创建管理这些依赖,从而尽可能的降低耦合,这些被它创建管理的类被称为bean。它是一个思想,从字面上看它是控制反转,但是直接说反转可能难以理解,我们可以从另一个角度去理解它,比如先理解正再理解反会更容易一些。什么是正,我们平常去new对象就是正面使用,我们使用Spring依赖注入(DI)去获取对象也是正面使用,new的时候是自己去创建依赖然后使用,但是这样我们的代码内部就有了它的实例,这就有了耦合。
spring容器读取了配置元数据之后,通过java反射创建类并注入其依赖类。
为什么不使用new来创建实例?
1.增加耦合,会访问到内部属性
2.更新的地方比较多,难于维护
3.常见问题
SpringBean和javaBean
传统的javaBean基本上跟POJO类差不多,就是为了传值而存在,没有任何容器去管理它的生命周期,完全是靠回收机制回收。Spring沿用了Bean这个名称,但是Spring里只要是SpringIOC创建管理的任何类都可以称为Bean,而且它生成的bean完全由自己管理,生命周期可以自己控制;
Ref和Value
ref: 由IOC管理的其它bean
value:基本类型赋值
注解和扫描方式
context:component-scan
base-package="com.xks.service"
& 不需要写bean,直接扫描
context:annotation-config
开启注解,需要写bean
4.编码实战
5.扩展思考
beanan生命周期scope控制bean的生命周期,scope的取值有5种取值:在Spring 2.0之前,有singleton和prototype两种;在Spring 2.0之后增加另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用。singleton 默认 单一实例 所有引用这个bean使用的都是一个,由spring控制。只要不销毁或者推出它就一直存在。prototype 标准 每次引用spring都返回一个新的,这个对象完全属于引用者。一般用来定义不能共享使用的对象类型。
Spring的缺点
1.性能损耗,跟jsp+servlet+javabean性能差距很大
2.内存消耗大,缓存多
3.异常(bug)定位不是特别准确
4.越来越大,不容易理解知识体系(比如spring自己的测试体系,版本变更不清楚,配置和注解背后的原理、和j2EE自己的注解分不清,还有事务管理优越在哪里等等)
有没有更好的方式代替spring
因为spring已经被大家研究的比较透彻了,所以一般来说spring是最佳的选择,如果非要替代的话可以直接使用servlet + javaBean 或者 EJB
6.参考文献
Spring实战 第二版
7.更多讨论
Spring容器中的bean是容器启动就存在了吗?其中的bean默认是单例模式还是多例模式?启动的时候会自动创建bean,其中的bean默认是单例模式,如果使用多例的话需要设置scope为prototype 需要的时候才创建的话懒加载又是什么设置default-lazy-init="true"启动懒加载注解的优点是什么?便捷,快速 @Autowired 可以标注哪些成员?可以标注使用扫描注解或者xml里配置的成员。构造法和setter方法哪种更好的?有没有这种比较?构造方法是固定的,加载的时候已经初始化好了的。setter是比构造方法后加载的。根据情况各有好坏SSM框架整合中Spring容器的加载顺序是咋样的?加载顺序是xml配置,然后静态工厂配置,然后创建bean实例ref和value使用上有什么区别?ref是已经配置的bean,value是简单的基本属性@Autowired与@resouce的区别是什么?@Autowired是spring的注解,默认为bytype@resource是j2ee的注解,默认为byname
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
onload=''&
&script type="text/javascript"&
window.onload=function()//用window的onload事件,窗体加载完毕的时候
//do something
var st = "";
$(function(){});
$().ready({
for(var i=0;i&9;i++){
st+="&div class='lbox'&5&/div&"
document.getElementByID('controller').innerHTML =
});$(function(){
alert("a");
for(var i=0;i&9;i++){
st+="&div class='lbox'&5&/div&"
alert(st);
var divadd = document.getElementByID('controller').innerHTML;
$("#controller").html(st);
window.onload=function(){
var st="";
&%--alert("2"+st);--%&
for(var i=0;i&9;i++){
st+="&div class='lbox'&5&/div&";
var divadd = document.getElementById("controller");
divadd.innerHTML =
&%--$("#controller").html(st);--%&
&%--alert(st);--%&
&%--document.write--%&
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
https://blog.csdn.net/weixin_/article/details/
jq提交方法:$("#selectid").on('click',function(){
var from = $('#restSelFrom');
var id = $('#uid').val();
var patrn = /^[0-9]*$/;
if(!patrn.exec(id) || id =="" ){
layer.tips('请输入正确的id', '#uid', {
tips: [1, '#3595CC'],
time: 4000
from.action="/ptt/entity/"+
alert(from.action)
from.submit();
});from提交方法:&form class="navbar-form navbar-left" role="search" action="/ptt/entity/5"
id="restSelFrom"
&div class="form-group"&
&input type="text" class="form-control" name="uid" id="uid"
&button type="submit" class="btn btn-default" form="restSelFrom"
&查询(id)&/button&
&/form&它们的提交路径都是"/ptt/entity/参数"但是jq提交会变成/?id=参数 而表单arcion依然会是"/ptt/entity/参数"使用:window.location.href = "/ptt/u/restudent/"+ 不使用 :from.submit();以后需要再研究
作者:weixin_ 发表于
https://blog.csdn.net/weixin_/article/details/

我要回帖

更多关于 厂里组织娱乐活动的口号 的文章

 

随机推荐