文章是看楠哥的视频做的总结,自己还查阅了一些资料,文章也加了自己的总结,这篇博客可以帮助大家入门,还有一些知识大家如果用到的话可以到时候再去学习一下,我写这篇主要是为了方便后面复习。
Spring MVC是Spring Framework提供的Web组件,全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架,提供前端路由映射、视图解析等功能
Java Web开发者必须要掌握的技术框架
MVC是一种软件架构思想,把软件按照模型,视图,控制器来划分
Model:模型层,指工程中的JavaBean,用来处理数据
JavaBean分成两类:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>SpringMVCartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>SpringMVC Maven Webappname>
<url>http://www.example.comurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.19version>
dependency>
dependencies>
project>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.19version>
dependency>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
beans>
然后在web.xml 配置Spring MVC的DispatcherServlet
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 Applicationdisplay-name>
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
拦截请求其实就是说,只要是符合这个URL的请求都会进入到Spring MVC中去看看有没有对应的Handler./不会拦截.jsp的路径,但是会拦截.html等静态资源
3.springmvc.xml进行配置
<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.zyh.controller">context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/">property>
<property name="suffix" value=".jsp">property>
bean>
beans>
@Controller
public class HelloHandler {
/**
* 当客户端访问index请求时
* 直接自动关联到这个方法
* 执行这个方法后,会返回结果
* @return
*/
@RequestMapping("/index")
public String index(){
System.out.println("接收到了请求");
//返回逻辑视图 逻辑视图相当于视图的别名 通过这个找到物理视图,也就是真正的视图
//这里返回的只是页面的名称,不是完整的页面访问路径
return "index";
}
}
@Controller注解是为了让Spring IOC容器初始化时自动扫描到该Controller类;@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/;方法返回的结果是视图的名称index,该名称不是完整页面路径,最终会经过视图解析器解析为完整页面路径并跳转。
配置Tomcat
5. 测试
流程梳理
Spring MVC搭建成功
@RequestMapping
Spring MVC通过@RequestMapping注解把URL请求和业务方法进行映射,在控制器的类定义处以及方法定义处都可以添加@RequestMapping,在类定义处添加相当于多了一层访问路径
@RequestMapping常用参数
@RequestMapping(value = "/index",method = RequestMethod.POST)
public String index(){
System.out.println("接收到了请求");
//返回逻辑视图 逻辑视图相当于视图的别名 通过这个找到物理视图,也就是真正的视图
//注意:这里返回的只是页面名称,不是完整的页面访问路径
return "index";
}
params是对URL请求参数进行限制,不满足条件的URL无法访问该方法,需要在业务方法中获取URL的参数值。
Spring MVC可以自动完成数据类型转换,该工作是由HandlerAdapter来完成的
@RequestMapping("/restful/{id}/{name}")
public String restful(@PathVariable("id") Integer num, @PathVariable("name") String name){
System.out.println(num+"-"+name);
return "index";
}
@RequestMapping("/cookie")
public String getCookie(@CookieValue("JSESSIONID") String sessionId){
System.out.println(sessionId);
return "index";
}
Spring MVC会根据请求参数名和POJO属性名进行匹配,自动为该对象填充属性值,并且支持属性级联
首先创建实体类
为了方便测试,写一个addUser.jsp页面
<%--
Created by IntelliJ IDEA.
User: 17614
Date: 2022-07-04
Time: 21:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/hello/add" method="post">
<table>
<tr>
<td>编号:td>
<td>
<input type="text" name="id">
td>
tr>
<tr>
<td>姓名:td>
<td>
<input type="text" name="name">
td>
tr>
<tr>
<td>
<input type="submit" value="提交">
td>
tr>
table>
form>
body>
html>
启动Tomcat服务器
结果发现出现乱码问题
为了解决这个问题,我们只需要在web.xml配置文件中配置过滤器就可以了
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<%--
Created by IntelliJ IDEA.
User: 17614
Date: 2022-07-04
Time: 21:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/hello/add" method="post">
<table>
<tr>
<td>编号:td>
<td>
<input type="text" name="id">
td>
tr>
<tr>
<td>姓名:td>
<td>
<input type="text" name="name">
td>
tr>
<tr>
<td>地址编号:td>
<td>
<input type="text" name="address.code">
td>
tr>
<tr>
<td>地址信息:td>
<td>
<input type="text" name="address.value">
td>
tr>
<tr>
<td>
<input type="submit" value="提交">
td>
tr>
table>
form>
body>
html>
Spring MVC默认是通过转发的形式响应JSP,可以手动进行修改
@RequestMapping("/restful/{id}/{name}")
public String restful(@PathVariable("id") Integer num, @PathVariable("name") String name){
System.out.println(num+"-"+name);
return "index";
}
比如,我们想把它改成重定向的话
设置重定向的时候不能写逻辑视图,必须写明资源的物理路径,比如"rediect:/index.jsp"
转发
我们可以看到地址栏没变
@RequestMapping("/baseType")
@ResponseBody
public String baseType(int id){
return "id:"+id;
}
客户端HTTP请求中必须包含id参数,否则抛出500异常,因为id不能为null
@RequestMapping("/packageType")
@ResponseBody
public String packageType(Integer id){
return "id:"+id;
}
如果HTPP请求中没有包含id参数,不会报错,id的值就是null,会直接返回id:null给客户端,但是如果id=a,或者id=1.2,同样会抛出400异常,因为数据类型无法转换
@RequestMapping("/arrayType")
@ResponseBody
public String arrayType(String[] names){
StringBuffer buffer = new StringBuffer();
for (String str:names){
buffer.append(str).append(" ");
}
return "names:"+buffer.toString();
}
public class User {
private Integer id;
private String name;
private Address address;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", address=" + address +
'}';
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Address {
private Integer code;
private String value;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "Address{" +
"code=" + code +
", value='" + value + '\'' +
'}';
}
}
<%--
Created by IntelliJ IDEA.
User: 17614
Date: 2022-07-04
Time: 21:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/hello/add" method="post">
<table>
<tr>
<td>编号:td>
<td>
<input type="text" name="id">
td>
tr>
<tr>
<td>姓名:td>
<td>
<input type="text" name="name">
td>
tr>
<tr>
<td>地址编号:td>
<td>
<input type="text" name="address.code">
td>
tr>
<tr>
<td>地址信息:td>
<td>
<input type="text" name="address.value">
td>
tr>
<tr>
<td>
<input type="submit" value="提交">
td>
tr>
table>
form>
body>
html>
我们如果希望直接把User对象返回给浏览器展示的话
我们可以在springmvc.xml中添加一个消息转换器把中文乱码解决掉
前后端转换的数据称为消息
解决响应时乱码问题,springmvc.xml中配置转换器即可
总结一下关于乱码的问题
Spring MVC不支持List类型的直接转换,需要包装成Object
public class UserList {
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
@RequestMapping("/listType")
@ResponseBody
public String listType(UserList userList){
StringBuffer buffer = new StringBuffer();
for (User user:userList.getUserList()){
buffer.append(user);
}
return "用户:"+buffer.toString();
}
为了方便测试,我们要写一个表单
addList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/hello/listType" method="post">
用户1id:<input type="text" name="userList[0].id"><br>
用户1姓名:<input type="text" name="userList[0].name"><br>
用户2id:<input type="text" name="userList[1].id"><br>
用户2姓名:<input type="text" name="userList[1].name"><br>
用户3id:<input type="text" name="userList[2].id"><br>
用户3姓名:<input type="text" name="userList[2].name"><br>
<input type="submit" value="提交">
form>
body>
html>
接下来进行测试
注意:User类一定要有无参构造,否则抛出异常
因为要用到jQuery,所以,先把相关代码写进来,因为代码很长,我这边就不展示出来了
为了测试jQuery代码能不能使用,写一个json.jsp,然后在jsp中引入进来,写一个简单的代码测试一下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<script type="text/javascript" src="js/jquery-1.8.3.min.js">script>
<script type="text/javascript">
$(function (){
alert(123);
})
script>
body>
html>
启动服务器
如果,访问的时候,能够弹框123,说明jQuery可以使用,否则说明无法使用
我们可以看到并没有弹窗,说明应该是哪里出了问题,jsp代码没有问题,问题应该是jQuery没有引进来,我们可以在浏览器用F12,检查一下
发现json.jsp没有问题,问题出在jQuery上面,报500错误
分析一下原因,因为我们刚开始在web.xml中,配置的是所有的请求都会被DispatcherServlet拦截映射,但是现在我们访问的是实际存在的资源,逻辑请求需要映射,但是物理请求是不需要映射的。这个时候,它会把我们的物理请求也进行映射,在配置文件加上下面的代码就可以了
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.jsurl-pattern>
servlet-mapping>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<script type="text/javascript" src="js/jquery-1.8.3.min.js">script>
<script type="text/javascript">
$(function(){
var user = {
"id":1,
"name":"张三"
};
$.ajax({
url:"/hello/jsonType",
data:JSON.stringify(user),
type:"POST",
contentType:"application/json;charset=UTF-8",
dataType:"text",
success:function(data){
alert(data.id)
alert(data.name)
}
})
})
script>
body>
html>
我们发现出错了,打断点发现此时Ajax请求没有进入到我们刚刚写的方法。
因为我们现在传的参数是json格式的,json格式就需要我们在后端把json格式解析成Java对象,这里我们仅仅加上@RequestBody注解是不够的,我们需要借助第三方工具把json解析成Java对象,这里用到的工具是fastjson,所以我们要在pom.xml中,把相关依赖导入进来
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.75version>
dependency>
导入进来后,还需要在springmvc的配置文件中进行配置
springmvc.xml配置
<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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.zyh.controller">context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/">property>
<property name="suffix" value=".jsp">property>
bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8">property>
bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">bean>
mvc:message-converters>
mvc:annotation-driven>
beans>
调用Web资源给域对象传值
业务数据的绑定是指把业务数据绑定给JSP域对象,业务数据的绑定是由ViewResolver来完成的,开发时,我们先添加业务数据,再交给ViewResolver来绑定,我们重点是学习如何添加业务数据,Spring MVC提供了下面几种方式来添加业务数据:
Spring MVC在调用业务方法之前会先创建一个隐含对象作为业务数据的存储容器,设置业务方法的入参为Map类型,Spring MVC会把隐含对象的引用传递给入参
Model和Map类似,业务方法通过入参来完成业务数据的绑定
和Map,Model不同的是,ModelAndView不仅包含业务数据,同时也封装了视图信息,如果使用ModelAndView来处理业务数据,业务方法的返回值必须是ModelAndView对象
业务方法中对ModelAndView进行两个操作:
Spring MVC可以在业务方法种直接获取Servlet原生Web资源,只需要在方法定义时添加HttpServletRequest输入参数就可以,在方法体种直接使用request对象
先在pom.xml导入相关依赖
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
dependency>
Spring MVC还可以通过@ModelAttribute注解的方式添加业务数据,具体使用步骤如下:
@ModelAttribute的作用是当Handler接收到一个客户端请求以后,不管调用哪一个业务方法,都会优先调用被@ModelAttribute注解修饰的方法,并且把其返回值作为业务数据,再到业务方法,此时业务方法只需要返回视图信息就可以了,不需要返回业务数据,即使返回业务数据,也会被@ModelAttribute注解修饰的方法返回的数据所覆盖
域中的对象以key-value的形式存储,此时key默认值是业务数据所对应的类的类名首字母小写以后的结果
如果getUser没有返回值,则必须手动在该方法中填充业务数据,使用Map或者Model均可。
@ModelAttribute
public void getUser(Model model){
User user=new User();
user.setId(1);
user.setName("张三");
model.addAttribute("user",user);
}
@SessionAttribute这个注解不是给方法添加的,而是给类添加的
@SessionAttributes除了可以通过key值绑定,也可以通过业务数据的数据类型进行绑定
@Controller
@SessionAttributes(type=User.class)
public class ViewHandler{
...
}
@SessionAttributes可以同时绑定多个业务数据
@Controller
@SessionAttributes(type={User.class,Address.class})
public class ViewHandler{
...
}
或者
@Controller
@SessionAttributes(value={"user","address"})
public class ViewHandler{
...
}
Spring MVC默认情况下可以对基本类型进行类型转换
,例如可以将String转换为Integer,Double,Float等。但是Spring MVC并不能转换日期类型(java.util.Date),如果希望把字符串参数转换为日期类型,必须自定义类型转换器
1.创建DateConverter类,并且实现org.springframework.core.convert.converter.Converter接口,这样它就成为了一个自定义数据类型转换器,需要指定泛型
public class DateConverter implements Converter<String, Date> {
private String pattern;
public DateConverter(String pattern) {
this.pattern = pattern;
}
@Override
public Date convert(String s) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.pattern);
try {
return simpleDateFormat.parse(s);
} catch (ParseException e | java.text.ParseException e) {
e.printStackTrace();
}
return null;
}
}
2.在springmvc.xml中配置conversionService bean,这个bean是org.springframework.context.support.ConversionServiceFactoryBean的实例化对象,同时bean中必须包含一个converters属性,在其中注册所有需要使用的自定义转换器
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.zyh.converter.DateConverter">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd">constructor-arg>
bean>
list>
property>
bean>
<mvc:annotation-driven conversion-service="conversionService">mvc:annotation-driven>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/converter/student" method="post">
<input type="text" name="student"/>(1-张三-22)<br/>
<input type="submit" value="提交"/>
form>
body>
html>
接下来看看怎么解决中文乱码问题(搞了好久都要崩溃了)
<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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.zyh.controller">context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/">property>
<property name="suffix" value=".jsp">property>
bean>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.zyh.converter.DateConverter">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd">constructor-arg>
bean>
<bean class="com.zyh.converter.StudentConverter">bean>
list>
property>
bean>
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8">property>
bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">bean>
mvc:message-converters>
mvc:annotation-driven>
beans>
如果我们想要在浏览器显示的是JSON格式,中文乱码需要在业务方法中通过设置response的编码方式来解决,springmvc.xml的bean不起作用,如果不需要把业务数据转换成json格式,springmvc.xml的配置可以起到中文乱码的作用
1.URL传参更加简洁
2.完成不同终端之间的资源共享,RESTful提供了一套规范,不同终端之间只要遵守这个规范,就可以实现数据交互。
RESTful具体来说是四种表现形式,HTTP请求中四种请求类型(GET、POST、PUT、DELETE)分别表示四种常规操作,CRUD
两个终端要完成数据交互,基于RESTful的方式,增删改查操作分别需要使用不同的HTTP请求类型来访问。
传统的web开发中form表单只支持GET和POST请求,如何解决呢?我们可以通过添加HiddenHttpMethodFilter过滤器,可以把POST请求转为PUT或者DELETE
@Component
@RequestMapping("/rest")
public class RESTHandler {
// @RequestMapping(value = "/find",method = RequestMethod.GET)
@GetMapping("/find")
@ResponseBody
public String find(){
return "Hello";
}
@PostMapping("/save")
public void save(){
}
@PutMapping("/update")
public void update(){
}
@DeleteMapping("/delete")
public void delete(){
}
}
HiddenHttpMethodFilter检测请求参数是否包含_method参数,如果包含则取出它的值,并且判断请求类型之后完成请求类型的转换,然后继续传递
实现步骤:
1.在form表单中添加隐藏域标签,name为_method,value为PUT或DELETE
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/rest/update" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="提交">
form>
body>
html>
2.在web.xml中配置HiddenHttpMethodFilter
<filter>
<filter-name>HiddenHttpMethodFilterfilter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
接下来用一个小案例练练手
这个整合没有连接数据库
需求分析
记得在pom.xml添加JSTL的依赖
代码实现
1.JSP
2.Course实体类
public class Courese{
private Integer id;
private String name;
private double price;
还有对应的set,get方法,构造器
}
3.CourseRepository
@Repository
public class CourseRepository {
private Map<Integer, Course> map;
public CourseRepository(){
map=new HashMap<>();
map.put(1, new Course(1,"语文",70.0));
map.put(2, new Course(2,"数学",80.0));
map.put(3, new Course(3,"英语",90.0));
}
public Collection<Course> findAll(){
return map.values();
}
public Course findById(Integer id){
return map.get(id);
}
public void saveOrUpdate(Course course){
map.put(course.getId(), course);
}
public void deleteById(Integer id){
map.remove(id);
}
}
4.CourseController
package com.zyh.controller;
import com.zyh.pojo.Course;
import com.zyh.repository.CourseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletResponse;
/**
* @author zengyihong
* @create 2022--07--11 16:14
*/
@Controller
@RequestMapping("/course")
public class CourseController {
@Autowired
private CourseRepository courseRepository;
@GetMapping("/findAll")
public ModelAndView findAll() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("courseList");
modelAndView.addObject("list", courseRepository.findAll());
return modelAndView;
}
@DeleteMapping("/deleteById/{id}")
public String deleteById(@PathVariable("id") Integer id){
courseRepository.deleteById(id);
return "redirect:/course/findAll";
}
@PostMapping("/save")
public String save(Course course) {
courseRepository.saveOrUpdate(course);
/**
* 添加信息后要求返回列表页面
* 重定向
*/
return "redirect:/course/findAll";
}
@GetMapping("/findById/{id}")
public ModelAndView findById(@PathVariable("id") Integer id) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("edit");
modelAndView.addObject("courser", courseRepository.findById(id));
return modelAndView;
}
@PutMapping("/update")
public String update(Course course){
courseRepository.saveOrUpdate(course);
return "redirect:/course/findAll";
}
}
JSP
courseList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<table>
<tr>
<td>编号:td>
<td>名称:td>
<td>价格:td>
<td>操作:td>
tr>
<c:forEach items="${list}" var="course">
<tr>
<td>${course.id}td>
<td>${course.name}td>
<td>${course.price}td>
<td>
<form action="/course/deleteById/${course.id}" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="删除">
form>
<a href="/course/findById/${course.id}">修改a>
td>
tr>
c:forEach>
table>
body>
html>
save.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/course/save" method="post">
<table>
<tr>
<td>课程编号:td>
<td>
<input type="text" name="id">
td>
tr>
<tr>
<td>课程名称:td>
<td><input type="text" name="name">td>
tr>
<tr>
<td>课程价格:td>
<td> <input type="text" name="price">td>
tr>
<tr>
<td>
<input type="submit" value="提交">
td>
<td>
<input type="reset" value="重置">
td>
tr>
table>
form>
body>
html>
edit.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/course/update" method="post">
<input type="hidden" name="_method" value="PUT"/>
<table>
<tr>
<td>课程编号:td>
<td>
<input type="text" name="id" value="${courser.id}">
td>
tr>
<tr>
<td>课程名称:td>
<td>
<input type="text" name="name" value="${courser.name}">
td>
tr>
<tr>
<td>课程价格:td>
<td>
<input type="text" name="price" value="${courser.price}">
td>
tr>
<tr>
<td>
<input type="submit" value="提交">
td>
tr>
table>
form>
body>
html>
1.底层使用的是Apache fileupload 组件完成上传功能,Spring MVC只是对其进行了封装,简化开发,pom.xml
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.8.0version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.4version>
dependency>
springmvc.xml
为了把二进制数据解析成对象
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">bean>
2.JSP页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="/file/upload" method="post" enctype="multipart/form-data">
<input type="file" name="img"/>
<input type="submit" value="提交">
form>
<img src="${src}"/>
body>
html>
@Component
@RequestMapping("/file")
public class FileHandler {
/**
* 文件是以二进制流传输的
* @param img
* @return
*/
@PostMapping("/upload")
public String upload(@RequestParam("img") MultipartFile img, HttpServletRequest request){
if (img.getSize()>0){
String path = request.getSession().getServletContext().getRealPath("file");
String filename = img.getOriginalFilename();
File descFile=new File(path, filename);
try {
img.transferTo(descFile);
request.setAttribute("src", "/file/"+filename);
} catch (IOException e) {
e.printStackTrace();
}
}
return "upload";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>多文件上传title>
head>
<body>
<form action="/file/uploads" method="post" enctype="multipart/form-data">
file1:<input type="file" name="imgs"/><br>
file2:<input type="file" name="imgs"/><br>
file3:<input type="file" name="imgs"/><br>
<input type="submit" value="提交"/>
form>
<c:forEach items="${pathList}" var="path">
<img src="${path}" width="300px">
c:forEach>
@PostMapping("/uploads")
public String uploads(@RequestParam("imgs") MultipartFile[] imgs,HttpServletRequest request){
List<String> pathList=new ArrayList<>();
for (MultipartFile img:imgs){
if (img.getSize()>0){
String path = request.getSession().getServletContext().getRealPath("file");
String filename = img.getOriginalFilename();
File descFile=new File(path, filename);
try {
img.transferTo(descFile);
pathList.add("/file/"+filename);
} catch (IOException e) {
e.printStackTrace();
}
}
}
request.setAttribute("pathList", pathList);
return "uploads";
}
JSP页面通过超链接点击进行下载
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件下载title>
head>
<body>
<a href="/file/download?fileName=皮卡丘.jpg">皮卡丘.jpga>
<a href="/file/download?fileName=柯南.png">柯南.pnga>
<a href="/file/download?fileName=springmvc.png">springmvc.pnga>
body>
html>
Handler
/**
* 根据文件的名字进行下载
*/
@GetMapping("/download")
public void download(String fileName,
HttpServletRequest request,
HttpServletResponse response) {
if (fileName!=null){
String path = request.getSession().getServletContext().getRealPath("file");
File file=new File(path,fileName);
OutputStream out=null;
if (file.exists()){
//设置下载文件
response.setContentType("applicationContext/force-download");
//设置文件名
response.setHeader("Context-Disposition", "attachment;filename="+fileName);
try {
out=response.getOutputStream();
out.write(FileUtils.readFileToByteArray(file));
out.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。
要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义。
通过实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
/**
* 在目标Handler(方法)执行前执行
* 返回true:执行Handler方法
* 返回false:阻止目标Handler方法执行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("目标Handler执行前执行MyInterceptor---->preHandle方法...");
return true;
}
/**
* 在目标Handler(方法)执行后,视图生成前执行
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("目标Handler执行后,视图执行前执行MyInterceptor---->postHandle方法...");
}
/**
* 在目标方法执行后,视图生成后执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("目标Handler执行后,视图执行后执行MyInterceptor---->afterCompletion方法...");
}
}
拦截器配置1
<mvc:interceptors>
<bean class="com.zyh.interceptor.MyInterceptor">bean>
mvc:interceptors>
拦截器配置方式2
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/hello/*"/>
<bean class="com.zyh.interceptor.MyInterceptor">bean>
mvc:interceptor>
mvc:interceptors>
Spring MVC框架支持多个拦截器的配置,从而构成拦截器链,对客户端进行多次拦截操作
过滤器配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.zyh.interceptor.MyInterceptor">bean>
mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.zyh.interceptor.MyInterceptor2">bean>
mvc:interceptor>
mvc:interceptors>
自定义第二个过滤器
public class MyInterceptor2 implements HandlerInterceptor {
/**
* 在目标Handler(方法)执行前执行
* 返回true:执行Handler方法
* 返回false:阻止目标Handler方法执行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("2.目标Handler执行前执行MyInterceptor2---->preHandle方法...");
return true;
}
/**
* 在目标Handler(方法)执行后,视图生成前执行
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("3.目标Handler执行后,视图执行前执行MyInterceptor2---->postHandle方法...");
}
/**
* 在目标方法执行后,视图生成后执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("5.目标Handler执行后,视图执行后执行MyInterceptor2---->afterCompletion方法...");
}
}
Handler
@RequestMapping("/hello")
@Controller
public class HelloContro
@RequestMapping("/packageType")
@ResponseBody
public String packageType(@RequestParam(value = "id", required = true) Integer id) {
System.out.println("拦截的方法...");
return "id=" + id;
}
}