一·使springmvc进入我们的系统
springmvc是怎么进入系统的。任何框架要进入系统主要靠的是在web.xml中加上一些东西。web.xml是系统的启动点。
现代化的书写方式是通过注解的方式来进行配置,
传统的方式是书写配置文件.
现在可以使用别人提供的了:
<!-- servlet定义的开始 -->
<servlet>
<!-- servlet的名字 -->
<servlet-name>dispatcher</servlet-name>
<!-- servlet所对应的java类 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- servlet启动的时候会读取的一些参数 -->
<init-param>
<!-- 上下文配置信息所在的位置 -->
<param-name>contextConfigLocation</param-name>
<!-- servlet所需的配置文件所在的路径。上下文所在的配置信息所在的位置,在类路径下spring下的dispatcher-servlet.xml -->
<param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>
<!-- servlet是自动启动而且启动的顺序是排在第一名 -->
<load-on-startup>1</load-on-startup>
<!-- servlet定义的结束 -->
</servlet>
从包名可以看出,这是spring提供的servlet,要做的就是把它启动起来。而且他是自动启动。
将这一段贴在
该目录下的web.xml中。位置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>stuinfo</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
springmvc提供了一个servlet,能够拦截所有的请求,也就是说所有的请求都经过它。映射方式类似于 /* -> dispatcherServlet
就是说所有的路径,只要你访问路径全都是这个servlet,也就是说spring拦住了整个系统的咽喉要道。当他发现这个请求不是归他处理(请求所写的东西与springmvc没有关系)的话,它会放行。
还要添加这个servlet的映射:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
这个映射表示,只要你访问的是带“/”的路径,都是访问“dispacher”这个servlet。表示只要你访问网页,只要写上任何的网址,最终都是这个servlet进行处理。
原来是,访问
这个网址才是
这个servlet来进行处理,现在相当于:
相当于任何的请求都要经过springmvc的部件过滤,这样,就给springmvc的部件提供了一种机会,能做各种各样的事情。以这样的一个部件,使springmvc能够进入我们的系统。
那么,在这样的servlet拦截了请求之后,如何识别,那些是springmvc处理,哪些不是springmvc处理呢?
比如保安在外面测体温,体温超过多少就不让进,那么这个标准写在哪里呢,不能在springmvc的框架中把它写死掉,这所有的东西都要写在一个配置文件之中,是在外面定制的。这个配置文件所在的路径是:
新建文件夹“spring”:
在这个文件夹下专门放与spring相关的配置文件。
新建文件夹“db”:
专门放与数据库有关的配置文件。
新建文件夹“mapper”:
专门放映射文件。
这些文件不是java代码,但是他们配合java代码工作,是java代码所依赖的资源。早期的java配置文件都用properties描述,后面改为xml,因为xml有更加强大的语言描述能力,能够说明更加复杂的事情。
我们需要配置文件来告诉servlet应该怎么工作。servlet启动的时候会严格的读取配置文件,文件位置在这里告知。
上下文所在的配置信息所在的位置,在类路径下spring下的dispatcher-servlet.xml,resources也在类路径下。
在打包界面可以看到,resources确实是在classes下:
逻辑是:我要用springmvc的servlet拦截请求,看看能不能用springmvc进行处理,处理指令在dispatcher-servlet.xml
在spring目录下,新建dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
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-4.3.xsd">
</beans>
这部分是为了避免重复。
1·本文件指定了springmvc需要处理的内容的处理机制,如果不是springmvc处理的,则一律放行。比如,看到html,JavaScript不做处理,一律放行。
2·注解驱动的开发
<!-- springmvc的配置是用注解就可以了,十分方便 -->
<mvc:annotation-driven></mvc:annotation-driven>
原来是要在xml里写配置的,但是很麻烦。
现在,通过注解的书写,也相当于在xml里写配置信息。
相当于告诉springmvc,我用注解来代替配置文件。
3·要告诉他到哪里去搜索你写注解的那些类——部件扫描器
使用注解的方式,就意味着是写在类上的。不是所有类都是控制器,只有某个包下面的类才有可能是控制器,为了避免扫描器全方位的扫描,消耗时间, 我们应该告诉他那些包下面才有可能是控制器。所有告诉他基本包下头的子包,他拿着这个去扫。
<!-- 控制器部件扫描 (springmvc中servlet已经被controller这个概念封装掉了)
我们必须让springmvc知道其控制器所在的位置,以便加载控制器
包含基本包下头的子包
-->
<context:component-scan base-package="edu.mju.stuwork.controller"></context:component-scan>
只有是对控制器的访问, springmvc的过滤器才启动。哪个java类是控制器呢,如果一个东西是控制器,他要声明自己是个控制器。,用注解的方式写。
传统的书写要写出类名是什么,包名是什么。但是以注解的方式写,就很清晰,因为本身就是写在这个类上面,类名是什么,包名是什么就不用说了。
控制器就代替了servlet,servlet将被封装起来,包在控制器中,底层还是servlet在工作。
我们还没有控制器包
新建包
新建类“StudentController”,他什么都没有继承,我们原来的servlet继承了HttpServlet,有包袱,要有容器,要服务器才能测试
package edu.mju.stuwork.controller;
import org.springframework.stereotype.Controller;
@Controller//只要写上这个他就是控制器
public class StudentController {
}
添加一个测试用的方法:
package edu.mju.stuwork.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class StudentController {
@RequestMapping("/a")//指明,哪个请求是映射到这个方法.只要访问/a就是调用这个方法
public String test() throws Exception{//是一个和网页可以产生联系的方法
System.out.println("testing new ");
return null;
}
}
复制包名:edu.mju.stuwork.controller
回到dispatcher-servlet.xml,将路径贴到贴到这个位置;
在启动后,要打印日志,需要log4j的配合。
log4j:the logging tools for (four)java,是一个针对java的日志工具,几乎成为了工业标准。像SSM,jquery。
添加log4j到resources下:
系统一启动,就会执行web.xml的配置。
再检查一下:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.mju</groupId>
<artifactId>stuinfo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
</dependencies>
</project>
spring-webmvc的版本是5.0.6,若使用5.2.1会有所不同,或者报错。
run on server
下面红红的是maven生命周期
加载XML,并定义文件:
映射/a到test():
404是因为没有欢迎页面:
访问:/a
"test now"有了,但是框架报错了。
更改“StudentController”如下:
package edu.mju.stuwork.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class StudentController {
@RequestMapping("/a") //指明,哪个请求是映射到这个方法.只要访问/a就是调用这个方法,RequestMapping的话什么提交方式都是无所谓的。
@ResponseBody//return "test now";的"test now"是一段文字,将作为我们返回的内容,作为一个返回的主体,在网页上会看到这段文字的出现。
public String test() throws Exception{//是一个和网页可以产生联系的方法
System.out.println("testing new ");
//return null;//是return null;,没有告诉他最终去哪里,所以会报错
return "test now";
}
}
现在:
当我们完成一个操作能不能显示输入界面呢?
在该路径下,新建文件夹“views”:
在其下,创建“input_student.jsp”,内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="<c:url value="/resources/vendor/bootstrap-4.4.1-dist/css/bootstrap.min.css"/>" rel="stylesheet">
<title>Insert title here</title>
</head>
<body>
<div class="container">
<h3 class="my-5">学生注册登记</h3>
<div class="row">
<form action="<c:url value="/stuMgr"/>" class="col-md-6" method="post">
<input type="hidden" name="task" value="createStu"/>
<div class="form-group">
<label>学生学号</label>
<input type="text" class="form-control" name="stuno">
</div>
<div class="form-group">
<label>学生姓名</label>
<input type="text" class="form-control" name="stuname">
</div>
<div class="form-group">
<label>学生成绩</label>
<input type="text" class="form-control" name="stumark">
</div>
<button type="submit" class="btn btn-primary mt-3">确认注册</button>
</form>
</div>
</div>
</body>
</html>
报错,缺少jstl
要在pom.xml添加依赖:
访问:https://mvnrepository.com/maven坐标的查询网站,
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
添加到:
报错消失
复制原来的vendor到webapp下:
原先我们是通过toInput到达页面的:
原来是在servlet实现的,现在控制器承担了servlet的角色,,就交给控制器来完成。
@RequestMapping的话什么提交方式都无所谓了,一般去输入界面,是使用Get提交,就使用@GetMapping。@GetMapping只接受以Get提交方式来到网站的话才是他处理的。
测试:
package edu.mju.stuwork.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class StudentController {
@RequestMapping("/a") //指明,哪个请求是映射到这个方法.只要访问/a就是调用这个方法,RequestMapping的话什么提交方式都是无所谓的。
@ResponseBody//return "test now";的"test now"是一段文字,将作为我们返回的内容,作为一个返回的主体,在网页上会看到这段文字的出现。
public String test() throws Exception{//是一个和网页可以产生联系的方法
System.out.println("testing new ");
//return null;//是return null;,没有告诉他最终去哪里,所以会报错
return "test now";
}
@GetMapping("/student/input")//只要访问这个路径就是访问这个toInput
public String toInput() throws Exception{
System.out.println("Input student here!");
return null;
}
}
访问:
出现:
页面是404,是因为return null,没有告诉他去一个什么样的资源,到什么样的页面去显示。
原来,我们给出一个完整路径:
现在,我们只写文件名,没有写完整的路径,这时,我们要告诉系统该怎么解析,使"input_student"
变成request.getRequestDispatcher("WEB-INF/views/input_student.html").forward(request, response);
@GetMapping("/student/input")//只要访问这个路径就是访问这个toInput
public String toInput() throws Exception{
System.out.println("Input student here!");
return "input_student";//我们要他去到input_student.jsp,一般写上文件名就可以了。返回了一个视图,他的名字叫input_student。系统并不知道这是什么,要配置一个解析器,告诉系统这是什么。
}
我们要配置一个视图解析器,解析返回的视图的字符串信息,解析成地址。
视图解析器是一个bean,是由spring提供的,全称是内部资源视图解析器
配置视图解析器
在dispatcher-servlet.xml下添加:
<!-- 该视图解析器能够获取controller方法返回的视图信息,形成一个完整的页面路径 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property><!-- 前缀 -->
<property name="suffix" value=".jsp"></property><!-- 后缀 -->
</bean>
/WEB-INF/views/?????.jsp,我们返回的是???里的东西。
就是前缀后缀之间的内容,组成一个完整的路径。就会自动forward到这个路径上。
视图解析器做的是:给返回值,加上前缀,加上后缀,forward过去。
测试:
出现两个映射:
测试:
这个页面和原来是有差距的。
比如,访问这个路径,他就会把这个路径当做控制器来理解。在springmvc眼中,所有的路径都是控制器映射路径。他拿着这个路径去找控制器,是找不到叫做“bootstrap.min.css”的控制器。他就放弃了,所有,点击这个网址,出现404。
显然,bootstrap.min.css不是控制器,是一个普通的资源,是要放行的。要告诉springmvc这样的路径不是控制器路径,不要动他。
凡是不是控制器的资源在springmvc中称为静态资源(static resource)
在dispatcher-servlet.xml中添加:
<!-- 静态资源 -->
<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>
表示:凡是在resource目录下的,以及他的子目录下面的所有的目录都是静态资源
在webapp下新建文件夹“resources”:
将所有的静态资源存进去就OK了。
将input_student.xml中的一个路径修改一下:
确定是在resources下。
dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
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-4.3.xsd">
<!-- 本文件指定了springmvc需要处理的内容的处理机制,如果不是springmvc处理的,则一律放行 -->
<!-- springmvc的配置是用注解就可以了,十分方便 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 控制器部件扫描 (springmvc中servlet已经被controller这个概念封装掉了)
我们必须让springmvc知道其控制器所在的位置,以便加载控制器
包含基本包下头的子包
-->
<context:component-scan base-package="edu.mju.stuwork.controller"></context:component-scan>
<!-- 该视图解析器能够获取controller方法返回的视图信息,形成一个完整的页面路径 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 静态资源 -->
<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>
</beans>
测试:
运行,还是这样子:
发现路径错了。。
修改为一致,再运行:
查看网页源代码,点击这个链接:
有东西:
OK