Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 中文字幕精品视频在线观,日韩一级视频,男人日女人免费视频

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          SpringMVC 環(huán)境搭建

          右上角【關(guān)注】發(fā)哥微課堂頭條號(hào),get更多相關(guān)技能~


          0x00:示例項(xiàng)目

          以一個(gè)項(xiàng)目示例總結(jié)下 SpringMVC 環(huán)境的搭建基本流程,項(xiàng)目結(jié)構(gòu)如下圖:

          0x01:導(dǎo)入 jar 包

          SpringMVC 主要 jar 包如下圖,需導(dǎo)入到 WEB-INF 下的 lib 目錄。

          0x02:配置前端控制器

          傳統(tǒng)的 servlet 開(kāi)發(fā)中,請(qǐng)求都在 web.xml 中配置,然后配置到對(duì)應(yīng)的 servlet 中。同樣,在 SpringMVC 中,請(qǐng)求也需要配置到對(duì)應(yīng)的 servlet 上,而做配置的就是前端控制器,用于攔截符合配置的 url 請(qǐng)求。在 SpringMVC 中,正是通過(guò)前端控制器 DispatcherServlet 來(lái)對(duì)請(qǐng)求進(jìn)行攔截并處理的。配置 web.xml,示例代碼如下:

          <?xml version="1.0" encoding="UTF-8"?>

          <web-app version="2.5"

          xmlns="http://java.sun.com/xml/ns/javaee"

          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

          <!-- SpringMVC前端控制器 -->

          <servlet>

          <servlet-name>springmvc</servlet-name>

          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

          <init-param>

          <param-name>contextConfigLocation</param-name>

          <param-value>classpath:springmvc.xml</param-value>

          </init-param>

          </servlet>

          <servlet-mapping>

          <servlet-name>springmvc</servlet-name>

          <url-pattern>*.action</url-pattern>

          </servlet-mapping>

          <welcome-file-list>

          <welcome-file>index.jsp</welcome-file>

          </welcome-file-list>

          </web-app>

          配置和 servlet 類(lèi)似,以上配置會(huì)攔截所有以 action 為后綴的請(qǐng)求,交給前端控制器 DispatcherServlet 去處理,定義了 SpringMVC 的核心配置文件為 springmvc.xml。

          0x03:配置處理器映射器

          在 springmvc.xml 配置文件中添加處理器映射器,示例代碼如下:

          <?xml version="1.0" encoding="UTF-8"?>

          <beans xmlns="http://www.springframework.org/schema/beans"

          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"

          xmlns:context="http://www.springframework.org/schema/context"

          xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

          xsi:schemaLocation="http://www.springframework.org/schema/beans

          http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

          http://www.springframework.org/schema/mvc

          http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd

          http://www.springframework.org/schema/context

          http://www.springframework.org/schema/context/spring-context-3.2.xsd

          http://www.springframework.org/schema/aop

          http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

          http://www.springframework.org/schema/tx

          http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

          <!-- 處理器映射器 -->

          <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

          </beans>

          處理器映射器有多種,它們都實(shí)現(xiàn)了 HandlerMapping 接口,示例代碼中用的是 BeanNameUrlHandlerMapping 類(lèi),映射規(guī)則是把 bean 的 name 作為 url 進(jìn)行查找。

          0x04:配置處理器適配器

          由之前的 SpringMVC 工作流程可知,當(dāng)處理器映射器 HandlerMapping 為前端控制器 DispatcherServlet 返回控制器 Handler 后,前端控制器就會(huì)給處理器適配器 HandlerAdapter 去執(zhí)行相關(guān)的 Handler 控制器也就是 Controller。

          處理器適配器也有多種,它們都實(shí)現(xiàn)了 HandlerAdapter 接口,這里使用 SimplerControllerHandlerAdapter 適配器,在 springmvc.xml 中添加以下代碼:

          <!-- 處理器適配器 -->

          <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

          0x05:配置視圖解析器

          當(dāng)處理器適配器處理了相關(guān)的具體方法后,就會(huì)返回一個(gè) ModelAndView 對(duì)象,這個(gè)對(duì)象包含了要跳轉(zhuǎn)的視圖信息 view 和視圖上需要顯示的數(shù)據(jù) model,此時(shí)前端控制器會(huì)請(qǐng)求視圖解析器 ViewResolver 來(lái)解析 ModelAndView 對(duì)象。

          視圖解析器也有很多種,這里使用默認(rèn)的 InternalResourceViewResolver,在 springmvc.xml 中添加以下代碼:

          <!-- 視圖解析器 -->

          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>

          基本配置完成后,既需要配置處理器 Handler 了。

          0x06:配置 Handler 處理器

          因?yàn)樯衔奶幚砥鬟m配器使用的是 SimpleControllerHandlerAdapter,所以這里的 Handler 需要實(shí)現(xiàn) Controller 接口。編寫(xiě)一個(gè)加載水果列表信息的功能,名為 FruitsControllerTest,示例代碼如下:

          package com.fageweiketang.controller;

          import java.util.ArrayList;

          import java.util.List;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import org.springframework.web.servlet.ModelAndView;

          import org.springframework.web.servlet.mvc.Controller;

          import com.fageweiketang.model.Fruits;

          public class FruitsControllerTest implements Controller {

          private FruitsService fruitsService = new FruitsService();

          public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {

          //模擬Service獲取水果商品列表

          List<Fruits> fruitsList = fruitsService.queryFruitsList();

          //返回ModelAndView

          ModelAndView modelAndView = new ModelAndView();

          //相當(dāng)于request的setAttribut,在jsp頁(yè)面通過(guò)fruitsList獲取數(shù)據(jù)

          modelAndView.addObject("fruitsList", fruitsList);

          //指定視圖

          modelAndView.setViewName("/WEB-INF/jsp/fruits/fruitsList.jsp");

          return modelAndView;

          }

          //模擬Service的內(nèi)部類(lèi)

          class FruitsService{

          public List<Fruits> queryFruitsList(){

          List<Fruits> fruitsList = new ArrayList<Fruits>();

          Fruits apple = new Fruits();

          apple.setName("蘋(píng)果");

          Fruits banana = new Fruits();

          apple.setName("香蕉");

          Fruits pear = new Fruits();

          apple.setName("梨");

          fruitsList.add(apple);

          fruitsList.add(banana);

          fruitsList.add(pear);

          return fruitsList;

          }

          }

          }

          示例中查詢到列表信息后創(chuàng)建了一個(gè) ModelAndView,將需要傳遞的數(shù)據(jù)通過(guò) ModelAndView 綁定到了對(duì)象中。又通過(guò) setViewName 方法指定了要跳轉(zhuǎn)的頁(yè)面。

          0x07:編寫(xiě)實(shí)體類(lèi)代碼

          實(shí)體類(lèi)很簡(jiǎn)單,一個(gè) get 和 set 方法即可,示例代碼如下:

          package com.fageweiketang.model;

          public class Fruits {

          private String name;

          public String getName() {

          return name;

          }

          public void setName(String name) {

          this.name = name;

          }

          }

          0x08:編寫(xiě)視圖頁(yè)面

          最后在 / WEB-INF/jsp/fruits 路徑下創(chuàng)建 fruitsList.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=UTF-8">

          <title>水果列表</title>

          </head>

          <body>

          <h3>水果列表</h3>

          <table width="300px;" border=1>

          <c:forEach items="${fruitsList }" var="fruit">

          <tr>

          <td>${fruit.name }</td>

          </tr>

          </c:forEach>

          </table>

          </body>

          </html>

          因?yàn)?springmvc.xml 中配置的處理器映射器是 BeanNameUrlHandlerMapping,在接收請(qǐng)求時(shí),會(huì)將 bean 的 name 作為 url 進(jìn)行查找,所以最后需要在 springmvc.xml 中配置一個(gè)可以被 url 映射的 Handler 的 bean,配置示例如下:

          <bean name="/queryFruits.action" class="com.fageweiketang.controller.FruitsControllerTest"/>

          啟動(dòng) tomcat 服務(wù)器,訪問(wèn) localhost/SpringMVC/queryFruits.action,結(jié)果如下:

          “愛(ài)讀書(shū)”--給你講技術(shù)》,我來(lái)看書(shū),你來(lái)進(jìn)步,讓我們開(kāi)始吧!

          本書(shū)簡(jiǎn)介

          書(shū)名為《Spring+MyBatis企業(yè)應(yīng)用實(shí)戰(zhàn)》,是本人在學(xué)習(xí)JavaEE框架時(shí)候的一本基礎(chǔ)書(shū)籍,本書(shū)對(duì)于SpringMVC和MyBatis框架及相關(guān)基礎(chǔ)知識(shí)講述的比較清晰,適合需要詳細(xì)學(xué)習(xí)Java框架的讀者。

          本文內(nèi)容為本書(shū)第二章--第八章,記錄和總結(jié)了所有SpringMVC的知識(shí)

          DispatcherServlet

          1.DispatcherServlet使用和配置

          SpringMVC提供了一個(gè)名為org.springframework.web.servlet.DispatcherServlet的Servlet充當(dāng)前端控制器,所有請(qǐng)求驅(qū)動(dòng)都圍繞這個(gè)DispatcherServlet來(lái)分配請(qǐng)求。DispatcherServlet是一個(gè)Servlet類(lèi),需要在web.xml中完成配置。

          (1)配置了啟動(dòng)時(shí)立即加載Servlet

          (2)需要配置springmvc-config.xml配置文件

          (3)配置了用當(dāng)前servlet處理所有請(qǐng)求URL

          2.DispatcherServlet的分發(fā)原理

          先看一下DispatcherServlet源碼中的方法

          源碼如下:

          initStrategies方法將在WebApplicationContext初始化后自動(dòng)執(zhí)行,自動(dòng)掃描上下文的Bean,根據(jù)名稱(chēng)或類(lèi)型匹配機(jī)制查找自定義的組件。如果沒(méi)有找到則會(huì)裝配一套默認(rèn)組件,默認(rèn)組件在DispatcherServlet.properties配置文件中。

          配置文件如下:

          如 果開(kāi)發(fā)者希望使用自定義類(lèi)型的組件,則只需要在Spring配置文件中配置自定義的Bean即可。MVC如果發(fā)現(xiàn)上下文中有用戶自定義的組件,就不會(huì)使用默認(rèn)組件。

          SpringMVC開(kāi)發(fā)步驟

          1.在web.xml中定義前端控制器DispatcherServlet來(lái)攔截用戶請(qǐng)求

          2.定義處理用戶請(qǐng)求的Handle類(lèi),可以實(shí)現(xiàn)Controller接口或使用@Controller注解

          3.配置Handle,可采用xml文件或注解的方式

          <!-- 配置Handle,映射/hello請(qǐng)求 -->
          <bean name="/hello" class="org.fkit.controller.HelloController"/>
          @Controller
          public class HelloController{
              @RequestMapping(value="/hello")
              public ModelAndView hello(){
              }
          }

          4.編寫(xiě)視圖資源,Handle處理用戶請(qǐng)求結(jié)束后,通常會(huì)返回一個(gè)ModelAndView對(duì)象,該對(duì)象包含返回的試圖名和模型。試圖名代表需要顯示的物理視圖資源;模型用于傳輸數(shù)據(jù)給視圖資源。

          SpringMVC執(zhí)行流程

          說(shuō)明如下:

          (1)用戶向服務(wù)器發(fā)送請(qǐng)求,請(qǐng)求被Spring的前端控制器DispatcherServlet截獲

          (2)DispatcherServlet對(duì)請(qǐng)求URL進(jìn)行解析,得到URI。然后根據(jù)URI,調(diào)用HandlerMapping獲得該Handler配置的所有相關(guān)對(duì)象,包括Handler對(duì)象以及Handler對(duì)象對(duì)應(yīng)的攔截器,會(huì)被封裝到一個(gè)HandlerExecutionChain對(duì)象中返回

          (3)DispatcherServlet根據(jù)獲得的Handler,選擇一個(gè)HandlerAdapter。HandlerAdapter會(huì)被用于處理多種Handler,調(diào)用Handler實(shí)際處理請(qǐng)求的方法

          (4)提取請(qǐng)求中的模型數(shù)據(jù),開(kāi)始執(zhí)行Handler。在填充Handler的入?yún)⑦^(guò)程中,根據(jù)配置spring會(huì)幫你實(shí)現(xiàn)消息轉(zhuǎn)換、數(shù)據(jù)轉(zhuǎn)換、數(shù)據(jù)格式化、數(shù)據(jù)驗(yàn)證

          (5)Handler執(zhí)行完成后,向DispatcherServlet返回一個(gè)ModelAndView對(duì)象。ModelAndView對(duì)象中包含試圖名和模型

          (6)根據(jù)返回的ModelAndView對(duì)象,選擇一個(gè)ViewResolver返回給DispatcherServlet

          (7)ViewResolver結(jié)合Model和View來(lái)渲染視圖

          (8)將試圖渲染結(jié)果返回給客戶端

          SpringMVC常用注解

          1.@Controller注解

          @Controller用于標(biāo)記一個(gè)類(lèi),使用它標(biāo)記的類(lèi)就是一個(gè)Controller對(duì)象,及一個(gè)控制器。Spring使用掃描機(jī)制查找應(yīng)用中所有基于注解的控制器類(lèi)。

          @Controller
          public class HelloController{
              @RequestMapping(value="/hello")
              public ModelAndView hello(){
              }
          }

          使用注解前需要如下步驟

          • 在SpringMVC配置文件的頭中引入spring-context
          • 使用<context:component-scan/>元素,功能是:?jiǎn)?dòng)包掃描功能,以便注冊(cè)帶有@Controller、@Service、@Repository、@Component等注解的類(lèi)成為Bean。base-package指定了需要掃描的類(lèi)包,類(lèi)包及其遞歸子包中的所有類(lèi)都會(huì)被掃描。配置如下:
          <context:component-scan base-package="org.fkit.controller"/>

          springmvc-config.xml常用配置

          說(shuō)明如下:

          (1)使用<context:component-scan>指定需要掃描的包

          (2)<mvc:annotation-driven>會(huì)自動(dòng)注冊(cè)RequestMappingHandlerMapping和Request MappingHandlerAdapter兩個(gè)Bean,提供注解的必要支持

          (3)<mvc:default-servlet-handler>是靜態(tài)資源處理器,SpringMVC會(huì)默認(rèn)捕獲所有請(qǐng)求,包括靜態(tài)資源請(qǐng)求。配置了當(dāng)前元素后靜態(tài)資源不會(huì)被DispatcherServlet處理

          (4)視圖解析器InternalResourceViewResolver來(lái)解析視圖,將View呈現(xiàn)給用戶。配置的prefix屬性表示視圖的前綴,suffix表示視圖的后綴。

          2.@RequestMapping注解

          @RequestMapping注解可以用來(lái)注釋一個(gè)控制器類(lèi),所有方法都將映射為相對(duì)于類(lèi)級(jí)別的請(qǐng)求,表示該控制器處理的所有請(qǐng)求都被映射到value屬性所指示的路徑下。

          上圖代表映射到如下路徑:

          http://localhost:8080/user/register
          http://localhost:8080/user/login

          常用屬性如下:

          3.請(qǐng)求處理方法可出現(xiàn)的參數(shù)類(lèi)型

          所有參數(shù)Spring會(huì)自動(dòng)將值傳給方法

          (1)HttpServletRequest參數(shù)

          (2)HttpSession參數(shù)

          (3)HttpServletResponse

          (4)InputStream

          (5)OutputStream

          (6)Map

          (7)Model

          (8)ModelMap

          (9)BindingResult

          (10)WebRequest

          4.請(qǐng)求處理方法可返回的類(lèi)型

          • ModelAndView
          • Model
          • Map
          • View
          • String

          下面做一些詳細(xì)說(shuō)明。

          (1)Model和ModelMap

          SpringMVC在調(diào)用處理方法之前會(huì)創(chuàng)建一個(gè)隱含的模型對(duì)象,作為模型數(shù)據(jù)的存儲(chǔ)容器。如果處理方法的參數(shù)為Model或ModelMap類(lèi)型,則SpringMVC會(huì)將隱含模型的引用傳遞給這些參數(shù)。在處理方法內(nèi)部,開(kāi)發(fā)者可以通過(guò)這個(gè)參數(shù)對(duì)象訪問(wèn)模型中的所有數(shù)據(jù),也可以向模型中添加新的數(shù)據(jù)。

          (2)ModelAndView

          控制器處理方法的返回值如果是ModelAndView,則既包含模型數(shù)據(jù),也包含視圖信息。

          常用方法如下:

          //添加模型數(shù)據(jù)
          addObject(String key, Object value);
          //設(shè)置視圖
          setViewName(String name);

          5.頁(yè)面轉(zhuǎn)發(fā)

          (1)轉(zhuǎn)發(fā)到JSP

          //默認(rèn)forward跳轉(zhuǎn)
          return "main";
          modelAndView.setViewName("main");
          //重定向頁(yè)面
          return "redirect:/main.jsp";
          modelAndView.setViewName("redirect:/main.jsp");

          (2)轉(zhuǎn)發(fā)到其他處理方法

          //forward跳轉(zhuǎn)
          return "forward:/main";
          modelAndView.setViewName("forward:/main");
          //重定向
          return "redirect:/main";
          modelAndView.setViewName("redirect:/main");

          6.@RequestParam注解

          @RequestParam用于將指定的請(qǐng)求參數(shù)賦值給方法中的形參。屬性如下:

          name:指定請(qǐng)求參數(shù)綁定的名稱(chēng)
          value:name屬性的別名
          required:指定參數(shù)是否必須綁定
          defaultValue:指定默認(rèn)值

          7.@PathVariable注解

          @PathVariable可以方便的獲得請(qǐng)求URL中的動(dòng)態(tài)參數(shù)。屬性如下:

          舉例如下:

          @RequestMapping(value="/pathVariableTest/{userId}")
          public void pathVariableTest(@PathVariable Integer userId)

          假如請(qǐng)求的URL為http://localhost:8080/pathVariableTest/1,則自動(dòng)將URL中模板變量{userId}綁定到通過(guò)@PathVariable注解的同名參數(shù)上,即userId變量將被賦值為1。

          8.@RequestHeader注解

          @RequestHeader注解用于將請(qǐng)求頭信息數(shù)據(jù)映射到功能處理方法的參數(shù)上。屬性如下:

          舉例如下:

          9.@CookieValue注解

          @CookieValue注解用于將請(qǐng)求的Cookie數(shù)據(jù)映射到功能處理方法的參數(shù)上。屬性如下:

          舉例如下:

          10.@RequestAttribute注解

          @RequestAttribute注解用于訪問(wèn)由請(qǐng)求處理方法、過(guò)濾器或攔截器創(chuàng)建的、預(yù)先存在于request作用域中的屬性,將該屬性轉(zhuǎn)換到目標(biāo)方法的參數(shù)。屬性如下:

          舉例如下:

          11.@SessionAttribute注解

          @SessionAttribute注解用于訪問(wèn)由請(qǐng)求處理方法、過(guò)濾器或攔截器創(chuàng)建的、預(yù)先存在于session作用域中的屬性,將該屬性轉(zhuǎn)換到目標(biāo)方法的參數(shù)。屬性如下:

          舉例如下:

          12.@ModelAttribute注解

          @ModelAttribute注解用于將請(qǐng)求參數(shù)綁定到對(duì)象。

          舉例如下:

          Form請(qǐng)求的參數(shù)值會(huì)自動(dòng)入?yún)⒌紷ModelAttribute注解的對(duì)象的同名屬性中

          13.@RequestBody注解

          @RequestBody注解用來(lái)處理content-type類(lèi)型為:application/json或application/xml的情況,將請(qǐng)求數(shù)據(jù)綁定到方法參數(shù)上。

          舉例如下:

          其中前臺(tái)向處理方法傳遞了Json格式的數(shù)據(jù),Json數(shù)據(jù)的key和Book屬性相對(duì)應(yīng)

          14.@ResponseBody注解

          @ResponseBody注解用于將請(qǐng)求處理方法返回的對(duì)象,轉(zhuǎn)換為指定格式后,寫(xiě)入到Response對(duì)象的body中。返回的數(shù)據(jù)不是HTML頁(yè)面,而是其他格式數(shù)據(jù),如JSON、XML時(shí)使用注解。

          舉例如下:

          上圖將List轉(zhuǎn)換為Json格式輸出

          15.@RestController注解

          @RestController注解相當(dāng)于同時(shí)使用了@Controller和@ResponseBody。用于RESTFUL風(fēng)格的請(qǐng)求處理方式。

          SpringMVC異常處理

          SpringMVC提供的兩種異常處理方式:

          • 使用異常處理器SimpleMappingExceptionResolver,類(lèi)有如下方法:
          //該方法處理程序執(zhí)行期間被拋出的異常,返回一個(gè)模型和視圖,視圖返回錯(cuò)誤處理頁(yè)面
          ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response)

          通過(guò)springmvc-config.xml配置實(shí)現(xiàn)

          <!-- p:defaultErrorView="error"表示所有沒(méi)有指定的異常都跳轉(zhuǎn)到異常處理頁(yè)面error
               p:exceptionAttribute="ex"表示異常處理頁(yè)面中訪問(wèn)的異常對(duì)象變量名為ex -->
          <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
                p:defaultErrorView="error" p:exceptionAttribute="ex">
                <!-- exceptionMappings表示映射的異常,接受參數(shù)是一個(gè)Properties,key是異常類(lèi)名,value是處理異常的頁(yè)面 -->
                <property name="exceptionMappings">
                    <props>
                        <prop key="IOException">ioerror</prop>
                        <prop key="SQLException">sqlerror</prop>
                   </props>
               </property>
          </bean>
          • 使用@ExceptionHandler注解實(shí)現(xiàn)局部異常處理

          @ExceptionHandler注解只在當(dāng)前類(lèi)生效

          • 使用@ControllerAdvice注解實(shí)現(xiàn)全局異常處理

          使用<context:component-scan>掃描到@ControllerAdvice注解后,會(huì)將注解修飾的類(lèi)內(nèi)部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法應(yīng)用到所有請(qǐng)求的異常處理上。

          SpringMVC國(guó)際化

          1.messageSource接口

          SpringMVC不直接使用java.util.ResourceBundle,而是使用messageSource的Bean來(lái)配置國(guó)際化屬性文件。

          上圖basenames指定了資源文件的名稱(chēng)

          2.localeResolver接口

          SpringMVC使用語(yǔ)言區(qū)域解析器來(lái)實(shí)現(xiàn)用戶選擇語(yǔ)言區(qū)域。提供了一個(gè)語(yǔ)言區(qū)域解析器接口LocaleResolver,實(shí)現(xiàn)類(lèi)包括:

          • AcceptHeaderLocaleResolver
          • SessionLocaleResolver
          • CookieLocaleResolver

          AcceptHeaderLocaleResolver是默認(rèn)解析器,會(huì)讀取瀏覽器accept-language標(biāo)題,來(lái)確定使用哪個(gè)語(yǔ)言區(qū)域

          3.message標(biāo)簽

          SpringMVC顯示本地化消息使用message標(biāo)簽,使用前需先導(dǎo)入taglib標(biāo)簽庫(kù)。

          <%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>

          message標(biāo)簽屬性如下:

          4.AcceptHeaderLocaleResolver

          實(shí)現(xiàn)步驟:

          (1)創(chuàng)建資源文件

          message_en_US.properties

          message_zh_CN.properties

          (2)在JSP中使用message標(biāo)簽輸出國(guó)際化消息

          (3)在SpringMVC配置文件中加載國(guó)際化資源文件并配置

          (4)可在controller中使用國(guó)際化

          RequestContext requestContext = new RequestContext(request);
          String username = requestContext.getMessage("username");

          SpringMVC數(shù)據(jù)轉(zhuǎn)換、格式化、校驗(yàn)原理

          Spring MVC框架將ServletRequest對(duì)象及處理方法的參數(shù)對(duì)象傳遞給DataBinder,DataBinder調(diào)用ConversionService組件進(jìn)行數(shù)據(jù)類(lèi)型轉(zhuǎn)換、數(shù)據(jù)格式化工作,并將ServletRequest中的消息填充到參數(shù)對(duì)象中。然后再調(diào)用Validator組件對(duì)已經(jīng)綁定了請(qǐng)求消息數(shù)據(jù)的參數(shù)對(duì)象進(jìn)行數(shù)據(jù)合法性校驗(yàn),并最終生成 數(shù)據(jù)綁定結(jié)果BindingResult 對(duì)象。

          SpringMVC文件上傳

          實(shí)現(xiàn)步驟:

          (1)創(chuàng)建表單并設(shè)置為multipart/form-data

          (2)創(chuàng)建controller

          SpringMVC會(huì)將上傳文件綁定到MultipartFile對(duì)象。MultipartFile提供了獲取上傳文件內(nèi)容、文件名等方法。

          MultipartFile常用方法如下:

          byte[] getBytes():獲取文件數(shù)據(jù)
          String getContentType():獲取文件MIME類(lèi)型,如image/jpeg
          InputStream getInputStream():獲取文件流
          String getName(): 獲取表單中文件組件的名稱(chēng)
          String getOriginalFilename():獲取上傳文件的原名
          long getSize(): 獲取文件的字節(jié)大小,單位為byte
          boolean isEmpty(): 是否有上傳的文件
          void transferTo(File file):將上傳文件保存到一個(gè)目標(biāo)文件中

          (3)在SpringMVC配置文件中增加文件上傳功能(配置MultipartResolver)

          CommonsMultipartResolver必須依賴(lài)于Apach FileUpload組件,需要引入JAR包

          SpringMVC文件下載

          實(shí)現(xiàn)步驟:

          (1)在頁(yè)面中加入下載超鏈接,鏈接地址指向controller方法

          (2)編寫(xiě)controller處理方法,用于文件下載

          使用Apache FileUpload組件FileUtils讀取要下載的文件,并將其構(gòu)建成ResponseEntity對(duì)象返回。ResponseEntity對(duì)象可以方便的定義返回的BodyBuilder、HttpHeaders、HttpStatus。

          BodyBuilder對(duì)象用來(lái)構(gòu)建返回的Body

          HttpHeaders代表Http協(xié)議頭信息

          HttpStatus代表Http協(xié)議的狀態(tài)

          SpringMVC攔截器

          Interceptor攔截器的主要作用是攔截用戶的請(qǐng)求并進(jìn)行相應(yīng)的處理(比如通過(guò)攔截器來(lái)進(jìn)行用戶權(quán)限驗(yàn)證,或者用來(lái)判斷用戶是否已經(jīng)登錄等)

          1.HandlerInterceptor接口

          定義攔截器類(lèi)需要實(shí)現(xiàn)HandlerInterceptor接口或繼承抽象類(lèi)HandlerInterceptorAdapter

          接口中的方法如下:

          //該方法在請(qǐng)求處理之前被調(diào)用,可以做前置的初始化操作或者是對(duì)當(dāng)前請(qǐng)求的一個(gè)預(yù)處理,也可以判斷來(lái)請(qǐng)求是否要繼續(xù)進(jìn)行下去。當(dāng)返回值為false,表示請(qǐng)求結(jié)束,后續(xù)的Interceptor和Controller不會(huì)再執(zhí)行;當(dāng)返回值為true澤會(huì)繼續(xù)執(zhí)行
          boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
          //該方法在controller方法被執(zhí)行,在視圖返回渲染前被調(diào)用。可以在這個(gè)方法中對(duì)處理后的ModelAndView進(jìn)行操作
          void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv)
          //該方法將在整個(gè)請(qǐng)求結(jié)束后執(zhí)行,作用是進(jìn)行資源清理
          void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)

          實(shí)現(xiàn)步驟:

          (1)定義攔截器類(lèi),實(shí)現(xiàn)接口和接口中的方法

          (2)在配置文件中配置攔截器(springmvc-config.xml)

          起HTML標(biāo)簽,前端工程師會(huì)非常的有發(fā)言權(quán),因?yàn)樵谄綍r(shí)開(kāi)發(fā)中一定會(huì)用到,可以說(shuō)是前端的入門(mén)必備知識(shí)。但往往在意更多的是頁(yè)面的渲染效果及交互方式,也就是頁(yè)面可見(jiàn)的部分,比如導(dǎo)航欄,菜單欄,列表,圖文等。


          其實(shí)還有一些頁(yè)面上沒(méi)有呈現(xiàn)出來(lái)卻非常重要的標(biāo)簽,這些標(biāo)簽大部分在頁(yè)面的頭部head標(biāo)簽內(nèi),雖然在頁(yè)面上看不見(jiàn)摸不著,但如果在特定的場(chǎng)景下,會(huì)產(chǎn)生意想不到的效果。下面我將從交互優(yōu)化,性能優(yōu)化,搜索優(yōu)化三個(gè)方面并結(jié)合場(chǎng)景來(lái)聊聊被“忽視”的HTML標(biāo)簽。


          交互優(yōu)化

          meta 標(biāo)簽:自動(dòng)跳轉(zhuǎn)/刷新

          假設(shè)要實(shí)現(xiàn)一個(gè)類(lèi)似自動(dòng)播放的頁(yè)面,首先我們第一反應(yīng)會(huì)想到用js定時(shí)器控制頁(yè)面跳轉(zhuǎn)來(lái)完成。但是其實(shí)有更加簡(jiǎn)便的方法,通過(guò)meta標(biāo)簽的refresh功能來(lái)實(shí)現(xiàn)。

          <meta http-equiv="refresh" content="10; url=view2.html">

          上面的代碼會(huì)在 10s 之后自動(dòng)跳轉(zhuǎn)到同域下的 view2.html 頁(yè)面。我們要實(shí)現(xiàn)自動(dòng)播放的功能,只需要在每個(gè)頁(yè)面的 meta 標(biāo)簽內(nèi)設(shè)置好下一個(gè)頁(yè)面的地址即可。


          如果要實(shí)現(xiàn)定時(shí)刷新的功能,只要去除后面url即可:

          <meta http-equiv="refresh" content="10">

          注意,用meta標(biāo)簽實(shí)現(xiàn)刷新/跳轉(zhuǎn)的過(guò)程是不可取消的,所以需要手動(dòng)取消的還是得老老實(shí)實(shí)使用js的定時(shí)器,但是對(duì)于簡(jiǎn)單的定時(shí)刷新或跳轉(zhuǎn),還是可以去親自實(shí)踐meta的用法。


          title 標(biāo)簽:消息提醒

          消息提醒功能實(shí)現(xiàn)在HTML5標(biāo)準(zhǔn)發(fā)布之前,瀏覽器還沒(méi)有開(kāi)放圖標(biāo)閃爍、音頻播放,彈出系統(tǒng)消息之類(lèi)的api,只能借助其他非常規(guī)的手段,比如修改title 標(biāo)簽來(lái)達(dá)到類(lèi)似的效果。


          下面的代碼通過(guò)定時(shí)修改title標(biāo)簽的內(nèi)容,實(shí)現(xiàn)了消息提醒的功能,可以讓用戶在瀏覽其他頁(yè)面時(shí)候,及時(shí)發(fā)現(xiàn)服務(wù)端返回的消息。

          let messageNum = 1; // 消息條數(shù)
          let count = 0; // 計(jì)數(shù)器
          const msgInterval = setInterval(() => {
            count = (count + 1) % 2;
          if(messageNum === 0) {
          // 通過(guò)DOM修改title
          document.title += `當(dāng)前頁(yè)面`;
              clearInterval(msgInterval);
          return;
            }
          const pre = count % 2 ? `新消息(${msgNum})` : '';
          document.title = `${pre}當(dāng)前頁(yè)面`;
          }, 1000);

          當(dāng)然,動(dòng)態(tài)修改title標(biāo)簽的用途不僅僅是消息提醒,還可以顯示一些異步進(jìn)行的任務(wù),比如下載進(jìn)度,上傳進(jìn)度等。


          性能優(yōu)化

          script 標(biāo)簽:調(diào)整加載順序提升渲染速度

          不知道你們有沒(méi)有過(guò)這樣的體驗(yàn):當(dāng)在瀏覽器打開(kāi)某個(gè)頁(yè)面時(shí),發(fā)現(xiàn)頁(yè)面一直在loading轉(zhuǎn)圈,或者等了好長(zhǎng)的時(shí)間頁(yè)面才有響應(yīng)。這一現(xiàn)象,除了網(wǎng)絡(luò)網(wǎng)速的原因外,大多數(shù)都是由于頁(yè)面結(jié)構(gòu)設(shè)計(jì)不合理導(dǎo)致加載時(shí)間過(guò)長(zhǎng)。因此,如果想要提升頁(yè)面的渲染速度,就需要了解瀏覽器頁(yè)面的渲染過(guò)程是怎樣的,從根本上來(lái)解決問(wèn)題。


          瀏覽器在加載頁(yè)面的時(shí)候會(huì)用到 GUI 渲染線程和 JavaScript 引擎線程。其中,GUI 渲染線程負(fù)責(zé)渲染瀏覽器界面 HTML 元素,JavaScript 引擎線程主要負(fù)責(zé)處理 JavaScript 腳本程序。由于 JavaScript 在執(zhí)行過(guò)程中還可能會(huì)改動(dòng)界面結(jié)構(gòu)和樣式,因此它們之間被設(shè)計(jì)為互斥的關(guān)系。也就是說(shuō),當(dāng) JavaScript 引擎執(zhí)行時(shí),GUI 線程會(huì)被掛起,等執(zhí)行完 JavaScript 的腳本程序后又會(huì)切換 GUI 線程繼續(xù)渲染頁(yè)面。


          所以我們可以知道頁(yè)面渲染過(guò)程中包含了請(qǐng)求腳本文件以及執(zhí)行腳本文件的時(shí)間,但頁(yè)面的首次渲染可能并不需要執(zhí)行完全部的文件,這些請(qǐng)求和執(zhí)行文件的動(dòng)作反而延長(zhǎng)了用戶看到頁(yè)面的時(shí)間,從而降低了用戶體驗(yàn)。


          為了快速將內(nèi)容呈現(xiàn)給用戶,減少用戶等待時(shí)間,可以借助script標(biāo)簽的3個(gè)屬性來(lái)實(shí)現(xiàn):

          async:表示立即請(qǐng)求腳本文件,但不阻塞 GUI 渲染引擎,而是文件加載完畢后阻塞 GUI 渲染引擎并立即執(zhí)行文件內(nèi)容。

          defer。立即請(qǐng)求腳本腳本,但不阻塞 GUI 渲染引擎,等到解析完 HTML 之后再執(zhí)行文件內(nèi)容。

          HTML5 標(biāo)準(zhǔn) type,對(duì)應(yīng)值為“module”。讓瀏覽器按照 ECMA Script 6 標(biāo)準(zhǔn)將文件當(dāng)作模塊進(jìn)行解析,默認(rèn)阻塞效果同 defer,也可以配合 async 在請(qǐng)求完成后立即執(zhí)行。


          所以可以得知,采用defer 屬性以及 type="module" 情況下能保證渲染引擎的優(yōu)先執(zhí)行,從而減少執(zhí)行文件內(nèi)容消耗的時(shí)間,讓用戶更快地看見(jiàn)頁(yè)面(即使這些頁(yè)面內(nèi)容可能并沒(méi)有完全地顯示)。除此外還要知道,當(dāng)渲染引擎解析 HTML 遇到 script 標(biāo)簽引入文件時(shí),會(huì)立即進(jìn)行一次渲染,這就是為什么會(huì)把引用JavaScript 代碼的 script 標(biāo)簽放入到 body 標(biāo)簽底部。


          link 標(biāo)簽:通過(guò)預(yù)處理提升渲染速度

          在我們對(duì)中大型項(xiàng)目進(jìn)行性能優(yōu)化時(shí),往往會(huì)對(duì)資源做減法(gzip壓縮,緩存等)或除法(按需打包,按需加載),可是如果能想到 link 標(biāo)簽的 rel 屬性值來(lái)進(jìn)行預(yù)加載,也能加快頁(yè)面的渲染速度。

          dns-prefetch。當(dāng) link 標(biāo)簽的 rel 屬性值為“dns-prefetch”時(shí),瀏覽器會(huì)對(duì)某個(gè)域名預(yù)先進(jìn)行 DNS 解析并緩存。這樣,當(dāng)瀏覽器在請(qǐng)求同域名資源的時(shí)候,能省去從域名查詢 IP 的過(guò)程(DNS查詢),從而減少時(shí)間損耗。(注意:這個(gè)屬性還在實(shí)驗(yàn)階段,部分瀏覽器的部分版本支持)

          preconnect。讓瀏覽器在一個(gè) HTTP 請(qǐng)求正式發(fā)給服務(wù)器前預(yù)先執(zhí)行一些操作,這包括 DNS 解析、TLS 協(xié)商、TCP 握手,通過(guò)消除往返延遲來(lái)為用戶節(jié)省時(shí)間。(注意:這個(gè)屬性還在實(shí)驗(yàn)階段,部分瀏覽器的部分版本支持)

          prefetch/preload。兩個(gè)值都是讓瀏覽器預(yù)先下載并緩存某個(gè)資源,但不同的是,prefetch 可能會(huì)在瀏覽器忙時(shí)被忽略,而 preload 則是一定會(huì)被預(yù)先下載。

          prerender。瀏覽器不僅會(huì)加載資源,還會(huì)解析執(zhí)行頁(yè)面,進(jìn)行預(yù)渲染。(注意:這個(gè)屬性還在實(shí)驗(yàn)階段,部分瀏覽器的部分版本支持)


          搜索優(yōu)化

          你所寫(xiě)的前端代碼,除了要讓瀏覽器更好執(zhí)行,有時(shí)候也要考慮更方便其他程序(如搜索引擎)理解。合理地使用 meta 標(biāo)簽和 link 標(biāo)簽,恰好能讓搜索引擎更好地理解和收錄我們的頁(yè)面。

          meta 標(biāo)簽:提取關(guān)鍵信息

          通過(guò) meta 標(biāo)簽可以設(shè)置頁(yè)面的描述信息,從而讓搜索引擎更好地展示搜索結(jié)果。

          例如,在百度中搜索“淘寶”,就會(huì)發(fā)現(xiàn)網(wǎng)站的描述信息,這些描述信息就是通過(guò) meta 標(biāo)簽專(zhuān)門(mén)為搜索引擎設(shè)置的,目的是方便用戶預(yù)覽搜索到的結(jié)果。


          為了讓搜索引擎更好地識(shí)別頁(yè)面,除了描述信息description之外還可以使用關(guān)鍵字,這樣即使頁(yè)面其他地方?jīng)]有包含搜索內(nèi)容,也可以被搜索到(當(dāng)然搜索引擎有自己的權(quán)重和算法,如果濫用關(guān)鍵字是會(huì)被降權(quán)的,比如 Google 引擎就會(huì)對(duì)堆砌大量相同關(guān)鍵詞的網(wǎng)頁(yè)進(jìn)行懲罰,降低它被搜索到的權(quán)重)。


          當(dāng)我們搜索關(guān)鍵字“安全購(gòu)物”的時(shí)候搜索結(jié)果會(huì)顯示淘寶網(wǎng)的信息,雖然顯示的搜索內(nèi)容上并沒(méi)有看到“安全購(gòu)物”字樣,這就是因?yàn)樘詫毦W(wǎng)頁(yè)面中設(shè)置了這個(gè)關(guān)鍵字。

          對(duì)應(yīng)代碼如下:

          <meta content="淘寶,掏寶,網(wǎng)上購(gòu)物,C2C,在線交易,交易市場(chǎng),網(wǎng)上交易,交易市場(chǎng),網(wǎng)上買(mǎi),網(wǎng)上賣(mài),購(gòu)物網(wǎng)站,團(tuán)購(gòu),網(wǎng)上貿(mào)易,安全購(gòu)物,電子商務(wù),放心買(mǎi),供應(yīng),買(mǎi)賣(mài)信息,網(wǎng)店,一口價(jià),拍賣(mài),網(wǎng)上開(kāi)店,網(wǎng)絡(luò)購(gòu)物,打折,免費(fèi)開(kāi)店,網(wǎng)購(gòu),頻道,店鋪" name="keywords">

          在實(shí)際工作中,推薦使用一些關(guān)鍵字工具來(lái)挑選,比如

          Google Trends

          https://trends.google.com/trends


          站長(zhǎng)工具

          https://data.chinaz.com/keyword/


          link 標(biāo)簽:減少重復(fù)

          有時(shí)候?yàn)榱擞脩粼L問(wèn)方便或者出于歷史原因,對(duì)于同一個(gè)頁(yè)面會(huì)有多個(gè)網(wǎng)址,又或者存在某些重定向頁(yè)面,比如:

          - https://baidu.com/a.html

          - https://baidu.com/detail?id=abcd


          那么在這些頁(yè)面中可以這樣設(shè)置:

          <link href="https://baidu.com/a.html" rel="canonical">

          這樣可以讓搜索引擎避免花費(fèi)時(shí)間抓取重復(fù)網(wǎng)頁(yè)。不過(guò)需要注意的是,它還有個(gè)限制條件,那就是指向的網(wǎng)站不允許跨域。


          當(dāng)然,要合并網(wǎng)址還有其他的方式,比如使用站點(diǎn)地圖,或者在 HTTP 請(qǐng)求響應(yīng)頭部添加 rel="canonical"。


          主站蜘蛛池模板: 亚洲欧美日韩中文字幕一区二区三区| 国产天堂在线一区二区三区| 一区国产传媒国产精品| 亚洲国产系列一区二区三区| 午夜性色一区二区三区不卡视频 | 国产一区二区三区高清视频 | 亚洲国产综合无码一区| 亚洲欧美日韩国产精品一区| 国产爆乳无码一区二区麻豆| av无码精品一区二区三区四区| 国产一区二区三区播放心情潘金莲| 一区二区三区福利视频免费观看| 亚洲av午夜精品一区二区三区| 日韩一区二区三区免费播放| 无码人妻一区二区三区一| 人妻无码一区二区三区免费| 无码少妇一区二区三区| 亚洲乱码一区二区三区在线观看 | 中文字幕国产一区| 国产精品区AV一区二区| 一区二区三区午夜| 精品人妻一区二区三区毛片 | 精品视频一区二区三区在线播放| 国产精品福利一区二区| 精品一区二区三区无码免费视频 | 精品国产AⅤ一区二区三区4区| 国模大胆一区二区三区| 在线精品亚洲一区二区| 亚洲AV无码一区二区乱子仑| 一本大道在线无码一区| 无码aⅴ精品一区二区三区| 国产精品成人免费一区二区| 精品国产一区二区三区av片| 日韩美一区二区三区| 国产一区在线播放| 久久久国产一区二区三区| 东京热无码一区二区三区av| 久久综合九九亚洲一区| 99久久人妻精品免费一区| 日本高清一区二区三区| 国产伦精品一区二区三区无广告|