美文网首页SpringMVCjs css html
[java]45、SpringMVC-请求处理

[java]45、SpringMVC-请求处理

作者: 史记_d5da | 来源:发表于2022-06-04 16:40 被阅读0次

    1、SpringMVC简介

    1.1、概念

    SpringMVC的正式名称是Spring Web MVC,是属于Spring框架的一部分,是基于Servlet APIWeb框架
    SpringMVC的核心功能是:拦截和处理客户端的请求

    1.2、基本使用

    1、在pom.xml中添加依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
    

    spring-webmvc的依赖项:
    spring-aopspring-beansspring-contextspring-core
    spring-expressionspring-web
    2、在web.xml中配置

    <!--    配置SpringMVC自带的DispathcerServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--    Spring的配置文件位置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
    <!--        拦截所有请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    3、在applicationContext.xml中配置

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

    4、创建Controller

    @Controller
    public class UserController {
        @RequestMapping("/addUser")
        @ResponseBody
        public String add() {
            return "Add Success!";
        }
    }
    

    当调用post请求时,就会调用Controller中的add方法
    5、@RequestMapping
    @RequestMapping可以用在类,方法上
    @GetMapping@PostMapping可以用在方法上,底层是基于@RequestMapping

    @Controller
    @RequestMapping("/user")
    public class UserControllerMethod {
        @RequestMapping(value = "/addUser", method = RequestMethod.POST)
        @PostMapping("/add")
        @ResponseBody
        public String add() {
            return "Add Success!";
        }
        // 多个路径 /get 和 /list都会调用
        @GetMapping({"/get", "/list"})
        @ResponseBody
        public String get() {
            return "user get Success!";
        }
    }
    
    1.3、请求参数

    1、默认情况下,SpringMVC会主动传递一些参数给请求方法
    WebRequestHttpServletRequestHttpServletResponseHttpSession

    @Controller
    @RequestMapping("/skill")
    public class SkillController {
        @RequestMapping("/add")
        @ResponseBody
        public String add(HttpServletRequest request,
                          HttpServletResponse response,
                          HttpSession session,
                          WebRequest request2) {
            return "SkillController add";
        }
    }
    

    2、默认情况下,请求参数会传递给同名的方法参数
    可以通过@RequestParam指定方法参数对应的请求参数名
    required属性为false:请求参数是可选的,客户端可以不传
    required属性为false:请求参数是必须的,客户端必须传,否则出现400错误
    可以通过Model对象去接收请求参数
    Model对象的属性名需要和请求参数名保持一致

    public class SkillController {
        @RequestMapping("/save")
        @ResponseBody
        public String save(@RequestParam(value = "name", required = false) String name,
                           String intro,
                          int level) {
            return "SkillController add";
        }
    }
    

    4、请求路径变量
    如果请求路径中的内容是变化的,可以定义成{变量名},然后通过使用@PathVariable去获取值

    // 浏览器中路由为
    // http://localhost:8080/mvc01/skill/get/12
    public class SkillController {
        @RequestMapping("/get/{id2}")
        @ResponseBody
        public String get(@PathVariable("id2") Integer id) {
            return "SkillController add" + id;
        }
    }
    

    5、利用反射获取参数名
    JDK8开始,可以通过java.lang.reflect.Parameter类获取参数名称
    前提:在编译*.java的时候保留参数名信息到*.class中,比如javac -parameters *.java
    可以通过javap -v *.class查看class文件的参数名信息
    对以下代码进行编译

    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    public class TestParams {
        public void run(String name, int age) {}
        public static void main(String[] args) throws Exception {
            Method method = TestParams.class.getMethod("run", String.class, int.class);
            for (Parameter parameter: method.getParameters()) {
                System.out.println(parameter.getName());
            }
        }
    }
    
    • javac TestParams.javajavap -v TestParams
    #javac
    public void run(java.lang.String, int);
        descriptor: (Ljava/lang/String;I)V
        flags: (0x0001) ACC_PUBLIC
        Code:
          stack=0, locals=3, args_size=3
             0: return
          LineNumberTable:
            line 9: 0
    
    • javac -parameters TestParams.javajavap -v TestParams.class
    #javac -parameters
    public void run(java.lang.String, int);
        descriptor: (Ljava/lang/String;I)V
        flags: (0x0001) ACC_PUBLIC
        Code:
          stack=0, locals=3, args_size=3
             0: return
          LineNumberTable:
            line 4: 0
        MethodParameters:
          Name                           Flags
          name
          age
    
    • Maven编译,获取MavenTestParams.class文件
    public void run(java.lang.String, int);
        descriptor: (Ljava/lang/String;I)V
        flags: (0x0001) ACC_PUBLIC
        Code:
          stack=0, locals=3, args_size=3
             0: return
          LineNumberTable:
            line 9: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       1     0  this   Lcom/sj/TestParam;
                0       1     1  name   Ljava/lang/String;
                0       1     2   age   I
    

    SpringMVC内部通过PrioritizedParameterNameDiscover类获取参数名

    1.4、乱码处理

    1)、get请求参数乱码
    Tomcat8开始已经没有这个问题
    Tomcat8以前的解决方案是,在TOMCAT_HOME/conf/server.xml中给Connector标签增加属性URIEncoding="UTF-8"

    <Connector port="8080" ... URIEncoding="UTF-8" />
    

    2)、post乱码问题
    通过filter拦截请求,调用request.setCharacterEncoding("UTF-8");
    SpringMVC中内置了这样的Filter,直接在web.xml配置即可使用

    <filter>
        <filter-name>CharacterEncodingFilter</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>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    3)、响应乱码

    @Controller
    @RequestMapping("/encoding")
    public class EncodingController {
        // 指定编码规则,默认是 text/html
        @RequestMapping( value = "/get",produces = "text/html; charset=UTF-8")
        @ResponseBody
        public String get() {
            return "我是小明";
        }
    }
    

    或者在applicationContext.html中添加<mvc:annotation-driven>

    <mvc:annotation-driven>
            <mvc:message-converters>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="defaultCharset" value="UTF-8" />
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    
    1.5、Servleturl匹配 - *.do//*的区别

    1、*.do不会拦截动态资源(比如*.jsp)、静态资源(比如*.html*.js
    2、/会拦截静态资源(比如*.html*.js),不会拦截动态资源(比如*.jsp
    Tomcat内部两个默认的拦截器
    1)、org.apache.catalina.servlets.DefaultServleturl-pattern/
    所有.jsp文件的拦截都会被JspServlet拦截
    2)、org.apache.jasper.servlet.JspServleturl-pattern*.jsp*.jspx

    3、/*会拦截动态资源(比如*.jsp)、静态资源(比如*.html*.js)一般用在Filter

    @Controller
    public class DoController {
        // 匹配所有.jsp文件
        @RequestMapping("/{filename}.jsp")
        @ResponseBody
        public String test3(@PathVariable String filename) {
            return filename;
        }
    }
    

    静态资源被拦截的解决方案1

    1、如果SpringMVCDispatcherServleturl-pattern设置为/,会导致静态资源被拦截
    解决方案:将静态资源交回给TomcatDefaultServlet 去处理

    <!--静态资源默认交回给servlet处理-->
    <mvc:default-servlet-handler default-servlet-name="default"/>
    

    2、<mvc:default-servlet-handler/>的原理
    会通过DefaultServletHttpRequestHandler对象将静态资源转发给TomcatDefaultServlet
    3、使用<mvc:default-servlet-handler/>后,会导致controller无法处理请求
    加上<mvc:annotation-driven>后,可以保证controller正常使用

    静态资源被拦截的解决方案2

    1、由 SpringMVC框架内部来处理静态资源(内部通过ResourceHttpRequestHandler对象)

    <!--mapping 是请求路径-->
    <!--location 是静态资源的位置-->
    <mvc:resources mapping="/asset/**" location="/asset/" />
    

    2、同样需要加上<mvc:annotation-driven>,可以保证controller正常使用

    相关文章

      网友评论

        本文标题:[java]45、SpringMVC-请求处理

        本文链接:https://www.haomeiwen.com/subject/nfugprtx.html