天天看點

使用requestmapping進不去控制器_吐血整理!14個編寫Spring MVC控制器的實用小技巧...

全文共4248字,預計學習時長9分鐘
使用requestmapping進不去控制器_吐血整理!14個編寫Spring MVC控制器的實用小技巧...

編寫Spring MVC控制器的最佳技巧

本文介紹了編寫Spring MVC架構的控制器(controller)的基礎技巧和最佳操作。在Spring MVC架構中,編寫控制器類通常是為了處理使用者提出的請求。

編寫完成後,控制器會調用一個業務類來處理業務相關任務,進而重定向客戶到邏輯視圖名。Springdispatcher servlet會對邏輯視圖名進行解析,并渲染結果或輸出。這就是一個典型的“請求—響應”的完整流程。

1.使用@controllerstereotype

建立一個能夠處理單個或多個請求的控制器類,最簡單的方法就是使用@controllerstereotype注解一個類,如:

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

publicclassHomeController {

@RequestMapping("/")

publicString visitHome() {

// do something before returning view name

return"home";

}

}

如上所示,visitHome()方法通過重定向跳轉到視圖名home來處理應用程式内容路徑(/)收到的請求。

注意:隻有在Spring配置檔案中啟用了注解驅動,才能使用@controllerstereotype。

啟用注解驅動後,Spring的容器(container)會自動掃描如下包中的類:

帶有@controller注解的類會被标記成控制器。由于其簡單友善,且不再需要對配置檔案中的控制器聲明beans,這一方法非常實用。

注意:使用@controller注解可以建立一個多動作控制器類,可同時處理多個不同的請求。如:

@Controller

publicclassMultiActionController {

@RequestMapping("/listUsers")

public ModelAndView listUsers() {

}

@RequestMapping("/saveUser")

public ModelAndView saveUser(User user) {

}

@RequestMapping("/deleteUser")

public ModelAndView deleteUser(User user) {

}

}

如上所示,有三個處理器(handler)在分别處理三個請求,/listUsers,/saveUser,和/deleteUser。

2.實作控制器接口

在Spring MVC中建立控制器還可以用另一個經典的方法,即對一個類實作Controller接口。如:

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;

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

publicclassMainControllerimplements Controller {

@Override

public ModelAndView handleRequest(HttpServletRequest request,

HttpServletResponse response) throws Exception {

System.out.println("Welcome main");

returnnew ModelAndView("main");

}

}

實作類必須重寫handleRequest()方法(當收到相比對的請求時,Spring dispatcher servlet會調用handleRequest)。由該控制器處理的請求URL模式在Spring的内容配置檔案中的定義如下:

這一方法的缺點在于其控制類無法同時處理多個請求URL。

3.繼承AbstractController類

如果想要輕松控制受支援的HTTP方法、會話和内容緩存,讓控制類繼承AbstractController類是理想的方法。如:

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;

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

publicclassBigControllerextends AbstractController {

@Override

protected ModelAndView handleRequestInternal(HttpServletRequest request,

HttpServletResponse response) throws Exception {

System.out.println("You're big!");

returnnew ModelAndView("big");

}

}

上例建立了一個配置了受支援的方法、會話和緩存的單動作控制器,能夠在控制器的bean聲明中被指明。如:

這一配置表明該控制器handler方法僅支援POST方法。了解更多配置(如會話、緩存),參見AbstractController。

SpringMVC還提供了多個支援特定目的的控制器類,包括:

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

4.為處理器指定URL映射

這是編寫控制器類必不可少的一步,旨在處理一個及以上特定請求。Spring MVC提供了@RequestMapping注解,用于指定URL映射。如:

@RequestMapping("/login")

這一步映射了URL模式/login,并用注解或注解類對其進行了處理。@RequestMapping注解用于類上時,類變成了單動作控制器。如:

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

@Controller

@RequestMapping("/hello")

publicclassSingleActionController {

@RequestMapping(method = RequestMethod.GET)

publicString sayHello() {

return"hello";

}

}

@RequestMapping注解用于方法上時,則可生成多動作控制器。如:

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

publicclassUserController {

@RequestMapping("/listUsers")

publicString listUsers() {

return"ListUsers";

}

@RequestMapping("/saveUser")

publicString saveUser() {

return"EditUser";

}

@RequestMapping("/deleteUser")

publicString deleteUser() {

return"DeleteUser";

}

}

@RequestMapping注解也可用于指定多個URL模式,并用單一方法對其進行處理。如:

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

此外,該注解還有其他的屬性,在一些情況下能發揮作用,如下一小節将講到的method屬性。

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

使用@RequestMapping注解的method屬性,可以指定處理器方法支援的HTTP方法(包括GET、POST、PUT等)。如:

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping

import org.springframework.web.bind.annotation.RequestMethod;

@Controller

publicclassLoginController {

@RequestMapping(value = "/login", method = RequestMethod.GET)

publicString viewLogin() {

return"LoginForm";

}

@RequestMapping(value = "/login", method = RequestMethod.POST)

publicString doLogin() {

return"Home";

}

}

如上所示,對于同一個URL模式/login,該控制器有兩個處理方法。第一個方法用于GET方法,第二個則用于POST方法。

了解更多@RequestMapping注解相關知識,參見@RequestMapping注解。

6.将請求參數映射至處理器方法

SpringMVC的特征之一,就是可以使用@RequestParam注解将請求參數作為處理器方法的正常參數取回。這是一個将控制器從ServletAPI的HttpServletRequest接口中解耦出來的好方法。

如:

@RequestMapping(value = "/login", method = RequestMethod.POSTpublic String doLogin(@RequestParamString username @RequestParamString password) {}

Spring将方法參數使用者名及密碼和命名相同的HTTP請求參數綁定到一起。這也就意味着可用如下方式調用一個URL(以GET請求方法為例):

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

類型轉換也自動完成了。如果對一個integer類型的參數聲明如下:

@RequestParamint securityNumber

則Spring會在處理方法中自動将請求參數的值(String類型)轉換為指定類型(integer)。

為防止參數名與變量名不同,可将參數實名指定如下:

@RequestParam("SSN") int securityNumber

@RequestParam注解還有另外兩個屬性,可在一些情況下發揮作用。其中一個屬性是required,可指定一個參數是強制參數還是可選參數。如:

@RequestParam(required = false) String country

這就意味着參數country是可選的,在請求中可略去。當請求中沒有參數country時,則變量country為空值。

另一個屬性是defaultValue,可在請求參數為空時充當回退值(fallbackvalue)。如:

@RequestParam(defaultValue = "18") int age

當方法參數類型為Map時,Spring也支援将所有參數作為Map對象。如:

doLogin(@RequestParam Map params)

則映射參數包含所有鍵值對形式的請求參數。了解更多@RequestParam注解相關知識,參見@RequestParam注解。

7.傳回模型和視圖

處理器方法在處理完業務邏輯後,會傳回一個視圖,該視圖随後由Springdispatcher servlet進行解析。Spring支援handler方法傳回String對象或ModelAndView對象。如下所示,handler方法傳回了一個String對象,并表示了視圖名LoginForm:

@RequestMapping(value = "/login", method = RequestMethod.GET)

public String viewLogin() {

return"LoginForm";

}

這是傳回視圖名最簡單的方法。但是如果想要發送其他資料到視圖,則必須傳回ModelAndView對象。如:

@RequestMapping("/listUsers")

public ModelAndView listUsers() {

List listUser = new ArrayList<>();

// get user list from DAO...

ModelAndView modelView = new ModelAndView("UserList");

modelView.addObject("listUser", listUser);

return modelView;

}

如上所示,該處理器方法傳回了一個ModelAndView對象,該對象視圖名為UserList,并有一個可用在視圖中的User對象集。

Spring是一個非常靈活的架構,支援将ModelAndView對象聲明為處理器方法的參數,而無需再重新建立一個。是以,上例可以重寫為:

@RequestMapping("/listUsers")

public ModelAndView listUsers(ModelAndView modelView) {

List listUser = new ArrayList<>();

// get user list from DAO...

modelView.setViewName("UserList");

modelView.addObject("listUser", listUser);

return modelView;

}

了解更多ModelAndView類相關知識,參見ModelAndView類。

8.将對象放入模型

在MVC架構的應用程式中,控制器将資料輸入到模型中,該模型則被用在視圖中。從上一節中的舉例中可以看到,ModelAndView類的addObject()用于将對象以名值對的形式放入模型中:

modelView.addObject("listUser", listUser);

modelView.addObject("siteName", newString("CodeJava.net"));

modelView.addObject("users", 1200000);

Spring同樣支援聲明處理器方法中的Map類型參數。Spring使用這一映射存儲将放入模型的對象。如:

@RequestMapping(method = RequestMethod.GET)

publicStringviewStats(Map model) {

model.put("siteName", "CodeJava.net");

model.put("pageviews", 320000);

return"Stats";

}

這一方法比使用ModelAndView對象更加簡單。Spring支援使用者靈活選擇Map對象和ModelAndView對象。

9.處理器方法中的重定向

當條件允許時,隻需在URL前加上redirect:/就可将使用者重定向跳轉到另一個URL。如:

// check login status....

if (!isLogin) {

returnnew ModelAndView("redirect:/login");

}

// return a list of Users

在上述代碼中,沒有登陸的使用者将會跳轉到/loginURL。

10.處理表單送出和表單驗證

Spring中的@ModelAttribute注解支援将表單字段綁定到表單傳回對象,BingingRequest接口則支援驗證表單字段。這使得處理表單送出變得非常簡單。一個處理和驗證表單資料的典型處理器方法的代碼如下所示:

@Controller

publicclassRegistrationController {

@RequestMapping(value = "/doRegister", method = RequestMethod.POST)

publicString doRegister(

@ModelAttribute("userForm") User user, BindingResult bindingResult) {

if (bindingResult.hasErrors()) {

// form validation error

} else {

// form input is OK

}

// process registration...

return"Success";

}

}

了解更多@ModelAttribute注解和BindingResult接口相關知識,參見Spring官方文檔:

  • Using @ModelAttribute on a method argument
  • Using @ModelAttribute on a method
  • Interface BindingResult

11.處理檔案上傳

Spring支援自動将上傳資料綁定到CommonsMultiparFile數組對象,這使得在處理器方法中處理檔案上傳變得非常簡單。Spring使用Apache CommonsFileUpload作為深層多部分解析器(underlyingmultipart resolver)。

簡單上傳使用者檔案的代碼如下所示:

@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)

publicStringhandleFileUpload(

@RequestParam CommonsMultipartFile[] fileUpload) throws Exception {

for (CommonsMultipartFile aFile : fileUpload){

// stores the uploaded file

aFile.transferTo(new File(aFile.getOriginalFilename()));

}

return"Success";

}

了解Spring MVC處理檔案上傳的完整方法,參見Spring MVC 檔案上傳教程。

12.在處理器中自動注入業務類

為了讓控制器将業務邏輯處理委托到相關業務類,可以使用@Autowired注解,讓Spring自動将業務類的實際實作注入到控制器中。如:

@Controller

publicclassUserController {

@Autowired

private UserDAO userDAO;

publicString listUser() {

// handler method to list all users

userDAO.list();

}

publicString saveUser(User user) {

// handler method to save/update a user

userDAO.save(user);

}

publicString deleteUser(User user) {

// handler method to delete a user

userDAO.delete(user);

}

publicString getUser(int userId) {

// handler method to get a user

userDAO.get(userId);

}

}

本例中所有與使用者管理相關的業務邏輯都由UserDAO接口的實作提供。如:

interfaceUserDAO {

List list();

void save(User user);

void checkLogin(User user);

}

如上所示,使用@Autowired注解使處理器方法可以将任務委托到業務類:

List listUser = userDAO.list();

了解更多@Autowired注解相關知識,參見Annotation TypeAutowired。

13.擷取HttpServletRequest和HttpServletResponse

有些情況要求在處理器方法中直接擷取HttpServletRequest或HttpServletResponse對象。在Spring靈活的架構中,僅需給處理器方法加上一個相關參數就可以完成此任務。如:

@RequestMapping("/download")

publicStringdoDownloadFile(

HttpServletRequest request, HttpServletResponse response) {

// access the request

// access the response

return"DownloadPage";

}

Spring支援檢測并自動将HttpServletRequest和HttpServletResponse對象注入到方法中。這樣一來,就可以直接擷取請求和響應,如擷取InputStream、OutputStream或傳回特定的HTTP代碼。

14.遵守單一職責原則

在Spring MVC中設計和編寫控制器時,應遵循以下兩個非常實用的操作:

  • 不要用控制器類來執行業務邏輯,應該用控制器類将業務處理委托到相關的業務類。這可以保證控制器專注于其指定職責,即控制應用程式的工作流。如:

@Controller

publicclassUserController {

@Autowired

private UserDAO userDAO;

publicString listUser() {

// handler method to list all users

userDAO.list();

}

publicString saveUser(User user) {

// handler method to save/update a user

userDAO.save(user);

}

publicString deleteUser(User user) {

// handler method to delete a user

userDAO.delete(user);

}

publicString getUser(int userId) {

// handler method to get a user

userDAO.get(userId);

}

}

  • 給每個業務領域建立一個獨立的控制器。如,用UserController控制使用者管理的工作流,用OrderController控制訂單處理的工作流,等等:

@Controller

publicclassUserController {

}

@Controller

publicclassProductController {

}

@Controller

publicclassOrderController {

}

@Controller

publicclassPaymentController {

}

以上就是本文全部内容,希望這14個小技巧可以幫助讀者準确且高效地編寫Spring MVC中的控制器類代碼。有任何技巧分享或建議,歡迎在評論區留言。

使用requestmapping進不去控制器_吐血整理!14個編寫Spring MVC控制器的實用小技巧...

留言點贊關注

我們一起分享AI學習與發展的幹貨

如轉載,請背景留言,遵守轉載規範