springMVC学习一

1、springMVC是什么Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架!简单说就是运用在web层的...
摘要由CSDN通过智能技术生成
1、springMVC是什么

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架!
简单说就是运用在web层的一个框架!

2、springMVC和Struts2比较

(1)共同点:都是表现层(web层,控制层)框架,都是基于MVC模型编写,底层都离不开ServletAPI,处理请求的机制都是一个核心控制器;
(2)区别:
A、入口不同,struts2的入口是一个Filter(StrutsPreparedAndExecuteFilter),而springMVC的入口是一个Servlet(DispatcherServlet);
B、springMVC是基于方法设计的,而struts是基于类设计的,前者是单例的,后者是多例的;
C、springMVC使用更加简洁,同事还支持(JSR303),能更方便的处理ajax;(注:JSR303是一套JavaBean参数校验标准,它定义了很多常用的校验注解,直接将这些注解加在JavaBean上面就可以在需要时,直接校验了。)
D、struts2的OGNL使页面开发效率比springMVC高,但是执行效率相较于JSTL没有提升,struts2提供的表单标签,也没有HTML执行效率高!

3、springMVC入门案列:

(1)新建一个maven的webapp项目,在web.xml中配置springMVC的核心控制器DispatcherServlet:
web.xml:

<!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>
  
  <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>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

(2)在main目录的resources目录下创建一个配制文件springmvc.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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="cn.melo"></context:component-scan>

    <!--试图解析器对象-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--控制器方法返回的字符串的前面会加上这个前缀:/WEB-INF/pages/-->
        <property name="prefix" value="/WEB-INF/pages/"/>
        <!--控制器方法返回的字符串的后面会加上这个后缀:.jsp-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--开启springmvc注解支持-->
    <mvc:annotation-driven/>
</beans>

(3)在main目录的java目录下创建控制器类:
HelloController.java:

package cn.melo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

//创建控制器类对象
@Controller
public class HelloController {

    //声明请求此方法的路径是/hello,这里的属性可以是path,也可以是value
    @RequestMapping(path = "/hello")
    public String sayHello(){
        System.out.println("Hello World!!");
        //返回的字符串和配置文件中的前后缀进行拼接,跳转到相应的页面
        return "success";
    }
}
4、springMVC入门案列的流程分析:

(1)因为在web.xml的DispatcherServlet的配置中加了:

<init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>

所以,服务器在启动时就会去classpath下找springmbc.xml并加载它!
(2)因为开启了注解扫描,所以当扫描dao@Controller的时候就会为控制类创建对象;
(3)用户发出请求,先到DispatcherServlet,根据路径,和springmvc的注解,找到对应的请求方法,执行之;
(4)根据方法的返回值和配置的视图解析器,跳转到对应的jsp页面!

5、springMVC入门案例中的控制器

(1)DispatcherServlet:前端控制器,相当于MVC的C,是整个流程控制的中心,由它调用其他组件,处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性;
(2)HandlerMapping:处理器映射,负责根据用户请求找到Handler(处理器),springmvc提供了不同的映射器实现不同的映射方式,如配置文件,实现接口,注解等!
(3)Handler:处理器,就是我们要编写的业务控制器,由DispatcherServlet把用户请求转发到Handler,由Handler对具体的请求进行处理;
(4)HandlerAdapter:处理器适配,对处理器进行适配,是适配器模式的应用,通过扩展适配器可以对更多类型的适配器进行执行!
(5)ViewResolver:视图解析器,负责将处理结果映射成View(视图);
(6)View:视图,springMVC提供了很多的View视图类型的支持,包括jstlView,freemarkerView,pdfView等,最常用的是jsp;

注:HandlerMapping、HandlerAdapter、ViewResolver被称为springMVC的三大框架!
(7)<mvc:annotation-driven/>:在springmvc.xml中配置这个可以替代注解处理器和适配器的配置;
springMVC的工作原理(图片来源于网络):
在这里插入图片描述

6、@RequestMapping注解

它的作用是建立请求和处理方法之间的对应关系;
(1)可以作用在类上或者方法上:
A、作用在类上,表示第一级的访问目录;
B、作用在方法上,表示第二级的访问目录;
(2)属性:
A、path:指定请求路径的url;
B、value:和path属性一样的;
C、method:指定该方法的请求方式;
D、params:指定限制请求参数的条件;
例如:
params = {“accountName”},表示请求参数必须有 accountName
params = {“moeny!100”},表示请求参数中 money不能是 100。
E、headers:发送的请求中必须包含的请求头;

7、请求参数的绑定

springMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的,要求是表单中name属性值与参数名相同,支持的数据类型有:基本数据类型,字符串类型,JavaBean类型,数组封装!
(1)基本数据类型与字符串类型的要求:表单的name属性值和参数名称一致,区分大小写!
(2)实体类型(JavaBean):表单的name属性值与JavaBean的属性名一致,如果一个JavaBean中包含了其他引用类型,那么表单的name要写成:
对象.属性名

测试:
jsp中:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>HelloWorld</h1>
    <a href="hello">点击</a>

    <form action="params" method="post">
        姓名:<input type="text" name="name"><br>
        年龄:<input type="text" name="age"><br>
        爱好:<input type="checkbox" name="hobbies" value="code">写代码
        <input type="checkbox" name="hobbies" value="basketball">打篮球
        <input type="checkbox" name="hobbies" value="sing">唱歌<br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

控制器类:

package cn.melo.controller;

import cn.melo.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Arrays;

@Controller
public class UserController {

    @RequestMapping(path = "/params")
    public String getParameters(String name, Integer age, String[] hobbies){
        System.out.println("name:"+name);
        System.out.println("age:" + age);
        System.out.println("hobbies:"+ Arrays.toString(hobbies));
        return "success";
    }

    @RequestMapping(path = "/user")
    public String getUser(User user){
        System.out.println(user);
        return "success";
    }
}

请求页面:
在这里插入图片描述
结果:
在这里插入图片描述

把表单提交路径改为user的测试结果:
在这里插入图片描述
也能封装上!
但是发现请求参数中有乱码,解决办法:
在web.xml中配置一个spring提供的过滤器(CharacterEncodingFilter):

<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)自定义类型转换器,表单提交的默认类型都是String类型,但是后台定义Integer类型,也可以完成封装,说明springmvc内部会默认进行数据类型转换。
A、如果想自定义数据类型转换器,可以自定义一个类实现Convert<K,T>接口,K是String,T是逆向转化成的类型,重写converse方法即可!
如,在表单中加一个:

日期:<input type="date" name="date">

在控制器类中:
在这里插入图片描述
自定义的类型转换类:
MyConverter.java

package cn.melo.util;

import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            if(!s.isEmpty() && s != null) {
                date = sdf.parse(s);
            }else{
                System.out.println("请输入日期!!!");
            }
        } catch (ParseException e) {
           throw new RuntimeException("日期转化异常了");
        }
        return date;
    }
}

最后,在springmvc.xml中注册自己写的转换器:

<!--注册自定义的类型转换器-->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
    	<!--用array,set,list都可以-->
        <array>
            <bean class="cn.melo.util.MyConverter"></bean>
        </array>
    </property>
</bean>

<!--使用自定义类型转换器-->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean" />

测试结果:
在这里插入图片描述
在这里插入图片描述
(4)在控制器类中使用servlet的原生api:
只需要在方法的形参上定义HttpServletRequest和HttpServletResponse对象即可!

8、常用的注解

测试用的表单:
在这里插入图片描述
(1)@RequestParam:把请求中指定名称的参数传递给控制器中的形参赋值。
属性:value:请求中参数的名称;required:请求参数中是否必须提供该参数,默认true;
如:

@RequestMapping(path = "/paramTest")
public String testParameters(@RequestParam(value = "name",required = false) String username){
    System.out.println("name:"+username);
    return "success";
}

测试结果:
在这里插入图片描述
在这里插入图片描述
(2)@RequestBody:用于获取请求体的内容(get没有请求体),属性:required:是否必须有请求体,默认true;
测试代码:

@RequestMapping(path = "/paramTest")
public String testParameters(@RequestBody(required = false) String body){
    System.out.println(body);
    return "success";
}

在这里插入图片描述
测试结果:

name=%E8%A9%B9%E5%A7%86%E6%96%AF&age=20&hobbies=code&hobbies=basketball&hobbies=sing&date=2019-11-20

(3)@PathVariable:绑定url中的占位符,如/xx/{id},{id}就是一个占位符
属性:value:指定url中占位符的名称!

注:Restful风格的url,请求路径一样,可以根据不同的请求方式,执行后台中不同的控制器方法!
Restful风格编程的优点:结构清晰,符合标准,易于理解,扩展方便!
测试:
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191120144150974.png
测试结果:
在这里插入图片描述
(4)@RequestHeader:获取指定请求头的值
属性:value:请求头的名称
测试:

@RequestMapping(path = "/paramTest")
public String testParameters(@RequestHeader(value = "Accept") String header){
    System.out.println(header);
    return "success";
}

测试结果:
在这里插入图片描述

text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

(5)@CookieValue:获取指定Cookie的值
属性:value:cookie的名称
测试:
jsp页面加上一段脚本:

<%
    Cookie cookie = new Cookie("xixi","777");
    cookie.setMaxAge(60*60);
    response.addCookie(cookie);
%>

后台:

@RequestMapping(path = "/paramTest")
public String testParameters(@CookieValue(value = "xixi") String cookieValue){
    System.out.println(cookieValue);
    return "success";
}

测试结果:
在这里插入图片描述
(6)@ModelAttribute:
A、用在方法上,表示当前方法在控制器方法执行前执行;
B、在参数上:获取指定数据给参数赋值;

使用场景:当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
就是现在方法上用这个注解,然后查询数据库,得到信息,再在参数上用这个注解,如果表单中没有传上来的参数,就用在数据库中查到的!!

第一种情况测试,用在方法上,方法有返回值:
页面:
在这里插入图片描述
实体类:User1.java:

package cn.melo.bean;

import java.io.Serializable;

public class User implements Serializable {
    private Integer uid;
    private String uname;
    private Double umoney;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public Double getUmoney() {
        return umoney;
    }

    public void setUmoney(Double umoney) {
        this.umoney = umoney;
    }

    @Override
    public String toString() {
        return "User1{" +
                "uid=" + uid +
                ", uname='" + uname + '\'' +
                ", umoney=" + umoney +
                '}';
    }
}

后台:

/**
* 模拟去查询数据库的方法
*/
@ModelAttribute
private User1 findUser(){
   User1 user1 = new User1(1,"abc",1000.00);
   System.out.println("查询出的用户:"+user1);
   return user1;
}

@RequestMapping(path = "/test3")
public String test3(User1 user1){
   System.out.println("修改了的用户:"+user1);
   return "success";
}

测试结果:
在这里插入图片描述
在这里插入图片描述
第二种情况测试,方法没有返回值,那么就要定义一个Map形式参数来存储数据:
测试代码:

/**
* 模拟去查询数据库的方法
*/
@ModelAttribute
private void findUser(Map<String,User1> map){
   User1 user1 = new User1(1,"abc",1000.00);
   System.out.println("查询出的用户:"+user1);
   map.put("abc",user1);
}

@RequestMapping(path = "/test3")
//value属性值是map的键
public String test3(@ModelAttribute(value = "abc")User1 user1){
   System.out.println("修改了的用户:"+user1);
   return "success";
}

测试结果:
在这里插入图片描述
(7)@SessionAttributes:用于多次执行控制器方法之间的参数共享,写在类上:
属性:value:指定存入属性的名称,types:指定存入属性的类型(Xxx.class)
页面:
在这里插入图片描述
首先在控制器类上加上:

@SessionAttributes(value = {"1st","2nd","3rd"},types = {Integer.class,String.class,User1.class})

控制器方法:

@RequestMapping("/testPut")
public String testPut(Model model){
    model.addAttribute("1st",123);
    model.addAttribute("2nd","XXXX");
    model.addAttribute("3rd",new User1(2,"cj",100.0));
    System.out.println("数据已经存储!!!");

    return "success";
}
@RequestMapping("/testGet")
public String testGet(ModelMap model){
    System.out.println("取出数据:");
    System.out.println(model.get("1st"));
    System.out.println(model.get("2nd"));
    System.out.println(model.get("3rd"));

    return "success";

}
@RequestMapping("/testClear")
public String testClear(SessionStatus status){
    status.setComplete();
    System.out.println("数据已经清除!!!");
    return "success";
}

测试结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值