SSM-springmvc框架学习

  1. 1. 一、springmvc 概述
    1. 1.1. 1.1 springmvc定义
    2. 1.2. 1.2 spring和springmvc对比
    3. 1.3. 1.3 springmvc简要流程
  2. 2. 二、开发步骤
    1. 2.1. 2.1、做一个小demo
    2. 2.2. 2.2、防止用户不在网页内请求下直接访问内部网站
  3. 3. 三、注解式开发
    1. 3.1. 3.1@RequestMapping
    2. 3.2. 3.2处理器方法的参数
    3. 3.3. 3.3逐个参数接收

一、springmvc 概述

1.1 springmvc定义

​ 基于spring的一个框架,实际上就是spring的一个模块,专门是做web开发的,理解为servlet的升级。web开发底层是servlet,框架是在servlet基础上面加入一些功能,让开发更方便。

1.2 spring和springmvc对比

​ spring:spring是容器,ioc能够管理对象,
​ 使用< bean>,@Component,@Repository,@Service,@Controller 标签

​ springmvc:能够创建对象,放入到容器中(springmvc容器),spring容器中放的是控制器对象

1.3 springmvc简要流程

​ 我们要做的是 使用 @Controller 创建控制器对象 ,把对象放入到springmvc 容器中,把创建的对象作为控制器使用。这个控制器对象能够接收用户的请求,显示处理结果,就当作是一个servlet使用。

​ 使用 @Controller 注解创建的是一个普通的对象 ,不是servlet,springmvc赋予了控制器对象一些额外的功能。

​ web开发底层是servlet,springmvc中有一个对象是servlet:DispatcherServlet(中央调度器)
​ DispatcherServlet:负责接收用户的所有请求,用户把请求给了DispatcherServlet,之后DispatcherServlet把请求转发给我们的Controller对象,最后Controller对象处理请求。

二、开发步骤

2.1、做一个小demo

​ index.jsp —> DispatcherServlet(中央调度器,类似servlet) —-> 转发,分配给Controller对象(@Controller 注解创建的对象)

开发流程:

  • 发起some.do请求
  • tomcat (web.xml 从url-pattern知道 *.do 的请求给DispatcherServlet)
  • DispatcherServlet(根据spring.xml配置知道some.do,doSome()方法)
  • DispatcherServlet把some.do转发给MyController.doSome()方法
  • 框架执行doSome()把得到的ModelAndView进行处理,转发到show.jsp

简化流程:

​ some.do -> DispatcherServlet -> MyController

img

在pom.xml中引入servlet和springmvc依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

<!--spring mvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>

核心配置文件 web.xml

  • (自定义配置文件的位置:在resources目录下创建配置文件,new->XML Configuration File->Spring Config,然后在web.xml下指定自定义配置文件的位置即可)
  • 之前servlet-name报错是因为没有设置servlet-mapping映射,设置完就不报错了
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
<?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">

<!--声明:注册springmvc的核心对象DispatcherServlet

需要在tomcat服务器启动后,创建DispatcherServlet对象实例

为什么要创建DispatcherServlet对象的实例呢?
因为在DispatcherServlet创建过程中,会同时创建springmvc容器对象,
读取springmvc的配置文件,把这个配置文件中的对象都配置好,
当用户发起请求时就可以直接使用对象了。

servlet的初始化会执行init()方法,DispatcherServlet在init()中{
//创建容器,读取配置文件
webApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
//把容器对象放入到ServletContext中
getServletContext().setAttribute(key,ctx);
}
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!--自定义springmvc读取文件的位置-->
<init-param>
<!--springmvc配置文件的位置属性-->
<param-name>contextConfigLocation</param-name>
<!--指定自定义文件的位置-->
<param-value>classpath:springmvc.xml</param-value>
</init-param>

<!--表示在tomcat启动后,创建servlet对象
数字表示启动后创建对象的顺序,数值越小,tomcat创建对象越早,要求大于等于0的整数
-->
<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
使用框架的时候,url-pattern可以使用两种值
1.使用扩展名方式,语法 *.xxxx , xxxx时自定义扩展名。常用的方式 *.do, *.action, *.mvc等等
http://localhost:8080/myweb/some.do
http://localhost:8080?myweb/other.do
2.使用斜杠"/"
-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

上面已经指定了中央调度器的位置,那么我们现在就在指定的位置创建springmvc.xml

  • 声明组件扫描器(controller)
1
2
3
4
5
6
7
8
9
<?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 https://www.springframework.org/schema/context/spring-context.xsd">

<!-- 声明组件扫描器-->
<context:component-scan base-package="com.laj.controller"/>
</beans>

声明了Controller后,我们就在com.laj.controller.MyController.java 创建控制类

  • 设置映射请求,new ModelAndView(),根据K-V的形式存放数据
  • 设置数据返回的视图,setViewName
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
package com.laj.controller;

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

/**
* @Controller 创建处理器对象,对象放在SpringMVC容器中
*/
@Controller
public class MyController {
/*
处理用户的请求,SpringMVC中是使用方法来处理的
方法是自定义的,可以有多种返回值,多种参数,方法名称自定义
*/

/**
* 准备使用doSome 方法处理some.do请求
* @return
*/
@RequestMapping(value = "/some.do")
public ModelAndView doSome(){
//处理some.do的请求
ModelAndView mv = new ModelAndView();
//K-V形式
mv.addObject("msg1","Hello World!");
mv.addObject("msg2","Hello World!!");

mv.setViewName("/show.jsp");
return mv;
}
@RequestMapping(value = "anny.do")
public ModelAndView anny(){
//处理some.do的请求
ModelAndView mv = new ModelAndView();
//K-V形式
mv.addObject("value1","我是编程天才!");
mv.addObject("value2","是的!");

mv.setViewName("/show.jsp");
return mv;
}
}

上面设置了数据返回的视图后,我们开始创建视图

(由于我们一开始没有创建主页面,现在这里补上index.jsp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%--
Created by IntelliJ IDEA.
User: 11877
Date: 2021/7/4
Time: 1:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>第一个MVC的项目</p>
<p><a href="some.do">发起一个some.do请求</a></p>
<p><a href="anny.do">发起一个anny.do请求</a></p>
</body>
</html>

在主页面中,有两个不同的请求页面, 根据不同的请求页面中,有两个不同的Controller类中的方法返回的值可以获取到。

接下来我们创建超链接里面的视图 数据通过 ${} 的格式进行书写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%--
Created by IntelliJ IDEA.
User: 11877
Date: 2021/7/4
Time: 1:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>show.jsp从request作用域获取数据</h3><br />
<h4>msg1数据:${msg1}</h4>
<h4>msg2数据:${msg2}</h4>
<h4>msg2数据:${value1}</h4>
<h4>msg2数据:${value2}</h4>

</body>
</html>

如此一个完整的SpringMVC 的demo就完成啦!

注意:文件的路径图

img

2.2、防止用户不在网页内请求下直接访问内部网站

解决办法:将视图文件(.jsp)放到WEB-INF下的文件夹下

导致:setViewName请求的网站需要改成**/WEB-INF/view/show.jsp**

如果有多个请求的网站页面,增加前缀的方式将很繁琐

解决办法:在springmvc.xml中声明视图解析器,使用bean注册前缀和后缀

1
2
3
4
5
6
7
<!--    声明视图解析器,帮助开发人员设置视图文件的路径  InternalResourceViewResolver-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀:视图文件的路径-->
<property name="prefix" value="/WEB-INF/view/"/>
<!-- 后缀:视图文件的扩展名-->
<property name="suffix" value=".jsp"/>
</bean>

让MyController中setViewName(“/WEB-INF/view/show.jsp”)—>MyController中setViewName(“show”)

三、注解式开发

3.1@RequestMapping

​ 放在类上面@RequestMapping(“/user”),表示下面的请求都是基于/user/xxx.xx,便于模块化操作

​ 放在方法上@RequestMapping(value=”/xxx.xx”,method = RequestMethod.GET) –>表示get请求方式

​ RequestMethod.GET、RequestMethod.POST……

​ 如果method不写就不限制

注意:在Controller中设置GET或者POST,在index中也要对应,否则会报 错误405

3.2处理器方法的参数

处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序员可以在方法中直接使用。

HttpServletRequest request, 请求
HttpServletResponse response, 应答
HttpSession session 会话

请求中所携带的请求参数(即用户提交的数据)

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class MyController {
@RequestMapping(value = "/some.do")
public ModelAndView doSome(HttpServletRequest request,
HttpServletResponse response,
HttpSession session){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","欢迎使用springmvc做web开发" + request.getParameter("name"));
mv.addObject("fun","执行的是doSome方法");
mv.setViewName("show");
return mv;
}

在这里插入图片描述

3.3逐个参数接收

设置主页index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>提交参数给Controller</p>

<form action="receive.do" method="post">
姓名:<input type="text" name="name"><br />
年龄:<input type="text" name="age"><br />
<input type="submit" value="提交参数">
</form>
</body>
</html>

<注意:1、action后面的域名前面不要加/

​ 2、input后面的参数是对应的事type和name>

业务层:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class MyController {

@RequestMapping(value = "/receive.do")
public ModelAndView doSome(String name ,String age){
ModelAndView mv = new ModelAndView();
mv.addObject("myname",name);
mv.addObject("myage",age);
mv.setViewName("show");
return mv;
}

}

视图层:

1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>从request作用域获取数据</h3><br />
<h3>name数据:${myname}</h3><br/>
<h3>age数据:${myage}</h3>
</body>
</html>

注意:在提交请求参数的时候,get请求方式中文没有乱码;post请求方式中文有乱码,需要使用过滤器处理乱码问题。

使用过滤器处理post中文乱码:characterEncodingFilter 在org. springframework: spring-web: 5.2.5. RELEASE依赖中

所以在web.xml文件中配置:三个参数:encoding、forceRequestEncoding、forceResponseEncoding,通过mapping映射,最后强制范围内请求通过过滤器

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
<!--注册声明过滤器,解决post请求乱码-->
<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>
<!-- 强制请求对象(HttpServletRequest)使用encoding编码的值-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<!-- 强制应答对象(HttpServletResponse)使用encoding编码的值-->
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!-- /*表示强制所有的请求先通过过滤器处理-->
<url-pattern>/*</url-pattern>
</filter-mapping>

总结:

img