key point
- Servlet GenericServlet HttpServlet HttpRequestServlet HttpResponseServlet
- 保持狀態(tài)的方法
- Servlet 之間的消息共享級(jí)別
- Context Listener(application)
- ServletContextListener
- ServletContextAttributeListener
- Session Listener session
- HttpSessionListener
- HttpSessionAttributeListener
- HttpSessionActivationListener
- HttpSessionBindingListener
- Filter
Java 和PHP體系對(duì)比
體系 | 負(fù)載均衡 | 中間件 | 框架 | 數(shù)據(jù)庫(kù) |
---|---|---|---|---|
JAVA | nginx | tomcat/jboss | spring/play | mysql/postgre... |
PHP | nginx | php-cgi | thinkphp/laravel | mysql/postgre... |
基本信息
servlet 的全稱(chēng)是 Server Applet讼庇。 是用Java編寫(xiě)的服務(wù)器端程序诚撵。其主要功能在于交互式地瀏覽和修改數(shù)據(jù)搅轿,生成動(dòng)態(tài)內(nèi)容。servlet不僅能處理http協(xié)議還能處理ftp等協(xié)議夺饲。
在servlet3.0之前一個(gè)servlet應(yīng)用由一系列處理請(qǐng)求的Java編譯文件(*.class)和一個(gè)告訴Java編譯文件是怎么組織的部署描述符(web.xml)構(gòu)成组砚。
在3.0之后 部署描述可以通過(guò)Java編碼的方式進(jìn)行拆挥,web.xml可以省略畔咧。
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.servlet;
import java.io.IOException;
/**
* Defines methods that all servlets must implement.
*
* <p>A servlet is a small Java program that runs within a Web server.
* Servlets receive and respond to requests from Web clients,
* usually across HTTP, the HyperText Transfer Protocol.
*
* <p>To implement this interface, you can write a generic servlet
* that extends
* <code>javax.servlet.GenericServlet</code> or an HTTP servlet that
* extends <code>javax.servlet.http.HttpServlet</code>.
*
* <p>This interface defines methods to initialize a servlet,
* to service requests, and to remove a servlet from the server.
* These are known as life-cycle methods and are called in the
* following sequence:
* <ol>
* <li>The servlet is constructed, then initialized with the <code>init</code> method.
* <li>Any calls from clients to the <code>service</code> method are handled.
* <li>The servlet is taken out of service, then destroyed with the
* <code>destroy</code> method, then garbage collected and finalized.
* </ol>
*
* <p>In addition to the life-cycle methods, this interface
* provides the <code>getServletConfig</code> method, which the servlet
* can use to get any startup information, and the <code>getServletInfo</code>
* method, which allows the servlet to return basic information about itself,
* such as author, version, and copyright.
*
* @author Various
*
* @see GenericServlet
* @see javax.servlet.http.HttpServlet
*
*/
public interface Servlet {
/**
* Called by the servlet container to indicate to a servlet that the
* servlet is being placed into service.
*
* <p>The servlet container calls the <code>init</code>
* method exactly once after instantiating the servlet.
* The <code>init</code> method must complete successfully
* before the servlet can receive any requests.
*
* <p>The servlet container cannot place the servlet into service
* if the <code>init</code> method
* <ol>
* <li>Throws a <code>ServletException</code>
* <li>Does not return within a time period defined by the Web server
* </ol>
*
*
* @param config a <code>ServletConfig</code> object
* containing the servlet's
* configuration and initialization parameters
*
* @exception ServletException if an exception has occurred that
* interferes with the servlet's normal
* operation
*
* @see UnavailableException
* @see #getServletConfig
*
*/
public void init(ServletConfig config) throws ServletException;
/**
*
* Returns a {@link ServletConfig} object, which contains
* initialization and startup parameters for this servlet.
* The <code>ServletConfig</code> object returned is the one
* passed to the <code>init</code> method.
*
* <p>Implementations of this interface are responsible for storing the
* <code>ServletConfig</code> object so that this
* method can return it. The {@link GenericServlet}
* class, which implements this interface, already does this.
*
* @return the <code>ServletConfig</code> object
* that initializes this servlet
*
* @see #init
*
*/
public ServletConfig getServletConfig();
/**
* Called by the servlet container to allow the servlet to respond to
* a request.
*
* <p>This method is only called after the servlet's <code>init()</code>
* method has completed successfully.
*
* <p> The status code of the response always should be set for a servlet
* that throws or sends an error.
*
*
* <p>Servlets typically run inside multithreaded servlet containers
* that can handle multiple requests concurrently. Developers must
* be aware to synchronize access to any shared resources such as files,
* network connections, and as well as the servlet's class and instance
* variables.
* More information on multithreaded programming in Java is available in
* <a >
* the Java tutorial on multi-threaded programming</a>.
*
*
* @param req the <code>ServletRequest</code> object that contains
* the client's request
*
* @param res the <code>ServletResponse</code> object that contains
* the servlet's response
*
* @exception ServletException if an exception occurs that interferes
* with the servlet's normal operation
*
* @exception IOException if an input or output exception occurs
*
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
/**
* Returns information about the servlet, such
* as author, version, and copyright.
*
* <p>The string that this method returns should
* be plain text and not markup of any kind (such as HTML, XML,
* etc.).
*
* @return a <code>String</code> containing servlet information
*
*/
public String getServletInfo();
/**
*
* Called by the servlet container to indicate to a servlet that the
* servlet is being taken out of service. This method is
* only called once all threads within the servlet's
* <code>service</code> method have exited or after a timeout
* period has passed. After the servlet container calls this
* method, it will not call the <code>service</code> method again
* on this servlet.
*
* <p>This method gives the servlet an opportunity
* to clean up any resources that are being held (for example, memory,
* file handles, threads) and make sure that any persistent state is
* synchronized with the servlet's current state in memory.
*
*/
public void destroy();
}
public void init(ServletConfig servletConfig) throws ServletException ;
init 方法在整個(gè)類(lèi)的生命周期內(nèi)只執(zhí)行一次(不是每一次用戶(hù)請(qǐng)求一次、這個(gè)類(lèi)就會(huì)被生成一次牧牢,而是當(dāng)用戶(hù)第一次請(qǐng)求這個(gè)類(lèi)的時(shí)候這個(gè)類(lèi)會(huì)被生成看锉,然后這個(gè)類(lèi)會(huì)放在JVM的heap里面,直到被GC)
ServletConfig servletConf
容器從部署文件中讀出Servlet初始化參數(shù)塔鳍,并把這些參數(shù)交給ServletConfig伯铣,然后把ServletConfig傳遞給servlet的init(ServletConfig config)方法。從而避免了在類(lèi)里硬編碼
URI和servlet對(duì)應(yīng)的這個(gè)部分可以用注解來(lái)代替
@WebServlet(name = "test", urlPatterns = {"/test1/test2/test3/"})
@WebInitParam(name = "color", value = "red")
public class MyServlet2 extends HttpServlet{
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
PrintWriter printWriter = response.getWriter();
printWriter.printf(getServletConfig().getInitParameter("color"));
}
}
對(duì)于之前的servlet接口有兩個(gè)可以改進(jìn)的地方
- 對(duì)于我們沒(méi)有功能的方法也要進(jìn)行實(shí)現(xiàn)
- servletConfig要我們自己去定義
于是就有了
GenericServlet 這個(gè)類(lèi)里面有ServletConfig屬性轮纫,實(shí)現(xiàn)了servlet接口腔寡,我們的類(lèi)繼承GenericServlet這個(gè)接口,只用對(duì)有必要的函數(shù)進(jìn)行重寫(xiě)蜡感。
為了便于http的處理蹬蚁,JEE提供了HttpServlet。HttpServlet繼承于GenericServlet郑兴。
在實(shí)現(xiàn)Servlet接口的service方法的時(shí)候?qū)⑷雲(yún)⑾蛳罗D(zhuǎn)型為HttpServletRequest 和HttpServletRequest犀斋。這樣我們可以使用HTTP協(xié)議的一些特性。
HttpServletRequest
- String getContextPath();//返回context(上下文的根)的路徑
- Cookie[] getCookies();//獲得cookie
- String getHeader(String name);//根據(jù)HTTP頭的key獲得value
- String getMethod();//獲得請(qǐng)求的方法
- String getQueryString(); //返回URI?后面的全部部分
- HttpSession getSession();//找到和這個(gè)請(qǐng)求的有關(guān)的session情连。如果沒(méi)有找到叽粹,創(chuàng)建新的session。
HttpServletResponse
- addCookie(Cookie cookie);
- addHeader();
- sendRedirect(); 向?yàn)g覽器response 狀態(tài)碼為302 location為sendRedirect里的地址
HttpService 重載service方法 根據(jù)HttpRequest.method 的不同將請(qǐng)求分發(fā)到不同的函數(shù)中却舀,后續(xù)繼承HttpService的類(lèi)只要重寫(xiě)要進(jìn)行處理的Http方法的方法就好虫几。比如我要處理http的get,我繼承于HttpService的類(lèi)只要重寫(xiě)doGet方法就好挽拔。
Servlet保持狀態(tài)的4種方法
- 網(wǎng)址重寫(xiě) ?a=b&c=d
- form-data
- cookie
- HttpSession
第1種和第2種方法可以通過(guò)request.getParameter("")的方式 通過(guò)key來(lái)訪(fǎng)問(wèn)值
第3種 cookie是放在http頭部中的 每一次向服務(wù)器發(fā)送信息的時(shí)候都會(huì)包括該域名下所有的cookie辆脸,cookie的個(gè)數(shù)是有限制的最大數(shù)量為20個(gè)。通過(guò)HttpServletReuest 的getCookies()方法可以獲得所有的cookie 然后通過(guò)比較cookie名稱(chēng)和我們預(yù)想的cookie的name是否一致得到我們想要的cookie螃诅。
第4種方法 一般向服務(wù)器發(fā)送消息的時(shí)候會(huì)有一個(gè)叫做JESSIONID Cookie 里面包含了在內(nèi)存這次訪(fǎng)問(wèn)session的key啡氢,服務(wù)器可以根據(jù)這個(gè)key反序列化出相關(guān)的信息。在Servlet中可以通過(guò)HttpServlet的getSession() 方法得到本次訪(fǎng)問(wèn)的HttpSession 對(duì)象术裸。
Servlet之間的消息共享
Servlet 之間通過(guò)Attribute(屬性)的方式進(jìn)行消息共享倘是。消息分享的層級(jí)有以下三個(gè)
- request(當(dāng)個(gè)訪(fǎng)問(wèn)者當(dāng)次請(qǐng)求)
- session (當(dāng)個(gè)訪(fǎng)問(wèn)者,所有的請(qǐng)求)
- application (全部訪(fǎng)問(wèn)者袭艺,所有的請(qǐng)求)
在request 級(jí)別的attirbute 的使用方法一般是
Map<String, String[]> bigCities = new HashLinkedMap<>();
bigCities.put("China",{"Beijing", "Shanghai", "Hongkong"});
bigCities.put("USA",{"New York", "Boston", "Washington, D.C."})
request.setAttrribuate("bigCities",bigCities);
RequestDispatcher rd = request.getRequestDispatcher("/show.jsp");
rd.forward(request, response);
將屬性放到request中搀崭,把這個(gè)屬性轉(zhuǎn)交給jsp頁(yè)面進(jìn)行頁(yè)面的渲染
<c:forEach item = "${requestScope.bigCities}" var = "country">
${country.key}
<c:forEach item= "${country.value}" var ="city" varStatus = "status">
${city}
<c:if test = "${! status.last}">
<br/>
</c:if>
</c:forEach>
</c:forEach>
監(jiān)聽(tīng)器
進(jìn)行事件驅(qū)動(dòng)編程,當(dāng)什么事情發(fā)生的時(shí)候我們要做出合適的反應(yīng)
定義監(jiān)聽(tīng)器有兩個(gè)方法
@WebListener
public class ListenerClass implements ListenerInterface{
}
或者
<listen>
<listener-class>org.cor.projectName.something</listener-class>
</listen>
Context Listener 上下文級(jí)別的監(jiān)聽(tīng)器
ServletContextLister
當(dāng)一個(gè)application的context被容器所創(chuàng)建的時(shí)候猾编,容器會(huì)調(diào)用實(shí)現(xiàn)這個(gè)接口的對(duì)象的特定方法
- void contextInitialized(ServletContextEvent event);
對(duì)環(huán)境的初始化做出響應(yīng) - void contextDestoryed(ServletContextEvent event);
對(duì)環(huán)境的析構(gòu)做出響應(yīng) - ServletContext getServletContext();
得到上下文對(duì)象
for example
@WebListener
public class AppContextListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent event){
Map<String, String> contries = new HashMap<String, String>();
contries.put("ca", "Canada");
contries.put("us", "USA");
}
}
當(dāng)一個(gè)application的context被容器所創(chuàng)建的時(shí)候瘤睹,我們給容器增加一個(gè)Attribute
ServletContextAttributeListener
當(dāng)application范圍內(nèi)的attribute發(fā)生改變的時(shí)候,容器會(huì)調(diào)用實(shí)現(xiàn)這個(gè)接口的對(duì)象的特定方法
- void attributeAdded(ServletContextAttributeEvent event);
增加屬性 - void attributeRemoved(ServletContextAttributeEvent event);
刪除屬性 - void attributeReplaced(ServletContextAttributeEvent event);
替換屬性的內(nèi)容
Session Listener session級(jí)別的監(jiān)聽(tīng)器
HttpSessionListener
這個(gè)接口的作用是和上面的ServletContextLister相類(lèi)似只不過(guò)是作用于session范圍
- sessionCreated(HttpSessionEvent event);
當(dāng)一個(gè)session被創(chuàng)建時(shí)會(huì)調(diào)用這個(gè)方法 - sessionDestroyed(HttpSessionEvent event);
當(dāng)一個(gè)session被銷(xiāo)毀時(shí)調(diào)用這個(gè)方法 - HttpSession getSession();
獲得要被操作的session
HttpSessionAttributeListener
這個(gè)接口的作用和上面的ServletContextAttributeListener 相類(lèi)似答倡,作用于session范圍
- void attributeAdded(HttpSessionBindingEvent event)
屬性添加 - void attributedRemoved(HttpSessionBindingEvent event);
屬性刪除 - void attributeReplace(HttpSessionBindingEvent event);
HttpSessionActivationListener
session 是保存在內(nèi)存中默蚌,當(dāng)內(nèi)存不夠的時(shí)候容器會(huì)嘗試著將session進(jìn)行遷移或者序列化,通過(guò)這個(gè)接口能對(duì)做出容器的行為做出反應(yīng)
- void sessionDidActivate(HttpSessionEvent event);(容器嘗試將session觸發(fā))
- void sessionWillPassivate(HttpSessionEvent event);(容器嘗試著將session鈍化)
HttpSessionBindingListener
如果一個(gè)類(lèi)想知道什么時(shí)候被綁定到HttpSesison上苇羡,那么這個(gè)類(lèi)要實(shí)現(xiàn)HttpSessionBindingListener接口绸吸,在綁定的時(shí)候或者不綁定的時(shí)候,這個(gè)類(lèi)會(huì)做出合適反應(yīng)
public BigCity implements HttpSessionBindingListener{
...
@Override
public void valueBound(HttpSessionBindingEvent event){
}
@Override
public void valueUnbound(HttpSessionBindingEvent event){
}
}
在把這個(gè)類(lèi)的對(duì)象放到session的setAttribute的時(shí)候设江,valueBound會(huì)被調(diào)用锦茁。
過(guò)濾器
過(guò)濾器是指請(qǐng)求過(guò)來(lái)的時(shí)候先攔截請(qǐng)求,處理一波之后在交給servlet叉存,在驗(yàn)證登陸狀態(tài)字符處理等的方面都有應(yīng)用码俩。
定義過(guò)濾器有兩個(gè)方法
@WebFilter(filterName = "***Filter", urlPatterns = {"/*"})
//過(guò)濾器必須要以Filter結(jié)尾
public class ***Filter implements Filter{
}
或者在部署文件中
<filter>
<filter-name>***Filter</filter-name>
<filter-class>test.andrew.io.***Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>***Filter</filter-name>
<url-patten>/*</url-patten>
</filter-mapping>
一個(gè)典型的Filter的應(yīng)用,設(shè)置字符
public class UTF8Filter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain fchain) throws IOException, ServletException {
// TODO Auto-generated method stub
//System.out.println("先執(zhí)行過(guò)濾器里面的內(nèi)容歼捏。稿存。笨篷。。瓣履。");
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
fchain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
Spring MVC
就和其他的框架一樣 Sring 的出現(xiàn)也是為了簡(jiǎn)化開(kāi)發(fā)
- Spring 環(huán)境的構(gòu)建
1.1 old school
step1: 在web.xml 指定把所有的請(qǐng)求都發(fā)送給處理<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
- contextLoaderListener
ContextLoaderListener的作用就是啟動(dòng)Web容器時(shí)率翅,自動(dòng)裝配ApplicationContext的配置信息。因?yàn)樗鼘?shí)現(xiàn)了ServletContextListener這個(gè)接口袖迎,在web.xml配置這個(gè)監(jiān)聽(tīng)器冕臭,啟動(dòng)容器時(shí),就會(huì)默認(rèn)執(zhí)行它實(shí)現(xiàn)的方法燕锥。至于ApplicationContext.xml這個(gè)配置文件部署在哪辜贵,如何配置多個(gè)xml文件,書(shū)上都沒(méi)怎么詳細(xì)說(shuō)明」樾危現(xiàn)在的方法就是查看它的API文檔托慨。在ContextLoaderListener中關(guān)聯(lián)了ContextLoader這個(gè)類(lèi),所以整個(gè)加載配置過(guò)程由ContextLoader來(lái)完成暇榴×穹迹看看它的API說(shuō)明- 第一段
ContextLoaderServlet的API,可以看到它繼承了ContextLoader這個(gè)類(lèi)而且它實(shí)現(xiàn)了ServletContextListener跺撼。
主要的實(shí)現(xiàn)是基于ContextLoader 這個(gè)類(lèi). - 第二段
ContextLoader創(chuàng)建的是 XmlWebApplicationContext這樣一個(gè)類(lèi)窟感,它實(shí)現(xiàn)的接口是WebApplicationContext->ConfigurableWebApplicationContext->ApplicationContext->
BeanFactory這樣一來(lái)spring中的所有bean都由這個(gè)類(lèi)來(lái)創(chuàng)建 - 第三段
講如何部署applicationContext的xml文件,如果在web.xml中不寫(xiě)任何參數(shù)配置信息歉井,默認(rèn)的路徑是"/WEB-INF/applicationContext.xml柿祈,在WEB-INF目錄下創(chuàng)建的xml文件的名稱(chēng)必須是applicationContext.xml。如果是要自定義文件名可以在web.xml里加入contextConfigLocation這個(gè)context參數(shù):
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext-.xml
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext-.xml
</param-value>
</context-param>
在<param-value> </param-value>里指定相應(yīng)的xml文件名哩至,如果有多個(gè)xml文件躏嚎,可以寫(xiě)在一起并一“,”號(hào)分隔。上面的applicationContext-.xml采用通配符菩貌,比如這那個(gè)目錄下有applicationContext-ibatis-base.xml卢佣,applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件箭阶,都會(huì)一同被載入虚茶。
由此可見(jiàn)applicationContext.xml的文件位置就可以有兩種默認(rèn)實(shí)現(xiàn):
第一種:直接將之放到/WEB-INF下
第二種:將之放到classpath下,但是此時(shí)要在web.xml中加入<context-param>仇参,用它來(lái)指明你的applicationContext.xml的位置以供web容器來(lái)加載嘹叫。按照Struts2 整合spring的官方給出的檔案,寫(xiě)成:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-.xml,classpath:applicationContext-.xml</param-value>
</context-param>
- 第一段
但是也不一定要定義applicationContext.xml, 如果不定義 applicationContext
1.2 使用config方bo
- Spring對(duì)請(qǐng)求的處理
- Spring 的ORM
- Spring的不同環(huán)境
spring part
該注解用于讀取Request請(qǐng)求的body部分?jǐn)?shù)據(jù)
資料1
資料2
資料3
Spring 環(huán)境的構(gòu)建
每種語(yǔ)言采用自動(dòng)化構(gòu)建的方式不盡相同诈乒,Python用的是pip罩扇,PHP用的是Composer,現(xiàn)在Java社區(qū)比較常用的是gradle和maven怕磨。
下面介紹maven的依賴(lài)構(gòu)建
首先用ide構(gòu)建一個(gè)maven的項(xiàng)目
一個(gè)pom.xml的樣例
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>andrew.io</groupId><!--組織名稱(chēng)-->
<artifactId>spring</artifactId><!--項(xiàng)目名稱(chēng)-->
<version>1.0-SNAPSHOT</version><!--版本名稱(chēng)-->
<dependencies>
<!--在這個(gè)位置添加依賴(lài)的包-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.10.5.RELEASE</version>
</dependency>
</dependencies>
</project>
一個(gè)簡(jiǎn)易的Spring MVC的分層
和其他語(yǔ)言的項(xiàng)目一樣喂饥,一個(gè)簡(jiǎn)單的spring mvc project也會(huì)對(duì)項(xiàng)目進(jìn)行分層消约。分的層次大致如下
- controller
主要用來(lái)組裝客戶(hù)端發(fā)過(guò)來(lái)的信息然后給業(yè)務(wù)層進(jìn)行處理
捕捉異常,對(duì)異常進(jìn)行合適處理
將結(jié)果反饋給請(qǐng)求方 - service
負(fù)責(zé)主要的業(yè)務(wù)邏輯的操作 - dao
數(shù)據(jù)庫(kù)CRUD - domian
對(duì)象和數(shù)據(jù)庫(kù)中的實(shí)體對(duì)應(yīng) - config spring
配置類(lèi)和spring配置文件(xml,yum,property)
這樣可以明確每個(gè)層次的邊界员帮、減少每個(gè)層次之間的耦合度或粮、增強(qiáng)復(fù)用性。
通過(guò)Spring MVC響應(yīng)一個(gè)請(qǐng)求
當(dāng)一個(gè)請(qǐng)求被容器響應(yīng)的時(shí)候集侯,首先由spring框架的DispatcherServlet進(jìn)行處理。它是一個(gè)前端控制器帜消,在Spring框架中通過(guò)單例模式實(shí)現(xiàn)棠枉,所有的請(qǐng)求都會(huì)通過(guò)它將任務(wù)派發(fā)被Controller。典型的應(yīng)用程序中會(huì)有多個(gè)控制器泡挺,DispatcherServlet會(huì)查詢(xún)一個(gè)或者多個(gè)控制器映射(handler mapping)來(lái)確定要派發(fā)給誰(shuí)辈讶。Controller的職責(zé)主要是將發(fā)過(guò)來(lái)的request做一個(gè)合適的處理(網(wǎng)址重寫(xiě)?a=b,還是通過(guò)表單提交(form-data)的post中的數(shù)據(jù)娄猫,或者是application-* 形式的)贱除,在把數(shù)據(jù)發(fā)送給server層,server層根據(jù)業(yè)務(wù)的要求對(duì)數(shù)據(jù)進(jìn)行加工媳溺,在加工過(guò)程的CRUD由Dao層負(fù)責(zé)月幌,之后將處理好的結(jié)果返回給Contorller。Controller將得到的數(shù)據(jù)進(jìn)行打包悬蔽,并且標(biāo)示出用于渲染輸出的視圖名扯躺,同時(shí)將這些數(shù)據(jù)返回給DispatcherServlet。DispatcherServlet會(huì)將使用視圖解析器(view resolver)來(lái)將邏輯視圖名匹配為一個(gè)特定的視圖實(shí)現(xiàn)蝎困。視圖將使用模型數(shù)據(jù)渲染輸出录语。由此一次請(qǐng)求完成。
配置DispatcherServlet
配置可以通過(guò)web.xml 實(shí)現(xiàn)禾乘,但是xml畢竟不如代碼清晰澎埠,現(xiàn)在比較推薦通過(guò)java類(lèi)進(jìn)行配置以下為一個(gè)配置類(lèi)
public class WebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer{
//
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[0];
}
//配置文件類(lèi)
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[0];
}
//指定上下文的根
protected String[] getServletMappings() {
return new String["/"];
}
}
怎么發(fā)揮作用的?
st=>start: 開(kāi)始
servlet=>operation: 容器查找實(shí)現(xiàn) ServletContainerInitializer接口的類(lèi)
spring=>operation: spring提供了這個(gè)接口的實(shí)現(xiàn)始藕,但是它會(huì)找實(shí)現(xiàn)了WebApplicationInitailizer的類(lèi)
spring3=>operation: spring3.2提供了一個(gè)WebApplicationInitailizer的基礎(chǔ)實(shí)現(xiàn)
蒲稳,叫做AbstractAnnotationConfigDispatcherServletInitializer,
但是正如名字顯示的是Abstract(抽象的)需要通過(guò)開(kāi)發(fā)者進(jìn)行實(shí)現(xiàn)
e=>end: 結(jié)束
st->servlet->spring->spring3->e
st=>start: 開(kāi)始
e=>end: 結(jié)束