分享 14 個 Spring MVC 頂級技巧

通常,在Spring MVC中,我們編寫一個控制器類來處理來自客戶端的請求。然後,控制器調用業務類來處理與業務相關的任務,然後將客戶端重定向到邏輯視圖名稱,該名稱由Spring的調度程序Servlet解析,以呈現結果或輸出。

這樣就完成了典型的請求-響應週期的往返。

今天整理了一下編寫Spring MVC控制器的14個技巧,你今天get到了嗎? \\(≧▽≦)/

1.使用@Controller構造型

這是創建可以處理一個或多個請求的控制器類的最簡單方法。僅通過用構造型註釋一個類@Controller ,例如:

<code>import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
    @RequestMapping("/")
    public String visitHome() {
      
        return "home";
    }
}/<code>


如你所見,visitHome()方法通過重定向到名為home的視圖來處理來自應用程序上下文路徑(/)的請求。

注意:@Controller原型只能在Spring的配置文件中啟用註解驅動時使用:

<code><annotation-driven>/<code>


啟用註釋驅動時,Spring容器自動在以下語句指定的包下掃描類:


<code><component-scan>/<code>


由@Controller 註釋註釋的類被配置為控制器。這是最可取的,因為它很簡單:無需在配置文件中為控制器聲明bean。

注意:通過使用@Controller 註解,您可以擁有一個多動作控制器類,該類能夠處理多個不同的請求。例如:

<code>@Controller
public class MultiActionController {
    @RequestMapping("/listUsers")
    public ModelAndView listUsers() {
    }
    @RequestMapping("/saveUser")
    public ModelAndView saveUser(User user) {
    }
    @RequestMapping("/deleteUser")
    public ModelAndView deleteUser(User user) {
    }
}/<code>


正如你可以在上面的控制器類看,有處理三種不同的請求3種處理方法 /listUsers,/saveUser,和/deleteUser分別。


2.實現控制器接口

在Spring MVC中創建控制器的另一種(也許是經典的)方法是讓類實現 Controller 接口。例如:

<code>import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class MainController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        System.out.println("Welcome main");
        return new ModelAndView("main");
    }
}/<code>


實現類必須重寫該 handleRequest() 方法,當匹配請求進入時,該方法將由Spring調度程序Servlet調用。此控制器處理的請求URL模式在Spring的上下文配置文件中定義如下:


<code><bean>/<code>


但是,此方法的缺點是控制器類無法處理多個請求URL。


3.擴展AbstractController類

如果要輕鬆控制受支持的HTTP方法,會話和內容緩存。擴展你的控制器 AbstractController 類是理想的選擇。請考慮以下示例:

<code>import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class BigController extends AbstractController {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        System.out.println("You're big!");
        return new ModelAndView("big");
    }
}/<code>


這將創建具有有關受支持的方法,會話和緩存的配置的單動作控制器,然後可以在控制器的bean聲明中指定這些配置。例如:


<code><bean>
    <property>
/<bean>/<code>


此配置指示POST 此控制器的hander 方法僅支持該方法。

Spring MVC還提供了幾種針對特定目的而設計的控制器類,包括:

  • AbstractUrlViewController
  • MultiActionController
  • ParameterizableViewController
  • ServletForwardingController
  • ServletWrappingController
  • UrlFilenameViewController


4.為處理程序方法指定URL映射

這是編碼控制器類時必須執行的強制性任務,該控制器類旨在處理一個或多個特定請求。Spring MVC提供了@RequestMapping 註釋,該註解用於指定URL映射。例如:

<code>@RequestMapping("/login")/<code>


這映射了/login 要由帶註解的方法或類處理的URL模式。當在類級別使用此註解時,該類將成為單動作控制器。例如:


<code>import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/hello")
public class SingleActionController {
    @RequestMapping(method = RequestMethod.GET)
    public String sayHello() {
        return "hello";
    }
}/<code>


當@RequestMapping 註解在方法級別使用的,你可以有一個多動作控制器。例如:


<code>import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
    @RequestMapping("/listUsers")
    public String listUsers() {
        return "ListUsers";
    }
    @RequestMapping("/saveUser")
    public String saveUser() {
        return "EditUser";
    }
    @RequestMapping("/deleteUser")
    public String deleteUser() {
        return "DeleteUser";
    }
}/<code>


@RequestMapping註釋還可以用於指定一個方法要處理的多個URL模式。例如:

<code>@RequestMapping({"/hello", "/hi", "/greetings"})/<code>


此外,此註解還具有在某些情況下可能有用的其他屬性,例如method。


5.為處理程序方法指定HTTP請求方法

可以使用 註解的method 屬性 指定處理程序方法支持哪種HTTP方法(GET,POST,PUT等) @RequestMapping。這是一個例子:

<code>import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String viewLogin() {
        return "LoginForm";
    }
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String doLogin() {
        return "Home";
    }
}/<code>


此控制器有兩個處理相同URL模式的方法/login,但前者用於 GET 方法,而後者用於 POST 方法。有關使用@RequestMapping 註解的更多信息,請參見 @RequestMapping註解。


6.將請求參數映射到處理程序方法

Spring MVC的很酷的功能之一是,您可以使用@RequestParam 註解將請求參數作為處理程序方法的常規參數進行檢索。這是將控制器HttpServletRequest 與Servlet API 的接口分離的好方法。

<code>@RequestMapping(value = "/login", method = RequestMethod.POST)
public String doLogin(@RequestParam String username,
                      @RequestParam String password) {
}/<code>


Spring將方法參數用戶名密碼綁定到具有相同名稱的HTTP請求參數。這意味著您可以按以下方式調用URL(如果請求方法是GET):


<code>http:// localhost:8080 / spring / login?username = scott&password = tiger/<code>


類型轉換也是自動完成的。例如,如果您聲明integer 如下類型的參數 :


<code>@RequestParam int securityNumber/<code>


然後,Spring將在處理程序方法中自動將請求參數(字符串)的值轉換為指定的類型(整數)。

如果參數名稱與變量名稱不同,則可以如下指定參數的實際名稱:

<code>@RequestParam("SSN") int securityNumber/<code>


該@RequestParam 註解也有兩個額外的屬性,這可能是在某些情況下是有用的。該屬性指定參數是否為必需。例如: required


<code>@RequestParam(required = false) String country/<code>

這意味著該參數 country 是可選的;因此,它可能會從請求中丟失。在上面的示例中,country 如果請求中不存在此類參數,則變量 將為null。

另一個屬性是 defaultValue,可以在請求參數為空時用作後備值。例如:

<code>@RequestParam(defaultValue = "18") int age/<code>


Map 如果方法參數是type,Spring還允許我們將所有參數作為對象 訪問 Map<string>。例如:/<string>


<code>doLogin(@RequestParam Map<string> params)/<string>/<code>

然後,映射參數包含鍵-值對形式的所有請求參數。有關使用@RequestParam 註釋的更多信息,請參見 @RequestParam註解。關注微信公眾號:Java技術棧,在後臺回覆:spring,可以獲取我整理的 N 篇最新 Spring 教程,都是乾貨。

7.返回模型和視圖

處理完業務邏輯後,處理程序方法應返回一個視圖,然後由Spring的調度程序servlet對其進行解析。Spring允許我們ModelAndView 從handler 方法中返回String或 對象 。

在以下示例中,該 handler 方法返回一個String並表示一個名為的視圖 LoginForm:

<code>@RequestMapping(value = "/login", method = RequestMethod.GET)
public String viewLogin() {
    return "LoginForm";
}/<code>


這是返回視圖名稱的最簡單方法。但是,如果要將其他數據發送到視圖,則必須返回一個 ModelAndView 對象。考慮以下處理程序方法:


<code>@RequestMapping("/listUsers")
public ModelAndView listUsers() {
    List<user> listUser = new ArrayList<>();
    // 從DAO獲取用戶列表…
    ModelAndView modelView = new ModelAndView("UserList");
    modelView.addObject("listUser", listUser);
    return modelView;
}/<user>/<code>


如您所見,此處理程序方法返回一個 ModelAndView 保存視圖名稱 UserList 的User 對象和一個可在視圖中使用的對象集合 。Spring 面試 7 大問題,推薦看下。

Spring也非常靈活,因為您可以將ModelAndView 對象聲明 為處理程序方法的參數,而不用創建一個新的對象。因此,以上示例可以重寫如下:

<code>@RequestMapping("/listUsers")
public ModelAndView listUsers(ModelAndView modelView) {
    List<user> listUser = new ArrayList<>();
    //從DAO獲取用戶列表…
    modelView.setViewName("UserList");
    modelView.addObject("listUser", listUser);
    return modelView;
}/<user>/<code>


瞭解有關該類的更多信息,請參見:ModelAndView class。


8.將對象放入模型

在遵循MVC架構的應用程序中,控制器(C)應該將數據傳遞到模型(M)中,然後在視圖(V)中使用該模型。正如我們在前面的示例中看到的那樣, 該類的addObject() 方法 ModelAndView是以名稱-值對的形式將對象放入模型中:

<code>modelView.addObject("listUser", listUser);
modelView.addObject("siteName", new String("CodeJava.net"));
modelView.addObject("users", 1200000);/<code>

同樣,Spring非常靈活。你可以Map 在處理程序方法中聲明類型的參數 。Spring使用此映射存儲模型的對象。讓我們看另一個例子:

<code>@RequestMapping(method = RequestMethod.GET)
public String viewStats(Map<string> model) {
    model.put("siteName", "CodeJava.net");
    model.put("pageviews", 320000);
    return "Stats";
}/<string>/<code>


這比使用ModelAndView 對象還要簡單 。根據你的喜好,可以使用Map 或 使用 ModelAndView 對象。在這裡要感謝Spring的靈活性。


9.處理程序方法中的重定向

如果你希望在滿足條件的情況下將用戶重定向到另一個URL,請redirect:/ 在URL之前追加。以下代碼段給出了一個示例:

<code>// 檢查登錄狀態....
if (!isLogin) {
    return new ModelAndView("redirect:/login");
}
// 返回用戶列表/<code>


在上面的代碼中,/login 如果未登錄,用戶將被重定向到該 URL。


10.處理表格提交和表格驗證

通過提供@ModelAttribute 用於將表單字段綁定到表單支持對象的註解以及BindingResult 用於驗證表單字段的界面,Spring使處理表單提交變得容易。下面的代碼片段顯示了一種典型的處理程序方法,該方法負責處理和驗證表單數據:

<code>@Controller
public class RegistrationController {
    @RequestMapping(value = "/doRegister", method = RequestMethod.POST)
    public String doRegister(
        @ModelAttribute("userForm") User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            // 表單驗證錯誤
        } else {
            // 表單輸入沒問題

        }
        // 註冊過程……
        return "Success";
    }
}/<code>


從Spring的官方文檔中瞭解有關@ModelAttribute 註釋和BindingResult 接口的更多信息:

  • 在方法參數上使用@ModelAttribute
  • 在方法上使用@ModelAttribute
  • 接口綁定結果


11.處理文件上傳

通過自動將上傳數據綁定到CommonsMultipartFile 對象數組,Spring還使在處理程序方法中處理文件上傳變得容易。Spring使用Apache Commons FileUpload作為基礎的多部分解析器。

以下代碼段顯示了從客戶端上傳文件有多麼容易

<code>@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
public String handleFileUpload(
        @RequestParam CommonsMultipartFile[] fileUpload) throws Exception {
    for (CommonsMultipartFile aFile : fileUpload){
        // 存儲上傳的文件

        aFile.transferTo(new File(aFile.getOriginalFilename()));
    }
    return "Success";
}/<code>


12.在控制器中自動裝配業務類

控制器應將業務邏輯的處理委託給相關的業務類。為此,您可以使用@Autowired 註解讓Spring自動將業務類的實際實現注入控制器。關注微信公眾號:Java技術棧,在後臺回覆:sp,可以獲取我整理的 N 篇最新Spring Boot 教程,都是乾貨。

考慮以下控制器類的代碼段:

<code>@Controller
public class UserController {
    @Autowired
    private UserDAO userDAO;
    public String listUser() {
        // 列出所有用戶的處理方法
        userDAO.list();
    }
    public String saveUser(User user) {
        // 保存/更新用戶的處理方法
        userDAO.save(user);
    }
    public String deleteUser(User user) {
        // 刪除用戶的處理方法
        userDAO.delete(user);
    }
    public String getUser(int userId) {
        // 獲取用戶的處理方法
        userDAO.get(userId);

    }
}/<code>


在此,與用戶管理有關的所有業務邏輯都由該UserDAO 接口的實現提供 。例如:


<code>interface UserDAO {
    List<user> list();
    void save(User user);
    void checkLogin(User user);
}/<user>/<code>


有關@Autowired 註解的更多信息,請參見 註釋類型自動裝配。


13.訪問HttpServletRequest和HttpServletResponse

在某些情況下,您需要直接 在處理程序方法中訪問 HttpServletRequest 或 HttpServletResponse對象。

通過Spring的靈活性,只需在處理方法中添加相關參數即可。例如:

<code>@RequestMapping("/download")
public String doDownloadFile(
        HttpServletRequest request, HttpServletResponse response) {
    // 訪問請求
    // 訪問響應
    return "DownloadPage";

}/<code>


Spring檢測並自動將 HttpServletRequest 和 HttpServletResponse 對象注入方法中。然後,可以訪問請求和響應如獲取 InputStream, OutputStream或返回一個特定的HTTP代碼。


14.遵循單一責任原則

最後,在設計和編寫Spring MVC控制器時,有兩個很好的實踐是你應該遵循的:

1)控制器類不應執行業務邏輯。相反,它應該將業務處理委託給相關的業務類別。這使控制器始終專注於其設計職責是控制應用程序的工作流程。例如:


<code>@Controller
public class UserController {
    @Autowired
    private UserDAO userDAO;
    public String listUser() {
        userDAO.list();
    }
    public String saveUser(User user) {
        userDAO.save(user);
    }
    public String deleteUser(User user) {
        userDAO.delete(user);
    }
    public String getUser(int userId) {
        userDAO.get(userId);

    }
}/<code>


2)為每個業務域創建每個單獨的控制器。例如, UserController 用於控制用戶管理的OrderController 工作流程, 用於控制訂單處理的工作流程等。例如:


<code>@Controller
public class UserController {
}
@Controller
public class ProductController {
}
@Controller
public class OrderController {
}
@Controller
public class PaymentController {
}/<code>


這14個小技巧,可以幫助你正確有效地在Spring MVC中編寫控制器類。如果你有其他提示或建議,請隨時在評論中分享您的想法。


分享到:


相關文章: