SpringMVC 基礎筆記(一)

SpringMVC 處理模型:

1、所有request請求,如果需要交由SpringMVC處理,必須在DispatcherServlet對請求進行處理

2、所有請求根據請求的信息,通過handlerMapping進行獲得相關的Handler映射。

3、根據handler的映射信息,獲得handler然後通過handlerAdapter對handler進行統一封裝代用。

3、然後根據handler的處理獲得相應的ModelAndView,然後通過ModelAndView獲得請求的模型數據和需要進行response的視圖信息

4、根據ModelAndView中的視圖信息調用ViewResolver,獲得相應的視圖(JSP等)

5、根據實際的視圖進行response渲染,並返回給客戶端


其中controller就是我們的handler然後通過handlerAdapter進行適配,至於我們的DefaultAnnotationHandlerMapping是通過@RequestMapping進行標識。可以發現其實HandlerMapping和HandlerAdapter、ViewResolver的實現類都可以進行調整的,當然默認已經幾乎夠用了。


首先對SpringMVC進行配置,我們需要配置web.xml 因爲需要聲明DispatcherServlet 截獲所有請求,第二需要在web.xml中定義SpringMVC的配置文件。

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>Spring Review Web Application</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <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:mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
可以見到有contextConfigLocation配置定義了SpringMVC的配置文件位置。當然這不是唯一定義SpringMVC配置文件位置的方式:

1、不寫配置文件的位置,默認爲servlet-name的名字+servlet.xml,以上面爲例:servlet-name爲springMvc,默認配置文件爲:/WEB-INF/springMvc-servlet.xml

2、配置namespace,如果配置namespace的情況下,配置文件的位置和文件名是:/WEB-INF/<namespace>.xml。

3、第三種方式就是上面那種,也是我經常使用的一種,因爲我用maven創建項目,所有配置文件習慣放在resource列表中。


當然也有一些不常用的屬性這裏也列出一下:

1、publishContext: boolean類型的屬性,默認爲true。決定是否將WebApplicationContext 發表到ServletContext的屬性列表中。調用者可以使用servletContext找到WebApplicationContext實例,對應的屬性名爲DispatcherServlet#getServletContextAttributeName()返回值。

2、publishEvents:boolean類型屬性,當DispatcherServlet處理完一個請求後,是否需要向容器發佈一個ServletRequestHandlerEvent事件,默認爲true,如果容器中沒有監聽可以設置爲false來提高運行性能。


SpringMVC配置文件

其實SpringMVC配置文件和Spring的基本配置文件差不多。但是最重要的概念是,Spring容器和SpringMVC容器的關係,SpringMVC的容器是作爲Spring容器的子容器。所以SpringMVC容器中的bean能夠訪問Spring容器中的資源,但是反過來則不可以。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.maxfunner"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/views/" p:suffix=".jsp" p:order="2"
    ></bean>

</beans>

這裏首先定義了關於組建的掃描的包起始位置,當然這裏最重要是controller的掃描。這裏我們定義了viewResolver是InternalResourceViewResolver,這個viewResolver稍後會詳細詳解,這裏定義了InternalResourceViewResolver的作用是,定義從handler獲得的視圖位置解釋。例如:我們從控制器返回一個“login”字符串,則將會解釋視圖爲/WEB-INF/views/login.jsp的視圖,然後將這個視圖進行渲染和響應。


然後我們做一個簡單的控制器

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping("/register.html")
    public String registerHtml() {
        return "user/register";
    }


    @RequestMapping("/login.html")
    public String loginHtml() {
        return "user/login";
    }


    @RequestMapping("/register.action")
    public ModelAndView registerAction(User user) {
        this.userService.saveUser(user);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/main");
        modelAndView.addObject("user", user);
        return modelAndView;
    }


    @RequestMapping("/{userId}")
    public String getUserById(@PathVariable("userId") int userId, ModelMap modelMap) {
        modelMap.put("user", this.userService.getUserById(userId));
        return "user/main";
    }


    @RequestMapping(value = "/list")
    public String userList(int begin, int end, ModelMap modelMap) {
        List<User> userList = this.userService.getUserByIdRange(begin, end);
        modelMap.addAttribute("userList", userList);
        return "user/list";
    }


    @RequestMapping(value = "/login.action", params = {"username=admin"})
    public ModelAndView adminLogin(String username, String password) {
        ModelAndView modelAndView = new ModelAndView();
        User user = this.userService.login(username, password);
        modelAndView.addObject("user", user);
        modelAndView.setViewName("user/main");
        System.err.println(">>>>>>> adminLogin !!!");
        return modelAndView;
    }


    @RequestMapping(value = "/login.action", params = {"username!=admin"})
    public ModelAndView normalLogin(String username, String password,
                                    @CookieValue("JSESSIONID") String jsessionId) {
        ModelAndView modelAndView = new ModelAndView();
        User user = this.userService.login(username, password);
        modelAndView.addObject("user", user);
        modelAndView.setViewName("user/main");
        System.err.println(">>>>>>> normalLogin !!! " + jsessionId);
        return modelAndView;
    }


}

這裏可以看見很多種獲http請求信息綁定的方式,首先解釋幾件事:

@RequestMapping:@RequestMapping 爲響應的方位URL,這個是針對於項目而然的,這裏的RequestMapping 在類的頭部也有定義,方法也有定義。在類中定義是非必要的,但是一般我們都會這樣做,原因是爲了對類進行URL分類。如果用戶訪問路徑爲/user/login.html 則這裏會訪問到loginhtml方法當中。如果我們沒有定義類的RequestMapping則 用戶訪問loginHtml則用戶的訪問路徑爲/login.html。然而@RequestMapping最重要的是將請求匹配到相應的處理方法當中,所以匹配方式可以有如下這些:

1、@RequestMapping("/user/*/main") 使用通配符進行多個url匹配到單個處理方法當中,通配符*一個路徑下的任意目錄名稱(不包括子目錄),通配符**則爲一個路徑下的任意目錄名稱(包括子目錄),?代表匹配任意字符。舉個例子:/user/*/main 匹配 /user/ab/main  /user/dd/main ... ,  /user/**/main 匹配 /user/admin /user/ccd/dd/main /user/add/admin ... , /user/??/main 匹配 /user/dd/main  /user/da/main

2、對請求參數的訪問限制:我們可以通過@RequestMapping的param的屬性對其進行控制,例子:

@RequestMapping(value = "/login.action", params = {"username=admin"})   如果username參數值爲admin 則映射到這個處理方法當中。

 @RequestMapping(value = "/login.action", params = {"username!=admin"}) 如果username參數值不等於admin 則映射到這個處理方法中。

除此之外,!admin則代表請求不包含admin的參數,admin則代表請求包含admin參數。當然如果多個條件可以使用“,” 分開。

3、對請求方法(method)進行綁定,@RequestMapping(value = "/register.action",method = RequestMethod.POST) 這個處理方法 請求method爲post纔會訪問。

4、@RequestMapping 還可以將我們傳入的URL作爲一個佔位符,然後將這個佔位符相應的實際路徑並定到處理方法的參數中,例子:

    @RequestMapping("/{userId}")
    public String getUserById(@PathVariable("userId") int userId, ModelMap modelMap) {
        modelMap.put("user", this.userService.getUserById(userId));
        return "user/main";
    }


入參綁定

一般情況下,我們最簡單就是講參數名稱定義爲提交的參數名稱一致,spring就會爲我們進行綁定,當然我們可以使用@RequestParam進行參數綁定,而且這@RequestParam提供了參數的一些綁定方式,例如這個參數是否必須、參數名是什麼等


@RequestParam

value -->參數名稱

required --> 這個參數是否爲必要參數,默認爲true

defaultValue ---> 默認參數,這個設置了required自定設置爲false。而且極少情況會使用到這個參數。

@RequestMapping(value = "/login.action", params = {"username=admin"})
    public ModelAndView adminLogin(@RequestParam(value = "username",required = true) String username,@RequestParam(value = "password",required = true)  String password) {
        ModelAndView modelAndView = new ModelAndView();
        User user = this.userService.login(username, password);
        modelAndView.addObject("user", user);
        modelAndView.setViewName("user/main");
        return modelAndView;
    }


@CookieValue 將Cookie參數綁定到處理方法的參數上:

@RequestMapping(value = "/login.action", params = {"username!=admin"})
    public ModelAndView normalLogin(String username, String password,@CookieValue(value = "JSESSIONID",required = false) String jsessionId)


@RequestHeader 將請求頭信息綁定到參數中:

@RequestMapping("/index.html")
public String index(@RequestHeader("Accept-Encoding") String encoding) {
      return "user/index";

 }


對form表單的參數封裝對象直接綁定:

@RequestMapping(value = "/register.action", method = RequestMethod.POST)
    public ModelAndView registerAction(User user) {
        this.userService.saveUser(user);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/main");
        modelAndView.addObject("user", user);
        return modelAndView;
  }

則請求參數的名稱和User對象的屬性名稱一致,spring會進行對象的創建和對應屬性的綁定操作。


綁定Servlet API對象作爲處理方法的入參:

@RequestMapping("/index.html")
public String index(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
    return "user/index";
}

Spring會根據參數進行動態綁定,非常方便。然而SpringMVC也提供了一個代理原生ServletAPI對象的接口,WebRequest。


我們甚至可以使用OutputStream作爲處理方法中的入參:

@RequestMapping("/userImage")
public void getImage(OutputStream outputStream) throws IOException {
    Resource resource = new ClassPathResource("/timg.jpeg");
    FileCopyUtils.copy(resource.getInputStream(),outputStream);
}

訪問相關路徑會獲得一張圖片



發佈了53 篇原創文章 · 獲贊 65 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章