SpringMVCjs css html

[java]45、SpringMVC-请求处理

2022-06-04  本文已影响0人  史记_d5da

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
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
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
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正常使用

上一篇 下一篇

猜你喜欢

热点阅读