SpringMVC配置和注解说明

2020-02-08  本文已影响0人  茶酒qqq
image.png

SpringMVC配置

入门案例-环境配置

  1. 创建maven-webapp项目,如下图所示
image-20200207103227886.png
  1. 在属性配置界面添加一对key-value,用于避免自动下载一大堆插件,因为会很慢

    key: archetypeCatalog
    value: internal

image-20200207103351484.png
  1. 自己配好文件夹

    image-20200207104033152.png
  1. 导入依赖包

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.26.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.26.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.3.26.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2.1-b03</version>
    </dependency>


  </dependencies>
  1. 建立springmvc配置文件springmvc.xml,并导入约束。此处需要导入两个命名空间,一个是 xmlns:context用于支持spring注解,xmlns:mvc用于支持springmvc注解

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           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
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    </beans>
    
  2. web.xml配置servlet拦截

    然后为了让我们写的springmvc.xml被识别到,需要指出它在哪。于是我们用<init-param>去说明。
    配置filter是为了配置编码为UTF-8。所有的请求过来都会用UTF-8去解码。

  <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <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>


  <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:springmvc.xml</param-value>
    </init-param>
    <!--    表示该servlet的启动顺序-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

入门案例-编写代码

  1. 建立index.jsp页面,包含链接<a href="hello">click</a>,指向hello路径(相对路径)

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>hello</title>
    </head>
    <body>
    <h1>hello SpringMVC</h1>
    <a href="hello">click</a>
    
    </body>
    </html>
    
  2. 编写Controller类HelloController

    • @Controller是spring的注解,用于注册Bean,与 @Component,@Service, @Repositry作用相同。为了区分这是个控制器而用了它。
    • @RequestMapping("/hello")用于指定匹配的url,这里url为"/hello",需要包含 /
    • 要求有@RequestMapping注解的方法返回值是String或者ModelAndView,这里先写String。返回值是要跳转的页面名称,这个要结合后面视图解析器来用
    package com.chajiu.contorller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HelloController {
    
        @RequestMapping("/hello")
        public String sayHello(){
            System.out.println("hello SpringMVC");
            return "success";
        }
    }
    
  3. 编写要跳转的页面success.jsp

    位置:在/WEB-INF/pages/下面,要和后面配置视图解析器对应

image-20200207105101463.png
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success</title>
</head>
<body>
<h1>success!</h1>
</body>
</html>

  1. 配置springmvc.xml

    @RequestMapping注解的方法返回的String都会先到视图解析器里,把前缀后缀加上,拼接成完整的要跳转的页面的路径,再去访问。

     <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           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
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启spring注解支持,让spring扫描包-->
    <context:component-scan base-package="com.chajiu.contorller"></context:component-scan>
    <!--开启SpringMVC注解的支持-->
    <mvc:annotation-driven/>
    
    <!--配置视图解析器-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <!--后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>
    </beans>
    

入门案例-启动

配好tomcat,启动,发现成功跳转。

@RequestMapping注解

用于匹配url。

类上也可以用它,表示一级拦截方式,方法上是二级拦截。

比如类上有@RequestMapping("/usr"),方法上有@RequestMapping("/hello"),那么只有"/usr/hello"的请求才能进入该方法。

属性:

请求参数绑定

1. 基本数据类型

url:

hello?username=ccc&password=123

方法:

@RequestMapping("/hello")
public String getAccount(String username, String password){...}

属性名称和形参名称对应即可。

2. pojo类型

public class Account {
    private Integer id;
    private String username;
    private String password;
    //getter
    //setter

如何注入Account?

提交的属性名和Account里属性名对应即可,方法参数直接写Account。如果没对上,则对应属性为null

<form action="param/saveAccount">
    username:<input  type="text" name="username"><br>
    password:<input type="text" name="password"><br>
    <input type="submit" value="submit">
</form>


@Controller
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("/saveAccount")
    public String saveAccount(Account account){
        System.out.println(account);
        return "success";
    }
}

pojo里包含引用类型怎么办

public class Account {
    private Integer id;
    private String username;
    private String password;
    <!--多了个user-->
    private User user;

映射方法不变,jsp中修改input的name:

<form action="param/saveAccount">
    username:<input  type="text" name="username"><br>
    password:<input type="text" name="password"><br>
    name:<input type="text" name="user.name"><br>
    age:<input type="text" name="user.age"><br>
    <input type="submit" value="submit">
</form>

怀疑这个请求参数绑定的方式应该是形参的Bean加上提交的属性名,组成全限定类名再注入。

因此注入Account的User的name就要是com.chajiu.pojo.Accout.user.name,因此html中要写user.name

3. 集合类型

比如User有个List集合:

public class User {
    private Integer id;
    private String name;
    private Integer age;

    private List<Role> roles;

jsp要上传User数据,同时包含多个角色信息,那怎么办?

在name那做文章:

<form action="param/saveUser" method="post">
    name:<input  type="text" name="name"><br>
    age:<input type="text" name="age"><br>
    role:<input type="text" name="roles[0].role"><br>
    <input type="submit" value="submit">
</form>

使用集合的属性名[i].子属性名表示。List中第一个role是roles[0].roleName,那么第二个role就是roles[1].roleName

如果是Map怎么表示?

role["key"].roleName

自定义类型转换器

提交数据都是字符串,如何会封装到Integerdouble?springMVC有转换器会帮我们把常见的数据类型进行转换再存入pojo中。

但是有时候这种转换不是我们想要的效果。比如String到Date,他给的转换只能转1998/12/28这种类型,对于1998-12-28将无能为力,报错。

所以我们有时候需要自定义类型转换器。

自定义一个类,实现Convert<s,t>接口:

public class StringToDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        if (s==null)
            throw new RuntimeException("请输入数据");
        DateFormat dateFormat=new SimpleDateFormat("yyyy-mm-dd");
        try {
            return dateFormat.parse(s);
        } catch (Exception e) {
            throw new RuntimeException("输入格式有误");
        }

    }
}

修改springmvc.xml:

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.chajiu.converter.StringToDateConverter"></bean>
        </set>
    </property>
</bean>

 <!--    添加conversion-service,指向自己的转换器bean-->
    <mvc:annotation-driven conversion-service="conversionService"/>

但是在修改后,只支持1998-12-28了。哈哈哈

拿到Servlet原生API

如何在方法中拿到request和response呢?

只要在你的方法形参中加入他们,springmvc在调用这个方法时就会自动绑定进去。

@RequestMapping("/saveUser")
public String savesUser(User user, HttpServletRequest req, HttpServletResponse res){
    System.out.println(user);
    System.out.println(req);
    System.out.println(res);
    HttpSession session = req.getSession();
    System.out.println(session);
    return "success";
}

常用注解

RequestParam

情况1:请求属性名和方法形参名对不上就没法匹配了吗?

比如你的url是 /user?name=aaa,而方法形参为 String username

正常情况无法匹配,但是我们可以手动修改映射关系:

@RequestMapping("/requestParam")
public String testRequestParam(@RequestParam(name="name") String username){

意为让请求中的name去匹配username

同时我们看出该注解只能修改基本类型的映射关系。对于pojo实体类无法起作用。

RequestBody

用于获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。
get 请求方式不适用。

@RequestMapping("/requestBody")
public String testRequestBody(String username,@RequestBody String body){

PathVaribale

用于绑定占位符和形参,{sid}为占位符。

使用占位符可以匹配多种url。特别是在RESTful风格的开发中,类似 /pathVariable/10,/pathVariable/12都会匹配到该方法。

@RequestMapping("/pathVariable/{sid}")
public String testPathVariable(@PathVariable(name="sid") String id){

RequestHeader

获取指定请求头部,比如我想获取Accept头部信息:

@RequestMapping("/requestHeader")
public String testRequestMapping(@RequestHeader("Accept") String accept){

CookieValue

用于获得指定的cookie值.

同样是绑定到某个形参上使用

@RequestMapping("/cookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String jsessionid){

ModelAttribute

给model添加属性的。在执行所有控制方法前先执行。

应用场景:要在控制方法执行前对请求参数做某些操作,比如修改值,填充null。

两种使用方式:

修饰方法:

@ModelAttribute
public Account show(String username,String password){
   Account account=new Account();
   account.setId(1);
   account.setUsername(username);
   account.setPassword(password);
   return account;
}

至于这里为什么声明了一个Map呢?因为modelMap是他实现类。接口 指向实现类是可以的。下面请看关系图:

image-20200208160549277.png

可以看出其实modelMap其实就是个Map,里面可以存放键值对。

修饰形参:

SessionAttributes

为了减少耦合,所以在把键值对放入requestScope中时,我们没有直接用元素的ServletAPI,而是用了一个中间对象ModelMap,把键值对交给他,他自动会存入RequestScope中。

那么如何不直接操作Session而把键值对放入SessionScope中呢?

使用SessionAttributes注解,会把modelMap中指定的键值对放入SessionScope中。

需要在类上使用:

@Controller
@SessionAttributes(value={"username"})
@RequestMapping("/anno")
public class AnnoController {

会把modelMap中key为username的属性放入SessionScope。当然可以指定多个。

方法中获取SessionScope中的对象:

@RequestMapping("/getSessionAttribute")
public String getSessionAttribute(ModelMap modelMap){
    String uname= (String) modelMap.get("username");
    System.out.println(uname);
    return "sessionAttributePage";
}

其实我感觉,SpringMVC把jsp的四大作用域都封装在了ModelMap中。所以用ModelMap.get()方法应该也是从四大域中取值。只是查找的顺序不同。从而避免我们之间操作四大域,减少耦合。

上一篇 下一篇

猜你喜欢

热点阅读