기술나눔

스프링 MVC 학습

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

4장 스프링 MVC

섹션 1 Spring MVC 소개

1. 스프링 MVC

SpringMVC는 Java 오픈 소스 프레임워크이며 Spring Framework 생태계의 독립 모듈로, Spring을 기반으로 하는 웹 MVC(데이터, 비즈니스 및 프레젠테이션) 디자인 패턴의 요청 중심 경량 웹 프레임워크를 구현합니다. 편의.

2. Spring MVC 핵심 컴포넌트

  • DispatcherServlet 전면 컨트롤러

    요청 수신 및 배포를 담당합니다.

  • 핸들러 프로세서

    프로세서에는 인터셉터, 컨트롤러의 메소드 등이 포함되며 주로 요청 처리를 담당합니다.

  • HandlerMapping 프로세서 매퍼

    구성 파일을 구문 분석하고, 주석을 스캔하고, 요청을 프로세서에 일치시킵니다.

  • HandlerAdpter 핸들러 어댑터

    요청에 따라 일치하는 프로세서를 찾는 과정을 적응이라고 합니다.

  • ViewResolver 뷰 리졸버

    프로세서가 실행된 후 얻은 결과는 뷰일 수 있지만 이 뷰는 논리적 뷰(페이지에 루프, 판단 등의 논리 코드가 있음)이므로 뷰 리졸버를 사용하여 처리해야 합니다. 뷰 렌더링이라고 합니다.

섹션 2 Spring MVC 개발 및 진화

<!--低版本-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

1. 빈 이름 또는 ID가 URL 요청과 일치합니다.

1.1 web.xml 구성
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <!--配置Servlet初始化参数-->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!--前置控制器要接收所有的请求,因此在容器启动的时候就应该完成初始化-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
1.2 spring-mvc.xml 구성
<!--视图解析器:在控制器返回视图的时候生效-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--视图资源的前缀-->
    <property name="prefix" value="/" />
    <!--视图资源的后缀-->
    <property name="suffix" value=".jsp" />
</bean>
<!--处理器映射的方式:使用bean的名字或者id的值来与请求匹配-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
1.3 컨트롤러 작성
public class UserController extends AbstractController {

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        //这里使用配置的视图解析器进行解析  user => / + user + .jsp => /user.jsp
        return new ModelAndView("user");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
1.4 컨트롤러 구성
<!--通过id值匹配请求的URL-->
<bean id="/view" class="com.qf.spring.mvc.controller.UserController" />
  • 1
  • 2

생각: 이 요청 일치 방법에 따르면 각 요청에 대응하는 컨트롤러가 필요합니다. 이는 서블릿 개발을 사용하는 것과 동일하며 많은 수의 컨트롤러가 작성되므로 개발 효율성이 매우 낮습니다.

Spring 提供了方法名来匹配请求来解决这个问题
  • 1

2. Bean의 메소드 이름이 요청과 일치합니다.

2.1 메소드 이름 파서

Spring은 컨트롤러의 메소드 이름에 대한 해석기인 InternalPathMethodNameResolver를 제공합니다. 이 해석기의 기능은 메소드 이름을 일치하는 URL 요청의 기초로 사용하고 이를 컨트롤러와 연결하는 것입니다.

2.2 다중 동작 컨트롤러

Spring은 다른 컨트롤러 클래스가 상속할 수 있는 MultiActionController 컨트롤러 클래스를 제공합니다. 해당 하위 클래스에서 개발자는 요청 처리를 위한 여러 메서드를 작성한 다음 메서드 이름 파서를 사용하여 요청과 일치시킬 수 있습니다.

2.3 컨트롤러 작성
public class UserMultiController extends MultiActionController {
    //这个方法就匹配 /login 请求
    //请求格式必须是 
    //ModelAndView 方法名(HttpServletRequest req, HttpServletResponse resp){}
    public ModelAndView login(HttpServletRequest req, HttpServletResponse resp){
        return new ModelAndView("login");
    }

    //这个方法就匹配 /register 请求
    public ModelAndView register(HttpServletRequest req, HttpServletResponse resp){
        return new ModelAndView("register");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
2.4 spring-mvc.xml 구성
 <!--方法名解析器-->
<bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />
<!-- /login 请求使用该bean对象处理-->
<bean id="/login" class="com.qf.spring.mvc.controller.UserMultiController">
    <property name="methodNameResolver" ref="methodNameResolver" />
</bean>
<!-- /register 请求使用该bean对象处理-->
<bean id="/register" class="com.qf.spring.mvc.controller.UserMultiController">
    <property name="methodNameResolver" ref="methodNameResolver" />
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

생각: 이 요청 일치 방법에 따르면 컨트롤러가 여러 요청을 처리해야 하는 경우 구성 정보의 양이 많아 나중에 유지 관리하기 어려운 문제가 발생합니다.

Spring 提供了 SimpleUrlHandlerMapping 映射器, 该映射器支持一个控制器与多个请求匹配的同时也解决了配置信息繁多的问题。
  • 1

3. 간단한 URL 핸들러 매핑

SimpleUrlHandlerMapping을 사용하려면 spring-mvc.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--视图解析器:在控制器返回视图的时候生效-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--视图资源的前缀-->
        <property name="prefix" value="/" />
        <!--视图资源的后缀-->
        <property name="suffix" value=".jsp" />
    </bean>

    <!--处理器映射的方式:使用bean的名字或者id的值来与请求匹配-->
<!--    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
    <!--通过id值匹配请求的URL-->
<!--    <bean id="/view" class="com.qf.spring.mvc.controller.UserController" />-->
    <!--方法名解析器-->
<!--    <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />-->
    <!-- /login 请求使用该bean对象处理-->
<!--    <bean id="/login" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <!-- /register 请求使用该bean对象处理-->
<!--    <bean id="/register" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/view">userController</prop>
                <prop key="/user/*">userMultiController</prop>
            </props>
        </property>
    </bean>
    <bean id="userController" class="com.qf.spring.mvc.controller.UserController" />
    <bean id="userMultiController" class="com.qf.spring.mvc.controller.UserMultiController" />
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

생각: 프로젝트 개발이 진행됨에 따라 점점 더 많은 비즈니스 기능이 개발되고 컨트롤러 수도 증가하며 요청 일치 수도 증가할 것입니다. 이로 인해 나중에 유지 관리하기 어려운 문제가 발생합니다. ?

Spring 提供了 DefaultAnnotationHandlerMapping 映射器,支持使用注解来匹配请求,这样就解决了请求匹配导致配置信息繁多的问题,同时还提升了开发效率。
  • 1

4. 일치하는 요청에 주석 달기

4.1 컨트롤러 작성
@Controller
public class UserAnnotationController {

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

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public String register(){
        return "register";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
4.2 spring-mvc.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: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">
    <!--视图解析器:在控制器返回视图的时候生效-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--视图资源的前缀-->
        <property name="prefix" value="/" />
        <!--视图资源的后缀-->
        <property name="suffix" value=".jsp" />
    </bean>

    <!--处理器映射的方式:使用bean的名字或者id的值来与请求匹配-->
<!--    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
    <!--通过id值匹配请求的URL-->
<!--    <bean id="/view" class="com.qf.spring.mvc.controller.UserController" />-->
    <!--方法名解析器-->
<!--    <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />-->
    <!-- /login 请求使用该bean对象处理-->
<!--    <bean id="/login" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <!-- /register 请求使用该bean对象处理-->
<!--    <bean id="/register" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <!--<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/view">userController</prop>
                <prop key="/login">userMultiController</prop>
                <prop key="/register">userMultiController</prop>
            </props>
        </property>
    </bean>
    <bean id="userController" class="com.qf.spring.mvc.controller.UserController" />
    <bean id="userMultiController" class="com.qf.spring.mvc.controller.UserMultiController" />-->
    <!--类上的注解处理器-->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <!--方法上的注解处理器-->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
    <!--扫描包,使得该包下类以及类中定义的方法上所使用的注解生效-->
    <context:component-scan base-package="com.qf.spring.mvc.controller" />
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

5. 최신 버전 구성

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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 https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--视图解析器:在控制器返回视图的时候生效-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--视图资源的前缀-->
        <property name="prefix" value="/" />
        <!--视图资源的后缀-->
        <property name="suffix" value=".jsp" />
    </bean>
    <!--较新的版本使用该标签开启注解支持-->
    <mvc:annotation-driven />
    <!--扫描包,使得该包下类以及类中定义的方法上所使用的注解生效-->
    <context:component-scan base-package="com.qf.spring.mvc.controller" />
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

섹션 3 Spring MVC 공통 주석

1. @컨트롤러

이 주석은 컨트롤러의 식별자입니다.

@Controller
public class UserController{
    
}
  • 1
  • 2
  • 3
  • 4

2. @요청매핑

이 주석은 요청을 일치시키는 데 사용됩니다.

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/login", method=RequestMethod.POST)
    public int login(){
        return 1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3. @요청본문

이 주석은 메서드의 매개변수에만 적용될 수 있으며 요청 본문에서 데이터를 가져와 매개변수에 삽입하는 데 사용됩니다.

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/login", method=RequestMethod.POST)
    public int login(@RequestBody User user){
        return 1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4. @응답 본문

이 주석은 페이지에 데이터를 전달하는 데 사용됩니다.

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/login", method=RequestMethod.POST)
    @ResponseBody
    public int login(@RequestBody User user){
        return 1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5. @요청파라미터

이 주석은 메서드의 매개변수에만 적용될 수 있으며 요청 헤더에서 데이터를 가져와 매개변수에 삽입하는 데 사용됩니다.

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/search", method=RequestMethod.GET)
    @ResponseBody
    public List<User> searchUsers(@RequestParam(value="name") String name){
        return new ArrayList<>();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

6. @Path변수

이 주석은 메소드의 매개변수에만 적용될 수 있으며 요청 경로에서 데이터를 가져와 매개변수에 삽입하는 데 사용됩니다.

@Controller
@RequestMapping("/user")
public class UserController{
    // /user/admin
    @RequestMapping(value="/{username}", method=RequestMethod.GET)
    @ResponseBody
    public User queryUser(@PathVariable("username") String username){
        return new User();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

7. @SessionAttributes[중요하지 않음]

이 주석은 클래스 정의에만 사용할 수 있으며 세션에 입력을 넣는 데 사용됩니다.

@SessionAttributes(types=User.class) //会将model中所有类型为 User的属性添加到会话中。
@SessionAttributes(value={“user1”, “user2”}) //会将model中属性名为user1和user2的属性添加到会话中。
@SessionAttributes(types={User.class, Dept.class}) //会将model中所有类型为 User和Dept的属性添加到会话中。
@SessionAttributes(value={“user1”,“user2”},types={Dept.class}) //会将model中属性名为user1和user2以及类型为Dept的属性添加到会话中。
  • 1
  • 2
  • 3
  • 4

8. @요청헤더

이 주석은 메소드 매개변수에만 적용될 수 있으며 요청 헤더에서 데이터를 얻는 데 사용됩니다.

@RequestMapping("/find")  
public void findUsers(@RequestHeader("Content-Type") String contentType) {//从请求头中获取Content-Type的值
}  
  • 1
  • 2
  • 3

9. @쿠키값

이 주석은 메소드 매개변수에만 적용될 수 있으며 요청에서 쿠키 값을 얻는 데 사용됩니다.

@RequestMapping("/find")  
public void findUsers(@CookieValue("JSESSIONID") String jsessionId) {//从请cookie中获取jsessionId的值
}  
  • 1
  • 2
  • 3

10. @컨트롤러 조언

이 주석은 클래스에만 적용할 수 있으며, 이는 이 클래스가 예외를 처리하는 컨트롤러임을 나타냅니다.

/**
 * 异常处理的控制器
 */
@ControllerAdvice //这个注解就是spring mvc提供出来做全局异常统一处理的
public class ExceptionController {
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

11. @예외 핸들러

이 주석은 예외를 처리하기 위해 @ControllerAdvice 또는 @RestControllerAdvice로 식별된 클래스의 메서드에만 적용할 수 있습니다.

/**
 * 异常处理的控制器
 */
@ControllerAdvice //这个注解就是spring mvc提供出来做全局异常统一处理的
public class ExceptionController {

    @ExceptionHandler //异常处理器
    @ResponseBody //响应至页面
    public String handleException(Exception e){
        return e.getMessage();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

섹션 4 JSR-303

1. JSR-303 소개

JSR은 Java 사양 제안을 나타내는 Java 사양 요청을 나타냅니다. JSR-303은 Java Bean 데이터 유효성 검증을 위해 Java에서 제공하는 표준 프레임워크로, 멤버 변수 및 속성 메소드에 주석을 달 수 있는 검증 주석 세트를 정의합니다. Hibernate Validator는 이 표준의 구현을 제공합니다.

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.0.1.Final</version>
  <!-- 最新7.0.1.Final -->
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2. 검증 주석

주석설명하다주석설명하다
@없는null이어야 합니다.@없음null일 수 없습니다.
@어설트참반드시 사실이어야 합니다@거짓말거짓이어야 한다
@민값이 지정된 최소값보다 크거나 같은 숫자여야 합니다.@맥스값이 지정된 최대값보다 작거나 같은 숫자여야 합니다.
@데시멀민값이 지정된 최소값보다 크거나 같은 숫자여야 합니다.@데시멀맥스값이 지정된 최대값보다 작거나 같은 숫자여야 합니다.
@크기세트의 길이@숫자숫자여야 하며 해당 값은 허용 가능한 범위 내에 있어야 합니다.
@과거과거 날짜여야 합니다.@미래미래 날짜여야 합니다.
@무늬정규 표현식과 일치해야 합니다.@이메일이메일 형식이어야 합니다.
@길이(최소=,최대=)문자열의 크기는 지정된 범위 내에 있어야 합니다.@빈게없음null일 수 없습니다. 길이는 0보다 큽니다.
@Range(최소=,최대=,메시지=)요소는 적절한 범위 내에 있어야 합니다.@NotBlanknull일 수 없습니다. 문자열 길이가 0보다 큽니다(문자열로 제한됨).

3. 신청

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.3.10</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.10</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.1.Final</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
<!-- web.xml -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
<?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: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/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=".jsp" />

    <mvc:annotation-driven>
        <mvc:message-converters>
            <!--处理字符串的消息转换器-->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <!--处理JSON格式的消息转换器-->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <context:component-scan base-package="com.qf.spring.controller" />
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.NotNull;

public class User {

    @NotNull(message = "账号不能为空")
    @Length(min = 8, max = 15, message = "账号长度必须为8~15位")
    private String username;

    @NotNull(message = "密码不能为空")
    @Length(min = 8, max = 20, message = "密码长度必须为8~20位")
    private String password;

    @Range(min = 0, max = 120, message = "年龄只能在0~120岁之间")
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;

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

    @RequestMapping("/add")
    @ResponseBody
    public Object saveUser(@Valid User user, BindingResult result){
        if(result.hasErrors()) return result.getAllErrors();
        return 1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

섹션 5 편안한

1. RESTFUL 소개

REST의 정식 명칭은 대표적 국가 이전,표현하다 대표 상태 이전

RESTFUL은 다음과 같은 특징을 가지고 있습니다.

  • 각 URI는 리소스를 나타냅니다.
  • 클라이언트는 GET, POST, PUT 및 DELETE를 사용하여 서버 리소스를 작동합니다. GET은 리소스를 얻는 데 사용되고, POST는 새 리소스를 만드는 데 사용되며(리소스 업데이트에도 사용할 수 있음), PUT은 리소스 업데이트에 사용되며, DELETE 리소스를 삭제하는 데 사용됩니다.

2. 편안한 요청

/user GET => 获取用户资源
/user POST => 增加用户资源
/user PUT => 修改用户资源
/user DELETE => 删除用户资源

/user/{username} GET => 获取指定用户资源  这是RESTFUL风格中子资源的表述方式
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3. Spring의 RESTFUL 지원

3.1 @휴식 컨트롤러

이 주석은 클래스에만 적용할 수 있으며 @Controller 및 @ResponseBody 주석의 조합과 동일합니다.이 클래스의 모든 메소드가 실행된 후 반환된 결과가 페이지에 직접 출력됨을 나타냅니다.

3.2 @매핑 가져오기
3.2 @포스트맵핑
3.2 @PutMapping
3.2 @매핑 삭제

섹션 6 정적 자원 처리

1. 정적 자원에 접근할 수 없는 이유

정적 리소스에는 html, js, css, 그림, 글꼴 파일 등이 포함됩니다. 정적 파일에는 URL 패턴이 없으므로 기본적으로 액세스할 수 없습니다. 접근할 수 있는 이유는 Tomcat에 전역 서블릿인 org.apache.catalina.servlets.DefaultServlet이 있기 때문입니다. 해당 URL 패턴은 "/"이므로 프로젝트에서 일치할 수 없는 정적 리소스 요청은 모두입니다. 이 서블릿에 의해 처리됩니다. 그러나 SpringMVC에서는 DispatcherServlet도 "/"를 URL 패턴으로 사용하므로 전역 Serlvet은 더 이상 프로젝트에서 사용되지 않으며 결과적으로 정적 리소스에 액세스할 수 없게 됩니다.

2. 솔루션

2.1 옵션 1

DispathcerServlet에 해당하는 url-pattern을 "/"가 아닌 일치하는 패턴으로 변경하면 됩니다. 예를 들어 *.do, *.action입니다. 이 수정 후에는 요청을 보낼 때 요청 URL이 .do 또는 .action과 일치해야 합니다.

2.2 옵션 2
<!-- web.xml -->
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
  </servlet-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
2.2 옵션 3
<!-- spring-mvc.xml -->
<!-- 
这个handler就是处理静态资源的,它的处理方式就是将请求转会到tomcat中名为default的Servlet 
-->
<mvc:default-servlet-handler/>
<!-- mapping是访问路径,location是静态资源存放的路径 -->
<mvc:resources mapping="/static/**" location="/static/" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

섹션 7 중국어 왜곡 코드 처리

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
         version="4.0">
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>encodingFilter</filter-name>
    <!--字符编码过滤器-->
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <!--编码格式-->
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <!--强制编码-->
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

섹션 8 Spring MVC 작동 원리

checkMultipart(request); //检测是否是多部分请求,这个只可能在文件上传的时候为真


getHandler(processedRequest); //获取处理器 => 遍历HandlerMapping,找到匹配当前请求的执行器链
//没有找到执行器链 就直接向页面报一个404
noHandlerFound(processedRequest, response);
//找到处理当前请求的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

//控制器之前执行的拦截器将先执行,如果拦截器不通过,则方法直接结束
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}
//控制器处理请求,可能会得到一个ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

//控制器之后的拦截器执行
mappedHandler.applyPostHandle(processedRequest, response, mv);
//处理分发的结果:这个结果就是控制器处理后的结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//拦截器在控制器给出的结果DispatcherServlet处理后执行
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22