過濾器 和 攔截器 6個區別,別再傻傻分不清了_台中搬家

台中搬家公司費用怎麼算?

擁有20年純熟搬遷經驗,提供免費估價且流程透明更是5星評價的搬家公司

本文收錄在個人博客:www.chengxy-nds.top,技術資料共享,同進步

周末有個小夥伴加我微信,向我請教了一個問題:老哥,過濾器 (Filter) 和 攔截器 (Interceptor) 有啥區別啊? 聽到題目我的第一感覺就是:簡單

畢竟這兩種工具開發中用到的頻率都相當高,應用起來也是比較簡單的,可當我準備回復他的時候,竟然不知道從哪說起,支支吾吾了半天,場面炒雞尷尬有木有,工作這麼久一個基礎問題答成這樣,丟了大人了。

平時覺得簡單的知識點,但通常都不會太關注細節,一旦被別人問起來,反倒說不出個所以然來。

歸根結底,還是對這些知識了解的不夠,一直停留在會用的階段,以至於現在一看就會一說就廢!這是典型基礎不紮實的表現,哎·~,其實我也就是個虛胖!

知恥而後勇,下邊結合實踐,更直觀的來感受一下兩者到底有什麼不同?

準備環境

我們在項目中同時配置 攔截器過濾器

1、過濾器 (Filter)

過濾器的配置比較簡單,直接實現Filter 接口即可,也可以通過@WebFilter註解實現對特定URL攔截,看到Filter 接口中定義了三個方法。

  • init() :該方法在容器啟動初始化過濾器時被調用,它在 Filter 的整個生命周期只會被調用一次。注意:這個方法必須執行成功,否則過濾器會不起作用。

  • doFilter() :容器中的每一次請求都會調用該方法, FilterChain 用來調用下一個過濾器 Filter

  • destroy(): 當容器銷毀 過濾器實例時調用該方法,一般在方法中銷毀或關閉資源,在過濾器 Filter 的整個生命周期也只會被調用一次

@Component
public class MyFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        System.out.println("Filter 前置");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("Filter 處理中");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

        System.out.println("Filter 後置");
    }
}

2、攔截器 (Interceptor)

攔截器它是鏈式調用,一個應用中可以同時存在多個攔截器Interceptor, 一個請求也可以觸發多個攔截器 ,而每個攔截器的調用會依據它的聲明順序依次執行。

首先編寫一個簡單的攔截器處理類,請求的攔截是通過HandlerInterceptor 來實現,看到HandlerInterceptor 接口中也定義了三個方法。

  • preHandle() :這個方法將在請求處理之前進行調用。注意:如果該方法的返回值為false ,將視為當前請求結束,不僅自身的攔截器會失效,還會導致其他的攔截器也不再執行。

  • postHandle():只有在 preHandle() 方法返回值為true 時才會執行。會在Controller 中的方法調用之後,DispatcherServlet 返回渲染視圖之前被調用。 有意思的是postHandle() 方法被調用的順序跟 preHandle() 是相反的,先聲明的攔截器 preHandle() 方法先執行,而postHandle()方法反而會後執行。

  • afterCompletion():只有在 preHandle() 方法返回值為true 時才會執行。在整個請求結束之後, DispatcherServlet 渲染了對應的視圖之後執行。

@Component
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("Interceptor 前置");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("Interceptor 處理中");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        System.out.println("Interceptor 後置");
    }
}

將自定義好的攔截器處理類進行註冊,並通過addPathPatternsexcludePathPatterns等屬性設置需要攔截或需要排除的 URL

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");
    }
}

我們不一樣

過濾器 和 攔截器 均體現了AOP的編程思想,都可以實現諸如日誌記錄、登錄鑒權等功能,但二者的不同點也是比較多的,接下來一一說明。

1、實現原理不同

過濾器和攔截器 底層實現方式大不相同,過濾器 是基於函數回調的,攔截器 則是基於Java的反射機制(動態代理)實現的。

這裏重點說下過濾器!

在我們自定義的過濾器中都會實現一個 doFilter()方法,這個方法有一個FilterChain 參數,而實際上它是一個回調接口。ApplicationFilterChain是它的實現類, 這個實現類內部也有一個 doFilter() 方法就是回調方法。

public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

ApplicationFilterChain裏面能拿到我們自定義的xxxFilter類,在其內部回調方法doFilter()里調用各個自定義xxxFilter過濾器,並執行 doFilter() 方法。

public final class ApplicationFilterChain implements FilterChain {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response) {
            ...//省略
            internalDoFilter(request,response);
    }
 
    private void internalDoFilter(ServletRequest request, ServletResponse response){
    if (pos < n) {
            //獲取第pos個filter    
            ApplicationFilterConfig filterConfig = filters[pos++];        
            Filter filter = filterConfig.getFilter();
            ...
            filter.doFilter(request, response, this);
        }
    }
 
}

而每個xxxFilter 會先執行自身的 doFilter() 過濾邏輯,最後在執行結束前會執行filterChain.doFilter(servletRequest, servletResponse),也就是回調ApplicationFilterChaindoFilter() 方法,以此循環執行實現函數回調。

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        filterChain.doFilter(servletRequest, servletResponse);
    }

2、使用範圍不同

我們看到過濾器 實現的是 javax.servlet.Filter 接口,而這個接口是在Servlet規範中定義的,也就是說過濾器Filter 的使用要依賴於Tomcat等容器,導致它只能在web程序中使用。

而攔截器(Interceptor) 它是一個Spring組件,並由Spring容器管理,並不依賴Tomcat等容器,是可以單獨使用的。不僅能應用在web程序中,也可以用於ApplicationSwing等程序中。

3、觸發時機不同

過濾器攔截器的觸發時機也不同,我們看下邊這張圖。

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

台中搬家公司推薦超過30年經驗,首選台中大展搬家

過濾器Filter是在請求進入容器后,但在進入servlet之前進行預處理,請求結束是在servlet處理完以後。

攔截器 Interceptor 是在請求進入servlet后,在進入Controller之前進行預處理的,Controller 中渲染了對應的視圖之後請求結束。

4、攔截的請求範圍不同

在上邊我們已經同時配置了過濾器和攔截器,再建一個Controller接收請求測試一下。

@Controller
@RequestMapping()
public class Test {

    @RequestMapping("/test1")
    @ResponseBody
    public String test1(String a) {
        System.out.println("我是controller");
        return null;
    }
}

項目啟動過程中發現,過濾器的init()方法,隨着容器的啟動進行了初始化。

此時瀏覽器發送請求,F12 看到居然有兩個請求,一個是我們自定義的 Controller 請求,另一個是訪問靜態圖標資源的請求。

看到控制台的打印日誌如下:

執行順序 :Filter 處理中 -> Interceptor 前置 -> 我是controller -> Interceptor 處理中 -> Interceptor 處理后

Filter 處理中
Interceptor 前置
Interceptor 處理中
Interceptor 後置
Filter 處理中

過濾器Filter執行了兩次,攔截器Interceptor只執行了一次。這是因為過濾器幾乎可以對所有進入容器的請求起作用,而攔截器只會對Controller中請求或訪問static目錄下的資源請求起作用。

5、注入Bean情況不同

在實際的業務場景中,應用到過濾器或攔截器,為處理業務邏輯難免會引入一些service服務。

下邊我們分別在過濾器和攔截器中都注入service,看看有什麼不同?

@Component
public class TestServiceImpl implements TestService {

    @Override
    public void a() {
        System.out.println("我是方法A");
    }
}

過濾器中注入service,發起請求測試一下 ,日誌正常打印出“我是方法A”

@Autowired
    private TestService testService;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("Filter 處理中");
        testService.a();
        filterChain.doFilter(servletRequest, servletResponse);
    }
Filter 處理中
我是方法A
Interceptor 前置
我是controller
Interceptor 處理中
Interceptor 後置

在攔截器中注入service,發起請求測試一下 ,竟然TM的報錯了,debug跟一下發現注入的service怎麼是Null啊?

這是因為加載順序導致的問題,攔截器加載的時間點在springcontext之前,而Bean又是由spring進行管理。

攔截器:老子今天要進洞房;
Spring:兄弟別鬧,你媳婦我還沒生出來呢!

解決方案也很簡單,我們在註冊攔截器之前,先將Interceptor 手動進行注入。注意:在registry.addInterceptor()註冊的是getMyInterceptor() 實例。

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Bean
    public MyInterceptor getMyInterceptor(){
        System.out.println("注入了MyInterceptor");
        return new MyInterceptor();
    }
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**");
    }
}

6、控制執行順序不同

實際開發過程中,會出現多個過濾器或攔截器同時存在的情況,不過,有時我們希望某個過濾器或攔截器能優先執行,就涉及到它們的執行順序。

過濾器用@Order註解控制執行順序,通過@Order控制過濾器的級別,值越小級別越高越先執行。

@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class MyFilter2 implements Filter {

攔截器默認的執行順序,就是它的註冊順序,也可以通過Order手動設置控制,值越小越先執行。

 @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").order(3);
    }

看到輸出結果發現,先聲明的攔截器 preHandle() 方法先執行,而postHandle()方法反而會後執行。

postHandle() 方法被調用的順序跟 preHandle() 居然是相反的!如果實際開發中嚴格要求執行順序,那就需要特別注意這一點。

Interceptor1 前置
Interceptor2 前置
Interceptor 前置
我是controller
Interceptor 處理中
Interceptor2 處理中
Interceptor1 處理中
Interceptor 後置
Interceptor2 處理后
Interceptor1 處理后

那為什麼會這樣呢? 得到答案就只能看源碼了,我們要知道controller 中所有的請求都要經過核心組件DispatcherServlet路由,都會執行它的 doDispatch() 方法,而攔截器postHandle()preHandle()方法便是在其中調用的。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
        try {
         ...........
            try {
           
                // 獲取可以執行當前Handler的適配器
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
                // 注意: 執行Interceptor中PreHandle()方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // 注意:執行Handle【包括我們的業務邏輯,當拋出異常時會被Try、catch到】
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
                applyDefaultViewName(processedRequest, mv);

                // 注意:執行Interceptor中PostHandle 方法【拋出異常時無法執行】
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
        }
        ...........
    }

看看兩個方法applyPreHandle()applyPostHandle()具體是如何被調用的,就明白為什麼postHandle()preHandle() 執行順序是相反的了。

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if(!ObjectUtils.isEmpty(interceptors)) {
            for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if(!interceptor.preHandle(request, response, this.handler)) {
                    this.triggerAfterCompletion(request, response, (Exception)null);
                    return false;
                }
            }
        }

        return true;
    }
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if(!ObjectUtils.isEmpty(interceptors)) {
            for(int i = interceptors.length - 1; i >= 0; --i) {
                HandlerInterceptor interceptor = interceptors[i];
                interceptor.postHandle(request, response, this.handler, mv);
            }
        }
    }

發現兩個方法中在調用攔截器數組 HandlerInterceptor[] 時,循環的順序竟然是相反的。。。,導致postHandle()preHandle() 方法執行的順序相反。

總結

我相信大部分人都能熟練使用濾器和攔截器,但兩者的差別還是需要多了解下,不然開發中使用不當,時不時就會出現奇奇怪怪的問題,以上內容比較簡單,新手學習老鳥複習,有遺漏的地方還望大家积極補充,如有理解錯誤之處,還望不吝賜教。

原創不易,燃燒秀髮輸出內容

整理了幾百本各類技術电子書, 送給小夥伴們, 我的同名公眾號自行領取。和一些小夥伴們建了一個技術交流群,一起探討技術、分享技術資料,旨在共同學習進步,如果感興趣就加入我們吧!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

台中搬家公司費用怎麼算?

擁有20年純熟搬遷經驗,提供免費估價且流程透明更是5星評價的搬家公司

OkHttp,一次無奈的使用_網頁設計公司

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

一次使用OKHTTP的心痛歷程

最近由於一些不得已的原因,接觸到了OKHttp,說起來也挺Dan疼的,之前同事將生產附件上傳地址配置成了測試地址,還好數量不多,沒有造成太大的影響,況且的是這位同事又離職了,當時只能在心中
默默的問候了他N遍,當然問候完了之後,也不得不繼續數據同步的工作。

OKHTTP官方地址:okHttp

本文源地址:一次使用OKHTTP的心痛歷程

介紹

由於OkHttp官網的介紹十分詳細,這裏只能貼上一段翻譯過後的introduce:

HTTP是現代應用網絡的一種方式。這就是我們交換數據和媒體的方式。高效地使用HTTP可以讓你的東西更快地加載並節省帶寬。

OkHttp是一個高效的Http客戶端,在默認的情況下:

  • HTTP / 2支持允許對同一主機的所有請求共享一個套接字。
  • 連接池可減少請求延遲(如果HTTP / 2不可用)。
  • 透明的GZIP縮小了下載大小。
  • 響應緩存可以完全避免網絡重複請求。

不過在我使用下來,OkHttp比 apache-http 好用太多,層次結構較直觀。

使用場景

本次場景是將上傳到測試環境的文件信息,下載到本地,然後再上傳到生產環境。

解決過程如下:

  • 將錯誤數據從數據庫表中粘貼到本地新建的一個Excel文件中。(畢竟直接連接數據庫風險更大)

  • 讀取Excel內的信息,獲取文件地址。

  • 請求文件地址,獲取到流文件信息。

  • 拿到流文件信息,拼接上傳數據,上傳到新的生產環境中。

  • 上傳完成后,獲取到生產環境文件地址。

  • 獲取到生產文件地址的同時,生成更新的SQL語句。

  • 到數據庫中執行SQL語句。

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

使用過程

本次使用沒有搭建新的工程,直接再 src/test/java 目錄下新建一個Java類。

引入OKHttp的依賴:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.3.1</version>
</dependency>

在引入了 okhttp 的jar包后,基本上就可以開始隨心所欲的進行自己任意喪心病狂的Http請求了。

比如,它直接同步和異步的請求:

同步GET

  private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url("https://publicobject.com/helloworld.txt")
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      Headers responseHeaders = response.headers();
      for (int i = 0; i < responseHeaders.size(); i++) {
        System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
      }

      System.out.println(response.body().string());
    }
  }

異步GET

 private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();

    client.newCall(request).enqueue(new Callback() {
      @Override public void onFailure(Call call, IOException e) {
        e.printStackTrace();
      }

      @Override public void onResponse(Call call, Response response) throws IOException {
        try (ResponseBody responseBody = response.body()) {
          if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

          Headers responseHeaders = response.headers();
          for (int i = 0, size = responseHeaders.size(); i < size; i++) {
            System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
          }

          System.out.println(responseBody.string());
        }
      }
    });
  }

Header信息

private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url("https://api.github.com/repos/square/okhttp/issues")
        .header("User-Agent", "OkHttp Headers.java")
        .addHeader("Accept", "application/json; q=0.5")
        .addHeader("Accept", "application/vnd.github.v3+json")
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      System.out.println("Server: " + response.header("Server"));
      System.out.println("Date: " + response.header("Date"));
      System.out.println("Vary: " + response.headers("Vary"));
    }
  }

POST請求流信息

public static final MediaType MEDIA_TYPE_MARKDOWN
      = MediaType.parse("text/x-markdown; charset=utf-8");

  private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    RequestBody requestBody = new RequestBody() {
      @Override public MediaType contentType() {
        return MEDIA_TYPE_MARKDOWN;
      }

      @Override public void writeTo(BufferedSink sink) throws IOException {
        sink.writeUtf8("Numbers\n");
        sink.writeUtf8("-------\n");
        for (int i = 2; i <= 997; i++) {
          sink.writeUtf8(String.format(" * %s = %s\n", i, factor(i)));
        }
      }

      private String factor(int n) {
        for (int i = 2; i < n; i++) {
          int x = n / i;
          if (x * i == n) return factor(x) + " × " + i;
        }
        return Integer.toString(n);
      }
    };

    Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(requestBody)
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      System.out.println(response.body().string());
    }
  }

POST請求File信息

  public static final MediaType MEDIA_TYPE_MARKDOWN
      = MediaType.parse("text/x-markdown; charset=utf-8");

  private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    File file = new File("README.md");

    Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      System.out.println(response.body().string());
    }
  }

Post表單提交

 private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    RequestBody formBody = new FormBody.Builder()
        .add("search", "Jurassic Park")
        .build();
    Request request = new Request.Builder()
        .url("https://en.wikipedia.org/w/index.php")
        .post(formBody)
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      System.out.println(response.body().string());
    }
  }

POST多個Body請求

  /**
   * The imgur client ID for OkHttp recipes. If you're using imgur for anything other than running
   * these examples, please request your own client ID! https://api.imgur.com/oauth2
   */
  private static final String IMGUR_CLIENT_ID = "...";
  private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

  private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
    RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("title", "Square Logo")
        .addFormDataPart("image", "logo-square.png",
            RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
        .build();

    Request request = new Request.Builder()
        .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
        .url("https://api.imgur.com/3/image")
        .post(requestBody)
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      System.out.println(response.body().string());
    }
  }

因為使用過程中大多數都是按照官網的例子來進行,所以這次使用的代碼是類似於官方提供的例子,當然也是不太好意思貼出來,哈哈。

總結

OkHttp算得上是相見恨晚,之前一遍一遍寫 apache-http 的時候就覺得 apche 有點冗餘,就是想有一個輕量級的,比較好上手,容易懂的http-client,不過現在接觸到了 okhttp,還是得感謝那位配錯地址的兄弟。

以上更多請求例子可以訪問:OKhttp-Request-example

參考資料:

OkHttp.io

OKhttp-Request-example

OKHttp-Github

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

7.5-15萬不買日系車 上班族首選車型顏值高有格調!_網頁設計公司

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

內飾運動感沒有那麼強烈,整體比較中規中矩,不過,配色上沒有那麼沉悶。福克斯有1。0T 1。5T 1。6L三種動力車型選擇,三種車型配置相差並不算太大,都標配了ESp,剎車輔助,牽引力控制等的配置,每一款動力的車型低配和次低配舒適性的配置稍少了一些,但對於日常使用而言,影響並不大。

如今路上的車輛越來越多,塞車,找不到停車位,已經是習以為常的時。因為這樣,現在不少人會選擇“體型”較小的車型,這樣在路上行駛或者在塞車擠位的時候都比較輕鬆。對於一般的上班族而言,下面這些車型就適合。

上汽大眾-pOLO

指導價:7.59-14.69萬

pOLO的外觀大家也再熟悉不過了,大眾臉配上小“體型”,有一種別樣的規矩感。內飾造型同樣是大眾風,但鋼琴烤漆高亮度面板和鍍鉻飾條,稍微的提升了些檔次感,布局也以實用為主。

pOLO有1.4L,1.6L以及1.4T車型選擇,對於一般用車,1.4T車型的選擇性較低。1.4L車型除了頂配之外都沒有配備ESp,剎車輔助,牽引力控制,這方便比較不就到,舒適配置表現中下,畢竟是8萬的大眾車。1.6L車型低配和次低配車型安全配置較低,舒適性配置比1.4L車型多了幾個,例如,電動天窗,定速巡航等,頂配和次頂配車型有配備ESp,剎車輔助,牽引力控制,舒適性配置也比較齊全。另外,1.4L車型的自動風尚型可以選裝ESp,剎車輔助,牽引力控制。

長安福特-福克斯

指導價:9.98-16.58萬

馬丁臉有較強烈的視覺感,整體的設計運動型較強,對於喜歡有點激情的上班族來說,很適合。內飾運動感沒有那麼強烈,整體比較中規中矩,不過,配色上沒有那麼沉悶。

福克斯有1.0T 1.5T 1.6L三種動力車型選擇,

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

三種車型配置相差並不算太大,都標配了ESp,剎車輔助,牽引力控制等的配置,每一款動力的車型低配和次低配舒適性的配置稍少了一些,但對於日常使用而言,影響並不大。中配車型配置比較齊全,日常使用很足夠,例如,電動天窗,多功能方向盤,后駐車雷達等都有配備。而頂配車型還配備了併線輔助,車道偏離系統,但價格較貴,日常使用,選擇中低配車型就足夠了。

東風標緻-標緻308S

指導價:11.27-17.97萬

不一樣的風情,這是308S給人的第一眼感覺,濃濃的法系味道。內飾顯得比較簡約,但做工依然保持了法系的精緻,看起很有質感,物理按鍵被替代成了觸碰式的,這對操作的實用性有一定的減少。

308S有1.2T 1.6L 1.6T三種動力車型車選擇,1.2T和1.6L的頂配車型配置較為齊全一些,但有些奇怪的是,全系都有配備ESp,剎車輔助,上坡輔助,就是沒有配備牽引力控制,頂配有配備全景天窗但是全系都沒有電動天窗,這算是法系的獨特的風格?中低配車型雖然配置較少,但對於日常使用也還是足夠的,只要你對配置要求不高的話。1.6T車型整體配置算得上齊全,有配備牽引力控制,但還是沒有電動天窗,其他舒適性配置算得上豐富,不過價格就貴了不少,不太推薦。

總結:斯文派的pOLO,激情派的福克斯,時尚派的標誌308S,三種不同風格之選。在價格上,pOLO算上優惠,最低配裸車價可以去到6萬多,而福克斯和308S價格稍微貴一些,但配置上會好很多。總體而言,福克斯各方面比較均衡,價格不高也不低,配置也一樣,對於現在人選車的“理念”而言,比較適合。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

低配高配相差甚遠 怎樣花最少的錢享受到高配置?_網頁設計公司

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

而高配車雖有各種高科技配置,但也帶來了高額的購車成本。所以,如果選了低配車而又不滿意,還有什麼好辦法可以補救下。總結:對於低配車加裝配置,可能在成本上比原高配車要佔優,但要注意的是,無論後期加裝的配置有多先進,總體上跟原高配車的體驗還是會有所不同。

買車除了關心汽車的三大件,配置高低也是必不可少的一項指標。但問題是,真到了選擇高配車和低配車的時候,你會怎麼選?現在的低配車配置寒酸,見不得人,但購買門檻低。而高配車雖有各種高科技配置,但也帶來了高額的購車成本。所以,

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

如果選了低配車而又不滿意,還有什麼好辦法可以補救下?

總結:對於低配車加裝配置,可能在成本上比原高配車要佔優,但要注意的是,無論後期加裝的配置有多先進,總體上跟原高配車的體驗還是會有所不同。因此,在看來,後期加裝配置也要適可而止,要跟自己實際需求掛鈎,切勿盲目貪心的強行增加配置,特別是一些高級配置,更是要慎之又慎,不然,花點錢倒是小事,搞壞了車子才是悲劇。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

最便宜的中型車 13萬國貨或韓系你選誰?_網頁設計公司

自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

動力對比B70搭載兩款發動機。2。0L自然吸氣發動機、1。8T渦輪增壓發動機,最大功率108千瓦、137千瓦,最大扭矩184牛米、235牛米,傳動系統方面,配備的是6擋手動和6擋手自一體,在參數上,B70的整套動力總成,動力還是比較充裕的,無論是買手動還是手自一體車型,穩定性都比較高。

可能在一些朋友眼裡,B級車一直都是20萬出頭,但是你終於不用去湊20萬去買一款B級車了,只要15萬左右的預算就可以買到一款B級車了,而且配置高,顏值高!最近編者的朋友也是握着15W左右的預算想買B級車,就看中了名圖和奔騰B70,問編者怎麼選,下面,就讓我們一起來看看這兩輛車之間如何選擇。

北京現代-名圖

指導價:12.98-17.68萬

一汽奔騰-奔騰B70

指導價:9.98-14.98萬

外觀對比

B70整體延續了家族化的設計風格,以往成熟穩重的造型被一套時尚動感的設計所取代,車身的線條比較圓滑,尾部方面設計簡潔大方,B70採用了雙邊共兩出的排氣管,並配鍍鉻裝飾條,整體視覺感官非常精緻。

名圖在外觀上,看起來並沒有B70那麼運動時尚,而是另外一種商務端莊的范,視覺效果並沒有太大的衝擊,車側與車尾造型之間比較簡潔,流暢,保險杠下緣黑色的塑料處理加上單邊雙出的排氣管,也為該車在穩重之餘增添一絲活力。

內飾對比

B70整體還是走運動時尚路線,中控台的“開口”設計就有些另類,顯得過於浮夸了,但整體的設計還是比較簡潔的,深黑色的內飾配上紅線縫製,更加突顯運動的氛圍。中控台也使用了軟質材料,整體的做工用料還是不錯的。在空間方面,B70還是要比名圖寬敞不少,無論是前排還是後排的的腿部空間的余量還是很大的。在長途乘坐感受上,會比名圖要舒服。

名圖的內飾,比B70的內飾氛圍要高級很多,平直式的中控布局,

綠能、環保無空污,成為 電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

還有大面積的木紋裝飾板點綴,所營造的效果更加沉穩,在儲物空間方面,名圖做的相當到位,手機、錢包。水瓶都能找到放的儲物空間,非常好用。在空間方面,頭部空間比較局促,但是在腿部空間表現相當不錯,翹個二郎腿,都沒什麼問題,符合B級車的水準。

動力對比

B70搭載兩款發動機;2.0L自然吸氣發動機、1.8T渦輪增壓發動機,最大功率108千瓦、137千瓦,最大扭矩184牛米、235牛米,傳動系統方面,配備的是6擋手動和6擋手自一體,在參數上,B70的整套動力總成,動力還是比較充裕的,無論是買手動還是手自一體車型,穩定性都比較高。底盤對路面細微的震動傳遞清晰,整個底盤的調校比較硬朗、偏運動。

名圖搭載了1.8L.2.0L的自然吸氣發動機,1.6T渦輪增壓發動機,最大功率105千瓦、114千瓦、128.7千瓦;最大扭矩176牛米、192牛米、265牛米,在傳動系統方面配備了6擋手動、6擋手自一體、7擋雙離合,可供消費者的選擇很多,就看自己的需求了,在動力上,名圖並不會比B70差,名圖在懸挂和底盤調教上更偏重舒適。對路面的顛簸、起伏路面過濾得更為徹底,無論是前後排的乘坐舒適性都非常不錯。

編者點評:

奔騰B70雖然是自主品牌,但並不會比合資品牌差,而且整體的做工、動力都有很大的提升,性價比也特別高,而名圖呢,可圈可點,整體性也還是不錯,但是看起來商務氣息特別濃,缺乏時尚感,和B70相比,它根本就沒有性價比可談,所以我更推薦奔騰B70,B70更加的親民,喜歡與否就看自己的選擇。汽車圈裡還有這樣的一句話“買韓系車,還不如買自主品牌”。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

疑似 Android 12 的 UI 全新介面設計截圖現身,圖示、通知、Widget 都有改變

離去年 Android 11 發表的時間也快要一年了,沒意外應該這幾個月就有機會看到 Android 12 作業系統,而功能部分先前已經有外媒從開發程式碼中推算,介面設計最近終於也有相關傳聞出現,有人從 Google 早期文件中找到疑似 Android 12 的介面截圖,跟現今 Android 11 可說有蠻大的改變,我個人是蠻喜歡的。

疑似 Android 12 的 UI 全新介面設計截圖現身

根據外媒 XDA-Developers 獲得的消息,稍早有人從 Google 早期文件中提取了 Android 12 新 UI 設計截圖,下圖為新的通知面板,可以看到不再是透明背景,而是改用淺米色替代。每個訊息通知的四個圓角也變更加明顯、且更大,圖示部分也一樣,這也導致能塞入的功能設置數量減少到 4 個:

Android 12 也預計加入跟 iOS 14 一樣的隱私新功能,只要當前有應用程式正使用你手機的相機或麥克風,畫面就會顯示提示,也能點擊它查看是哪一個應用程式:

新的隱私設置頁面,你可以關閉相機、靜音麥克風、管理位置資訊、甚至是停用設備上的感應器等等。不過這似乎只有在啟用 “開發人員選項” 後才會出現:

主畫面的模樣就沒有改變太多:

似乎也加入新的 Widget 小工具功能:

可添加最近的訊息、未接來電或活動狀態的 Widget:

不過好像只有一個大小選擇:

XDA 也補充,他們尚未收到這份完整文件,因此還無法 100% 驗證這些圖片的真實性,不過可以確定的是,來源相當值得信賴。

功能方面,先前 9to5Google 也整理可能會有這 3 項:

  • App Pairs:改進版分割螢幕,讓用戶能更快將兩個常用應用程式組合一起並使用。
  • Columbus:雙擊手機背面可啟用功能操作。
  • hibernate:休眠未使用的應用程式,壓縮檔案來釋出更多儲存空間。

Android 正式推出時間目前還不知道,不過沒意外應該會落在上半年。

資料來源:XDA-Developers

外媒:這 5 個 iPhone 12 特色,Android 應該要學習與複製

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

想不到7.5萬起車型開起來比14萬的車還更爽!

38-11。28萬本田飛度有着“知乎神車”的稱號,原因10萬以內沒能找到一輛這樣低油耗、加速快以及高保值率的合資車。它使用的是1。5L地球夢發動機,最大功率96千瓦,配合5MT手動變速箱,可以實現9s以內的百公里加速時間,另外還有CVT變速箱可以選擇。

前言

“才六七萬錢的車,能開就行了,還要什麼操控樂趣?”,相信這句話是不少人都聽到過的,認為低價位的汽車都是比較無聊的,但是有沒有想過有些六七萬起售的汽車能給到你超越價格的樂趣,甚至要比貴了一倍價錢的車型還要好玩?

小型車,其實是一個被忽略的市場,在國產緊湊型轎車以及小型SUV的轟炸下,合資小型車的市場份額被逐漸蠶食。以前那種合資小型車百花齊放的景象已經看不到了,前些年年輕人都追求的是這種有着絕佳的操控樂趣小車。

它們都有着小巧的車身,在車流中可以非常靈活地穿梭;有着精準的操控,坐在車內有着一種人車合一的感覺;有着極低的重心,即使在山道也能有着較佳的車身姿態。有着類似卡丁車的操控樂趣,而且還有着較高的改裝潛力。

上汽大眾-pOLO

官方指導價:7.59-14.69萬

作為德系的代表,大眾pOLO有着極高的造詣,小巧的車身配合精準的操控,這輛小型車有着超高的駕駛樂趣,較高速度過彎都能有着一個極佳的姿態。所以在不少車隊甚至是大眾官方都是將其作為賽車車型的首選,價格低操控好而且改裝潛力大。

不過對於家庭用戶來說,後排空間就相對局促。動力方面有着1.4L以及1.6L自然吸氣發動機可以選擇,變速箱則是5MT以及6AT變速箱可以選擇,不過更推薦的是5MT,傳動效率高動力佳,而且檔位清晰,離合容易控制,上手難度低。

廣汽本田-飛度

官方指導價:7.38-11.28萬

本田飛度有着“知乎神車”的稱號,原因10萬以內沒能找到一輛這樣低油耗、加速快以及高保值率的合資車。它使用的是1.5L地球夢發動機,最大功率96千瓦,配合5MT手動變速箱,可以實現9s以內的百公里加速時間,另外還有CVT變速箱可以選擇。

它還有着極其優秀的車廂空間,完全不亞於某些合資緊湊型轎車,加上低油耗的特點非常適合家庭使用。動力強以及手感極好的手動變速箱,讓它有着超高的加速性能,不過過彎的時候側傾稍微有點大,但幸好可以通過改裝改善。

長安鈴木-雨燕

官方指導價:5.98-8.28萬

鈴木雨燕是之前小型車大熱時的產物,到如今那麼多年都僅僅是對外觀進行小小的修改,所以有着當初那種最佳的駕駛樂趣,不過也是因為這麼多年都沒有進行性能上的改進而為人所詬病。發動機方面有着1.3L以及1.5L兩種排量可以選擇,1.5L自然吸氣發動機最大功率76千瓦,相對弱勢。

但配合5MT手動變速箱操控極佳,加上優秀的底盤表現以及改裝潛力使得它是第三代飛度之前最熱的改裝車,如今在不少賽車場都可以看到它的蹤影。並且對於某些改裝發燒友來說,可以無損改裝進口速翼特的M16A發動機也是重大的優勢,動力輸出更加,高轉有着極其優秀的表現和魅力。

編輯總結:

以上三款汽車都可以說是這個價位中操控最好的代表,甚至比起12萬左右的合資緊湊型轎車還要優秀。價格基本可以在不到7萬可以買到,尤其是大眾pOLO,終端起售價甚至可以在6.5萬左右,非常適合追求駕駛樂趣的年輕人。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

部分Apple Watch S5、SE發生充電故障 蘋果官方宣布免費維修

近日有部分Apple Watch Series 5、Apple Watch SE的使用者回報,當手錶進入「省電模式」後,就沒有辦法充電,蘋果於16日發布最新的watchOS進行修正,同時也表示,如果仍然無法充電的話,請聯繫蘋果進行維修。

↑部分Apple Watch傳出進入省電模式後,無法充電的故障問題。(示意圖/pixabay)

蘋果今日在官方網站上發文,表示有極小部分的Apple Watch Series 5、Apple Watch SE在執行 watchOS 7.2或7.3版本系統時,當進入「省電模式」後,會發生無法充電的問題。宣布在今日發布最新版作業系統watchOS 7.3.1,表示只要更新到此版系統後,就不會再有這樣的狀況。

而蘋果官方表示,建議原本有問題的Apple Watch Series 5、Apple Watch SE,在更新系統後,先將手表放在常用的充電器上「至少等待30分鐘」,如果還是無法充電的話,可以聯繫蘋果官方進行維修。

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

這有點猛!疑似 M1X 晶片的規格、效能跑分現身國外網站,12 核心 CPU + 16 核心 GPU

搭載 M1X 晶片 MacBook 可說是今年很多蘋果用戶最期待的產品之一,從 M1 來看,雖然已經知道這顆效能絕對不會差到哪去,但究竟有多強悍,相信不少人都想提前知道。而最近國外跑分網站就出現疑似 M1X 晶片的規格表,不僅非常猛,下方甚至還附上跑分比較表,如果是真的,那這顆實在有點誇張。

(圖片來源)

疑似 M1X 晶片的規格、效能跑分現身國外網站

近日國外 CPU Monkey 跑分網站上,出現一筆 Apple M1X 的跑分與規格資料,從下圖可以看到,這顆晶片採 5nm 製程技術,時脈雖然維持在 3.20GHz,但核心數提升到 12 顆,8 顆效能核心 + 4 顆節能核心。GPU 更誇張,核心數直接多一倍,變成 16 核心(M1 為 8 核心)。也有註明推出時間,預計在 2021 年的 Q2:

核心數跟去年底 LeasApplePro 爆料的 12 顆一樣,也增添這表格的可信度:

Next Mac March 12 cores

— LeaksApplePro (@LeaksApplePro) December 31, 2020

下方還有跑分數據圖,多核心相當猛,不過真實性還不知道,所以大家就參考即可,不用太認真看待。

首先是 Cinebench R23 單核心,時脈沒變,也因此分數當然跟 M1 差不多,獲得 1514 的同分表現:

Cinebench R23 多核心就超級猛,比 Ryzen 5700G 和 i9-10900X 還要高,獲得 14450 的分數:

Geekbench 5 64 位元單核心測試,也跟 M1 一樣,獲得 1744 的分數:

iGPU F32 效能測試,跟 M1 相比幾乎快提升一倍,拿下 5200 的超高分數:

如果到時 Apple 端出的 M1X 晶片真是這樣,那今年的新 Mac 看來也必入手不可阿,實在是讓人非常期待。

稍早也有消息指出,3/16 蘋果有可能舉辦春季新品發表會,不過預測新品表似乎沒有 Mac。

資料來源:CPU Monkey

針對 Apple M1 惡意軟體出現,安全自保守好三不

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!

捷豹XF榮獲金方向盤 “最佳轎車”獎

捷豹XF第二代捷豹XF於今年年初發布,提供多種動力系統供消費者選擇,其中包括兩款6缸發動機和多款全新Ingenium系列4缸柴油發動機。其中,163馬力2。0升柴油發動機的二氧化碳排放量僅為104克/公里。搭載380馬力3。0升6缸汽油發動機的車型最高速度可達155英里/小時。
本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

※別再煩惱如何寫文案,掌握八大原則!