關於利用maven搭建ssm的博客,我們一起來探討下問的最多的問題

来源:https://www.cnblogs.com/youzhibing/archive/2019/04/10/10658540.html
-Advertisement-
Play Games

前言 開心一刻 有個同學去非洲援建,剛到工地接待他的施工員是個黑人,他就用英語跟人家交流,黑人沒做聲。 然後他又用法語,黑人還是沒說話。 然後他用手去比劃。黑人終於開口了:瞎比劃嘎哈,整個工地都中國人 前提背景 在利用maven/eclipse搭建ssm(spring+spring mvc+myba ...


前言

  開心一刻

    有個同學去非洲援建,剛到工地接待他的施工員是個黑人,他就用英語跟人家交流,黑人沒做聲。 然後他又用法語,黑人還是沒說話。 然後他用手去比劃。黑人終於開口了:瞎比劃嘎哈,整個工地都中國人

前提背景

  在利用maven/eclipse搭建ssm(spring+spring mvc+mybatis)一文的問題反饋中,大體分兩個:404和頁面無數據;至於500,個人認為比較好解決,按照提示進行處理就好,本文就不討論500了

  404

    主要也是兩種

    1、webapp未發佈

      相關資源未部署,例如webapp未發佈部署,類似如下

      不只是webapp,main下的java、resources、webapp,maven依賴都是需要部署到tomcat,不然就不完整,就會存在各種各樣的少內容的問題;

    2、請求URL不對

      這個確實是很多新入行的小伙伴容易出現的問題

      如果工程正常部署,請求URL出現404,很有可能是我們請求的URL不對;我們到tomcat的home目錄下看看工程是否正常部署,類似如下

      還可以看看工程發佈的內容(問題1中需要發佈的內容)是否都在;如果工程部署正常,而請求的URL又出現404,那不用想,就是你的URL寫錯了

    404的解決方案就是:確認工程是否正確部署到tomcat,確認請求的URL是否正確,基本只要確認這兩點也就能找到問題了;後文不會再詳細的講404,我們將重點放到下麵這個問題上

  頁面無數據

    具體的問題應該是這樣的:當我們請求:http://localhost:埠/工程名/personController/showPerson時,數據正常顯示如下

    當我們直接請求jsp時,只有title沒有數據,如下

    這是為什麼?

    對於這個問題一開始確實沒太在意,只是提示小伙伴去看servlet的四大作用域和jsp的九大內置對象,後面陸陸續續很多小伙伴都問了我,包括評論區留言、站內消息、QQ私聊等

    站內信

    評論區

    QQ

    我發現這個問題好像不是個別小伙伴的問題,很多新入門的小伙伴都存在這樣的疑問,下麵我們就對此次問題就行一個詳細的探究;後續篇幅較長,基礎鋪墊較多,希望大家耐心看完

問題探究

  servlet與servlet容器

    狹義上來講,servlet指的就是介面:javax.servlet.Servlet,廣義上來講,servlet指的是servlet規範:Java Servlet API 標準;javax.servlet.Servlet與servlet容器都是servlet規範下的產物。Java Servlet API是Servlet容器和Servlet之間的介面,它定義了Servlet的各種方法,還定義了Servlet容器傳送給Servlet的對象類,其中最重要的是請求對象ServletRequest和響應對象ServletResponseo這兩個對象都是由Servlet容器在客戶端調用Servlet時產生的,Servlet容器把客戶請求信息封裝在ServletRequest對象中,然後把這兩個對象都傳送給要調用的Servlet,Servlet處理完後把響應結果寫入ServletResponse,然後由Servlet容器把響應結果發送到客戶端。

    Servlet與Servlet容器的關係有點像槍和子彈的關係,槍是為子彈而生,而子彈又讓槍有了殺傷力。雖然它們是彼此依存的,但是又相互獨立發展,這一切都是為了適應工業化生產的結果。從技術角度來說是為瞭解耦,通過標準化介面來相互協作。Servlet 容器作為一個獨立發展的標準化產品,目前它的種類很多,包括Jetty、tomcat、resin、JBoss、WebSphere、Weblogic等,這些都是成熟的產品,有專門的公司或者組織進行維護,我們直接拿來用就好。

    我們約定下,下文中的servet指的都是servlet介面:javax.servlet.Servlet,servlet容器指的是:Tomcat,Web伺服器與Servlet容器是同一個內容(實際是有區別的,具體區別大家自行去查閱)

    Tomcat容器模型如下

    Tomcat響應客戶請求過程

      其中,①處表示Web伺服器接收到客戶端發出的HTTP請求後,轉發給Servlet容器,再由Servlet容器轉發給具體的Servlet實例進行請求的處理;②處表示Servlet實例將處理結果封裝進ServletResponse中,再由Servlet容器把ServletResponse發給Web伺服器,通知Web伺服器以HTTP響應的方式把結果發送到客戶端。也就是說,與客戶端直接打交道的是tomcat(servlet容器),而不是我們的Servlet實例,而真正處理請求的才是我們的Servlet實例。

    說的簡單點,我們自定義的Servlet,其實是對servlet容器在業務層面的拓展,相當於業務定製一樣;我們可以這樣理解,servlet容器對servlet提供技術支持,而servlet對servlet容器提供業務拓展,兩者缺一不可,缺了技術支持,業務拓展實施不起來,缺了業務拓展,技術支持沒有現實意義。Servlet容器封裝了底層複雜的技術實現,使我們可以專註於業務實現,而Servlet容器與業務實現之間的紐帶就是Servlet介面,它是我們對Servlet容器進行業務拓展的標準,所以我們的業務需要實現Servlet介面。套用阿基米德的杠桿原理:給Servlet容器多個servlet實例,Servlet容器還你豐富的web服務。

  JSP

    示例代碼:our-servlet

    我們先來看看在jsp出現之前,servlet如何輸出頁面,HelloServlet如下

package com.lee.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String businessDate = "業務數據....";
        
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.write("<html>");
        out.write("<head>");
        out.write("<title>Hello World</title>");
        out.write("</head>");
        out.write("<body>");
        out.write("<h1>Hello World!</h1>");
        out.write("<div><span><strong>");
        out.write(businessDate);
        out.write("</strong></span></div>");
        out.write("</body>");
        out.write("</html>");
        out.flush();
        out.close();
    } 
}
View Code

    不僅僅是業務數據,還包括靜態頁面的內容,通通在servlet返回,如果頁面簡單,這麼處理也能接受,但是如果頁面像淘寶、京東那樣非常複雜,你能想象嗎?太容易出錯了,一旦靜態頁面的元素少了或者多了內容,都不知道如何排查,面對茫茫多的out.write,就只有哭的份了。所以jsp就應運而生了。

    JSP全稱:Java Server Pages,允許在傳統靜態網頁HTML中插入Java代碼片段(Scriptlet)和JSP標簽,以簡化頁面靜態內容的開發。但需要註意的是,JSP文件的本質還是Servlet,只不過與Servlet不同的是,JSP是專門用於進行數據展示的Servlet;JSP最終會被Tomcat解析成Servlet,在Tomcat內置了一個JSP解析引擎,當第一次訪問該JSP頁面時,解析引擎會將JSP頁面解析成Servlet,然後再由Servlet將動態數據、靜態內容全部輸出到瀏覽器供展示。我們來看看jsp解析後的文件在哪裡、內容是什麼,以示例中的index.jsp為例。路徑如下圖

    index_jsp.java

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.47
 * Generated at: 2019-04-08 13:14:31 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n");
      out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");
      out.write("<title>index</title>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("    <div>\n");
      out.write("        Welcome, my friend!\n");
      out.write("    </div>\n");
      out.write("</body>\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
View Code

    發現熟悉的out.write又回來了,只是此時的out.write不是我們手動寫的,而是Tomcat解析jsp後生成的;如果jsp沒變動,jsp只會在第一次被調用時解析、編譯一次,後續的請求都會由編譯後的servlet處理,我們來驗證下,如何驗證了? 不變index.jsp內容再請求index.jsp,看看上圖中文件的修改時間會不會變

    發現文件的修改時間沒有變動,也就是說上面的的結論:如果jsp沒變動,jsp只會在第一次被調用時解析、編譯一次是對的。感興趣的朋友可以去看下Tomcat的源碼,看看具體的實現細節。

    有人可能會問:為什麼不將jsp的內容直接返回給瀏覽器?我們要明白一點:瀏覽器只能解析html、css、js,除此之外的內容它解析不了,那麼我們能直接將jsp的內容返回給瀏覽器嗎?所以中間有處理過程,最終由servlet將靜態內容返回給瀏覽器。有些愛問的小伙伴可能又會問了:瀏覽器為什麼只能解析:html、css、js,這涉及到瀏覽器規範的問題,除非你有能力改變這個規範,讓瀏覽器支持你想要的內容,這個問題不做過深的討論,我們姑且認為這是瀏覽器的限制,既然我們改變不了這個限制,那就適應這個限制。

  Servlet四大作用域與JSP九大內置對象

    Servlet四大作用域包括:page域、request域、session域、application域,作用域指的是變數的有效期限,具體如下

      當變數的作用域是page,它的有效範圍只在當前jsp頁面里有效;
      當變數的作用域是request,它的有效範圍是當前請求周期,所謂請求周期,就是指從http請求發起,到伺服器處理結束,返迴響應的整個過程,在這個過程中可能使用forward的方式跳轉了多個jsp頁面,在這些頁面里你都可以使用這個變數;
      當變數的作用域是session,它的有效範圍是當前會話,何為當前會話,就是指從用戶打開瀏覽器開始,到用戶關閉瀏覽器的整個過程,這個過程可能包含多個請求響應;
      當變數的作用域是application,它的有效範圍是整個應用,何為整個應用,就是指從應用啟動,到應用結束;

    JSP九大內置對象包括:page、request 、response、pageContext、session、application、out、config、exception,內置對象指的是Servlet容器創建的一組對象,不需使用new關鍵字就可以直接使用的內置對象。

    四大作用域與九大內置對象對應關係如下

    更多詳情需要大家自己去查閱資料了

  EL表達式與JSTL標簽

    我們知道jsp中可以插入Java代碼片段,類似如下

<%pageContext.setAttribute("sex", "男"); %>  <!-- 設置值,作用域是當前jsp頁面 -->
    <div>
        <%=pageContext.getAttribute("sex") %>   <!-- 註意去看解析後的el_jsp.java,被解析成了out.print(pageContext.getAttribute("sex") ); -->
         Welcome, my friend!
    </div>

    其中<% %>包裹的就是java片段,<%= %>輸出表達式值到頁面;可以看到不夠簡潔,閱讀性也不太友好,所以EL表達式就應運而生了,上述代碼可以替換成如下代碼

<%pageContext.setAttribute("sex", "男"); %>  <!-- 設置值,作用域是當前jsp頁面 -->
<div>
         ${sex} Welcome, my friend! <!-- ${expression} EL的語法結構 -->
    </div>

    EL能夠訪問頁面的上下文以及不同作用域中的對象 ,取得對象屬性的值,或執行簡單的運算或判斷操作,用來簡化JSP中的java代碼。EL表達式是JSP1.2之後內置支持的,可以直接在JSP中使用,它從servlet四大作用域(範圍servletContext > session > request > pageContext)中取值,這四個域都有setAttribute("",object)方法和getAttribute("")方法, EL表達式會自動按作用範圍從小到大的順序從四大作用域中尋找對應名字的值,找到了就立即返回不再繼續尋找,其內部調用的就是pageContext的findAttribute("")方法。

    EL固然能簡化JSP中的java代碼,但是它功能非常簡單,不能滿足一些複雜的代碼邏輯,所以就誕生了JSTL。JSP標準標簽庫(JSTL)是一個JSP標簽集合,它封裝了JSP應用的通用核心功能,支持通用的、結構化的任務,比如迭代,條件判斷,XML文檔操作,國際化標簽,SQL標簽,另外還支持自定義標簽,它實現了JSP頁面中的代碼復用、簡化了代碼的書寫,同時也保證了JSP的可讀性更強。JSTL功能比較豐富,但它不是JSP內置支持的,所以需要導入標簽庫到JSP頁面(還要添加jstl的jar包依賴)。JSTL往往會集合EL表達式來使用,簡單示例如下

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!-- 引入JSTL標簽庫,c表示標簽庫別名,可以任意命名,一般而言用c -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>index</title>
</head>
<body>
    <c:set var="sex" value="女" scope="page"></c:set> <!-- scope指定作用域,page/request/session/application -->
    <c:if test="${sex == '男' }">
        Hello, ${sex}
    </c:if>
    <c:if test="${sex != '男' }">
        Hi, girl
    </c:if>
</body>
</html>

    這代碼看起來就清爽多了,沒有java代碼,前端開發者也很容易看懂;關於EL表達式與JSTL標簽更詳細信息,需要大家自行去查閱資料了,本文篇幅有限,不做過多的講解了。

  重定向與請求轉發

    那麼可想而知,重定向的request作用域的變數是會失效的,而轉發則不會

  Spring MVC

    還記得我們是如何配置Spring MVC的嗎, 我們會在web.xml中配置如下代碼

<servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    這樣就配置了Spring MVC;大家可以留意下DispatcherServlet,去看他的類圖會發現,他就是一個Servlet的實現,也就是說Sprinv MVC就是基於Servlet的拓展。

    我們在Spring MVC基礎上進行開發的時候,將數據綁定到作用域的時候,一般用的是SpringMVC的數據模型:Model或者ModelMap,例如這樣

@RequestMapping("/showPerson")
public String showPersons(Model model){
    List<Person> persons = personService.loadPersons();
    model.addAttribute("persons", persons);        // 綁定數據到視圖
    return "showperson";
}

    而不是顯示的直接綁定到Servlet四大作用域,數據難道沒有綁定到四大作用域? 我們說過,EL表達式只能在四大作用域中取值,否則取不到,所以SpringMVC中的數據綁定最終還是會到四大作用域的某一個中,至於是何時、何地、如何將Model中的屬性綁定到哪個作用域,這個不是本文要說的了,篇幅太大了,有機會再重開一篇博客給大家講下,給大家點提示:spring3.2之前去查看AnnotationMethodHandlerAdapter,spring3.2及之後去查看:RequestMappingHandlerAdapter。這裡給個結論:在預設情況下,Model中的屬性作用域是request級別

  問題解答

    有些小伙伴會抱怨了:上面嗶嗶了那麼多,怎麼就是不講答案,凈說一些沒用的

    如果大家堅持看到這了,再堅持會,答案馬上揭曉,上面鋪墊了那麼多,絕對是有用的。

    我們回到問題:當我們請求http://localhost:埠/工程名/personController/showPerson時,數據正常顯示,而當我們直接請求jsp時,只有title卻沒有數據,這是為什麼?title是靜態頁面內容,這個不用管,那為什麼直接請求jsp為什麼沒有資料庫的person列表呢? jsp源代碼如下

<%@ page language="java" contentType="text/html; charset=utf-8"
     pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>person list</title>
    </head>
    <body>
        <table>
            <tr>
                <th>姓名</th>
                <th>年齡</th>
            </tr>
            <c:forEach items="${persons}" var="person">
                <tr>
                    <td>${person.name }</td>
                    <td>${person.age }</td>
                </tr>
            </c:forEach>
        </table>
    </body>
</html>

    裡面用到了<c:forEach>和EL表達式,解釋下這個流程:EL表達式先從四大作用域獲取名為persons的集合,然後<c:forEach>遍歷該集合,每次遍歷的結果放到page作用域,並取名叫person,最後通過EL表達式輸出person的name和age到頁面。那麼請問:直接訪問JSP,四大作用域中有名叫persons的屬性嗎?很顯然沒有,persons不存在,遍歷它會有結果輸出嗎?這就是為什麼直接訪問jsp沒有數據的答案。

    我們再回到Controller層

@RequestMapping("/showPerson")
public String showPersons(Model model){
    List<Person> persons = personService.loadPersons();        // 從數據獲取person列表,並存放到了persons集合中
    model.addAttribute("persons", persons);                    // 將persons集合添加到model的persons屬性中
    return "showperson";                                    // 轉發到showperson.jsp
}

    代碼也非常簡單,先從資料庫獲取person集合,然後將該集合設置到了model的屬性persons中,我們知道model的屬性預設情況下會設置到request作用域;然後將請求轉發到showperson.jsp,轉發過程中,request作用域的變數仍然有效,所以jsp中EL表達式能夠讀取到persons變數,所以就有數據輸出到頁面了。

總結

  1、Servlet與Servlet容器的關係比較曖昧,兩者相互作用,實現web服務;簡單點說,我們自定義的Servlet就是對Servlet容器的業務拓展,而Servlet容器是對Servlet的支撐;

  2、JSP的出現時為了簡化靜態頁面的開發,EL表達式與JSTL的出現則是為了簡化JSP頁面的Java代碼;JSP本質還是Servlet,在第一次被訪問的時候會被Servlet容器解析成Servlet、編譯Servlet,最終還是有Servlet將頁面內容out.write到瀏覽器;

  3、Spring MVC本質還是Servlet,它的出現是為了簡化web開發,同時可以與spring無縫對接,享受spring帶來的好處;Spring MVC的數據綁定,依托的還是Servlet的的四大作用域,只是中間存在轉換過程;

  4、EL表達式的取值必須存在於四大作用域中,在jsp中用EL表達式時,一定要保證數據正確地添加到了四大作用域中,不然,EL表達式會取不到值;

參考

  《深入分析JavaWeb技術內幕》

  《Tomcat 系統架構與模式設計分析》

  Java Web(一) Servlet詳解!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言: 在我們還沒學習框架之前,肯定都學過JDBC。百度百科對JDBC是這樣介紹的【JDBC(Java DataBase Connectivity,java資料庫連接)是一種用於執行SQL語句的Java API,可以為多種關係資料庫提供統一訪問,它由一組用Java語言編寫的類和介面組成。JDBC提供 ...
  • 今天,終於把學習了一年多的《Java核心技術36講》第一遍完結了,歷時一年多,花出去的錢終於感覺有了第一筆回報。 這是我在極客時間的第一門付費課程,剛出來的時候,正巧自己轉到全職Java開發不久,沒怎麼看目錄就入手了這門課,還去幾個微信群宣傳了下。那時候返現意識還不是很高,靠這門課還賺了點小錢。嚴格 ...
  • 定義: 定義: 定義一個用於創建對象的介面,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。 結構:(書中圖,侵刪) 一個工廠的抽象介面 若幹個具體的工廠類 一個需要創建對象的抽象介面 若幹個所需創建的對象的類 較之簡單工廠方法,多了一層抽象——將工廠也抽象了;由原來的一個萬能工廠變 ...
  • 定義: 為其他對象提供一種代理以控制對這個對象的訪問。 結構:(書中圖,侵刪) 一個定義公共方法的介面 一個真實實體 一個含有真實實體引用的代理類 我思考了一下,咱們的科學上網就是一種代理 如上圖,假如要訪問油管,我們需要先將請求發給代理伺服器,由代理伺服器幫我們訪問目標網站。 但是一般這種目標網站 ...
  • 以下圖片是基於自身對知識掌握的基本能力而畫出的,並沒有系統全面的讀過活躍於互聯網大牛的著作(個人認為那樣會限制自身的思維空間),因此,若圖片里存在錯誤,敬請批評指正,謝謝! ...
  • 之前我發過一篇 "《說說我為什麼看好Spring Cloud Alibaba》" ,然後這兩天有網友給我轉了這篇文章 "《坑爹項目spring cloud alibaba,我們也來一個》" ,問我的看法是怎麼樣的,聊天時候簡單說了一下。今天在家休息,抽空整理一下內容,逐點說一下我的看法,主要還是覺得 ...
  • 1、什麼是線程? 2、線程和進程有什麼區別? 3、如何在Java中實現線程? 4、Java關鍵字volatile與synchronized作用與區別? volatile修飾的變數不保留拷貝,直接訪問主記憶體 synchronized用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多只有一個線 ...
  • Redis實現分散式鎖的正確使用方式(java版本) 本文使用第三方開源組件Jedis實現Redis客戶端,且只考慮Redis服務端單機部署的場景。 本篇博客將介紹第二種方式,基於Redis實現分散式鎖。雖然網上已經有各種介紹Redis分散式鎖實現的博客,然而他們的實現卻有著各種各樣的問題,為了避免 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...