1.基本配置
1.1环境搭建
1.数据库
CREATE DATABASE `ssmbuild`;
USE `ssmbuild`;
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT(11) NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');
2.新建一Maven项目:ssmbuild , 添加web的支持,连接数据库,导入相关的pom依赖
<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!--Servlet - JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.13</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
3.包结构
4.mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
数据库配置文件 database.properties(因为用的c3p0所以要jdbc.)
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
jdbc.username=root
jdbc.password=1234
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}
1.2Mybatis层
1.2.1dao层
BookMapper接口
public interface BookMapper {
//增加一本书
int addBooks(Books books);
//删除一本书
int deleteBooks(int bookID);
//更新一本书
int updataBooks(Books books);
//查询一本书
Books queryBooksById(int bookID);
//查询所有书
List<Books> queryBooks();
}
BookMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="moli.dao.BookMapper">
<insert id="addBooks" parameterType="Books">
insert into ssmbuild.books (bookName,bookCounts,detail) values (#{bookName},#{bookCounts},#{detail})
</insert>
<delete id="deleteBooks" parameterType="int">
delete from ssmbuild.books where bookId=#{bookID}
</delete>
<update id="updataBooks" parameterType="Books">
update ssmbuild.books set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail}
where bookID=#{bookID}
</update>
<select id="queryBooksById" resultType="Books">
select * from ssmbuild.books where bookID=#{bookID}
</select>
<select id="queryBooks" resultType="Books">
select * from ssmbuild.books
</select>
</mapper>
注册:mybatis-config.xml
<!--连接数据库,交给spring去做-->
<typeAliases>
<package name="moli.pojo"/>
</typeAliases>
<mappers>
<mapper class="moli.dao.BookMapper"/>
</mappers>
1.2.2service层
public interface BookService {
//增加一本书
int addBooks(Books books);
//删除一本书
int deleteBooks(int id);
//更新一本书
int updataBooks(Books books);
//查询一本书
Books queryBooksById(int id);
//查询所有书
List<Books> queryBooks();
}
public class BookServiceImpl implements BookService {
private BookMapper bookMapper;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public int addBooks(Books books) {
return bookMapper.addBooks(books);
}
public int deleteBooks(int id) {
return bookMapper.deleteBooks(id);
}
public int updataBooks(Books books) {
return bookMapper.updataBooks(books);
}
public Books queryBooksById(int id) {
return bookMapper.queryBooksById(id);
}
public List<Books> queryBooks() {
return bookMapper.queryBooks();
}
}
1.3spring层
Spring就是一个大杂烩,一个容器!
1.配置Spring整合MyBatis,我们这里数据源使用c3p0连接池:spring-dao.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.关联数据库配置文件-->
<context:property-placeholder location="classpath:database.properties"/>
<!--2.连接池:
dbcp:半自动化操作,不能自动连接
c3p0:自动化操作(自动化加载配置文件,并且可以自动的加载到对象中去)
druid(德鲁伊)、hikari-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!--3.sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="moli.dao"/>
</bean>
</beans>
2.Spring整合service层,spring-service.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"
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">
<!-- 1.扫描service相关的bean -->
<context:component-scan base-package="moli.service" />
<!--2.BookServiceImpl注入到IOC容器中-->
<bean id="BookServiceImpl" class="moli.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!-- 3.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
1.4SpringMVC层
web.xml
<?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">
<!--DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--一定要注意:我们这里加载的是总的配置文件,之前被这里坑了!-->
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--encodingFilter-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Session过期时间-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
spring-mvc.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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.开启springmvc注解驱动-->
<mvc:annotation-driven/>
<!--2.静态资源默认servlet配置-->
<mvc:default-servlet-handler/>
<!-- 3.配置jsp 显示ViewResolver视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="moli.controller" />
</beans>
Spring配置整合文件,applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:spring-dao.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="classpath:spring-mvc.xml"/>
</beans>
2.书籍的CRUD
问题:bean不存在
排错步骤:
- 查看这个bean是否注入成功
- Junit单元测试,看我们的代码是否能够查询出来结果
- 以上没问题就说明问题不在底层,是spring出现了问题
- springmvc,整合的时候我们没有调用servce层的bean
- applicationContext.xml没有注入bean
- web.xml中没有绑定配置文件
2.1controller层
Controller层调用Service层
@Controller
@RequestMapping("/book")
public class BookController {
//查询全部书籍
@Autowired
@Qualifier("BookServiceImpl")
private BookService bookService;
@RequestMapping("/allBook")
public String allBook(Model model){
List<Books> books = bookService.queryBooks();
model.addAttribute("books",books);
return "allBook";
}
//增加书籍
@RequestMapping("/toaddBook")
public String addBook(){
return "addBook";
}
@RequestMapping("/addBook")
public String addbook1(Books books){
System.out.println("books:"+books);
bookService.addBooks(books);
return "redirect:/book/allBook";
}
//修改书籍
@RequestMapping("/toupdataBook")
public String updatabook(int id,Model model){
Books books = bookService.queryBooksById(id);
model.addAttribute("Qbook",books);
return "updataBook";
}
@RequestMapping("/updataBook")
public String updatabook1(Books books){
System.out.println(books);
int i = bookService.updataBooks(books);
if (i>0){
System.out.println("成功");
}
return "redirect:/book/allBook";
}
//删除书籍
@RequestMapping("/deleteBook/{bookid}")
public String delete(@PathVariable("bookid") int id){
bookService.deleteBooks(id);
return "redirect:/book/allBook";
}
}
2.2前端页面
index.jsp
<head>
<title>首页</title>
<style>
a{
text-decoration: none;
font-size: 18px;
color: black;
}
h3{
width: 180px;
height: 45px;
margin: 100px auto;
text-align: center;
line-height: 45px;
background: bisque;
border-radius: 5px;
}
</style>
</head>
<body>
<h3>
<a href="${pageContext.request.contextPath}/book/allBook">进入书籍展示</a>
</h3>
</body>
allBook.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>查询全部书籍</title>
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>书籍列表-----------显示所有书籍</small>
</h1>
</div>
</div>
</div>
<div>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toaddBook">增加书籍</a>
</div>
<div>
<%--搜索框功能不能用a标签,要用form表单才能实现--%>
<form action="${pageContext.request.contextPath}/book/queryBook" method="post" class="form-inline" style="float: right">
<input type="text" name="queryBook" class="form-control" placeholder="请输入要查询的书籍名称">
<input type="submit" value="查询" class="btn btn-primary">
</form>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<%--table-hover鼠标悬停高亮的表格,table-striped 表格实现隔行换色--%>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>书籍编号</th>
<th>书籍名称</th>
<th>书籍数量</th>
<th>书籍详情</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%--书记从数据库中查询拿出来,遍历books:foreach--%>
<c:forEach var="book" items="${books}">
<tr>
<td>${book.bookID}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
<td>
<a href="${pageContext.request.contextPath}/book/toupdataBook?id=${book.bookID}">修改</a>
|
<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
addBook.jsp
<head>
<title>增加书籍</title>
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>增加书籍</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/book/addBook" method="post">
<div class="form-group">
<label for="bkname">书籍名称</label>
<input type="text" name="bookName" class="form-control" id="bkname" required>
</div>
<div class="form-group">
<label for="bkcounts">书籍数量</label>
<input type="text" name="bookCounts" class="form-control" id="bkcounts" required>
</div>
<div class="form-group">
<label for="detail">书籍详情</label>
<input type="text" name="detail" class="form-control" id="detail" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="添加">
</div>
</form>
</div>
</body>
updataBook.jsp
<head>
<title>修改书籍</title>
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>修改书籍</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/book/updataBook" method="post">
<%--出现问题:我们提交了修改的sql请求,但是请求失败,是因为我们没有传入bookID的值,这里就需要隐藏域
初次考虑以为是事务问题,发现并不是;再次尝试看我们的sql请求是否提交,发现没有提交,修改未完成--%>
<input type="hidden" name="bookID" value="${Qbook.bookID}">
<div class="form-group">
<label for="bkname">书籍名称</label>
<input type="text" name="bookName" value="${Qbook.bookName}" class="form-control" id="bkname"required>
</div>
<div class="form-group">
<label for="bkcounts">书籍数量</label>
<input type="text" name="bookCounts" value="${Qbook.bookCounts}" class="form-control" id="bkcounts" required>
</div>
<div class="form-group">
<label for="detail">书籍详情</label>
<input type="text" name="detail" value="${Qbook.detail}" class="form-control" id="detail" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
3.增加搜索功能
从底层改起!
dao:添接口,接口实现类
//根据名字查询书籍
Books queryBookByName(@Param("bookName") String bookName);
<select id="queryBookByName" resultType="Books">
select * from ssmbuild.books where bookName=#{bookName}
</select>
service:添接口,接口实现类
Books queryBookByName(String bookName);
public Books queryBookByName(String bookName) {
return bookMapper.queryBookByName(bookName);
}
前端:
<div>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toaddBook">增加书籍</a>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">查询全部书籍</a>
</div>
<div>
<%--搜索框功能不能用a标签,要用form表单才能实现--%>
<form action="${pageContext.request.contextPath}/book/queryBook" method="post" class="form-inline" style="float: right">
<span style="color: red;font-weight: bold">${err}</span>
<input type="text" name="queryBookName" class="form-control" placeholder="请输入要查询的书籍名称">
<input type="submit" value="查询" class="btn btn-primary">
</form>
</div>
Controller:
@RequestMapping("/queryBook")
public String query(String queryBookName,Model model){
Books book = bookService.queryBookByName(queryBookName);
System.err.println(book);
List<Books> books = new ArrayList<>();
books.add(book);
if (book==null){
bookService.queryBooks();
model.addAttribute("err","未查到书籍");
}
model.addAttribute("books",books);
return "allBook";
}
4.Ajax(阿贾克斯)
4.1简介
Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML,异步不刷新)。
Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。Google Suggest能够自动帮你完成搜索单词。
Google Suggest 使用 AJAX 创造出动态性极强的 web 界面:当您在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。例如:
传统的网页(即不用ajax技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页。
使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。
利用AJAX可以做:
- 注册时,输入用户名自动检测用户是否已经存在。
- 登陆时,提示用户名密码错误。
- 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。
4.2伪造Ajax
我们可以使用前端的一个iframe标签来伪造一个ajax的样子:
新建一个module :mvc-06-ajax , 导入web支持,在项目结构中导入jar包,编写一个controller测试,框架没问题。
新建一个html,伪造Ajax
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>iframe测试</title> <script> function go() { var url = document.getElementById("url").value; document.getElementById("iframe1").src=url; } </script> </head> <body> <div> <p>请输入地址:</p> <p> <input type="text" id="url" value="http://www.sy-xykj.com/dongman/mingxingdazhentandiqiji/1-5.html"> <input type="button" value="提交" onclick="go()"> </p> </div> <div> <iframe id="iframe1" style="width: 100%;height: 500px"></iframe> </div> </body> </html>
4.3jQuery
4.3.1简介
jQuery是一个优秀的JavaScript库,是一个凭借简洁的语法和跨平台的兼容性,极大地简化了JavaScript开发人员遍历HTML文档,操作DOM,执行动画和开发Ajax的操作。jQuery封装了很多预定义的对象和函数。
Ajax的核心是XMLHttpRequest对象(XHR),XHR为向服务器发送请求和解析服务器响应提供了接口,能够以异步方式从服务器获取新数据。
jQuery 提供多个与 AJAX 有关的方法。
通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON ,同时您能够把这些外部数据直接载入网页的被选元素中。
jQuery 不是生产者,而是大自然搬运工。它是一个库,里面有很多Js函数(方法)。
jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!
jQuery下载:https://jquery.com/download/
每一个web开发都要在applicationContext.xml中过滤静态资源:
<mvc:default-servlet-handler />
jQuery.ajax(...)
部分参数:
url:请求地址
type:请求方式,GET、POST(1.9.0之后用method)
headers:请求头
data:要发送的数据
contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
async:是否异步
timeout:设置请求超时时间(毫秒)
beforeSend:发送请求前执行的函数(全局)
complete:完成之后执行的回调函数(全局)
success:成功之后执行的回调函数(全局)
error:失败之后执行的回调函数(全局)
accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
dataType:将服务器端返回的数据转换成指定类型
"xml": 将服务器端返回的内容转换成xml格式
"text": 将服务器端返回的内容转换成普通文本格式
"html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
"script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
"json": 将服务器端返回的内容转换成相应的JavaScript对象
"jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数
4.3.2使用
<head>
<title>$Title$</title>
<%--引入jQuery--%>
<script src="${pageContext.request.contextPath}/statics/js/jquery.js"></script>
<script>
function a() {
$.post({
url: "${pageContext.request.contextPath}/a1",
data:{"name":$("#username").val()},
success:function (data,status) {
alert(data);
console.log(status)//状态码200,404,500
}
});
}
</script>
</head>
<body>
<%--失去焦点的时候,发起一个请求(携带信息)到后台--%>
用户名:<input type="text" id="username" οnblur="a()">
</body>
@RequestMapping("/a1")
public void a1(String name, HttpServletResponse response) throws IOException {
System.out.println("a:param:====>"+name);
if ("小明".equals(name)){
response.getWriter().print("true");
}else {
response.getWriter().print("false");
}
}
4.3.3异步加载数据
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
public String name;
public int age;
public String sex;
}
@RequestMapping("/a2")
public List<User> a2(){
ArrayList<User> list = new ArrayList<>();
list.add(new User("小明",2,"男"));
list.add(new User("小红",4,"女"));
list.add(new User("小王",10,"男"));
return list;
}
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery.js"></script>
<script>
$(function () {
$("#btn").click(function () {
//$.post(url,data可省略,callback)
$.post("${pageContext.request.contextPath}/a2",function (data) {
var html="";//用来做字符串拼接
//let和var是一样的,但是let更安全只在for循环内生效
for (let i=0 ;i<data.length;i++){
html+="<tr>"+
"<td>"+data[i].name+"</td>"+
"<td>"+data[i].age+"</td>"+
"<td>"+data[i].sex+"</td>"+
"</tr>"
}
$("#content").html(html);
})
})
})
</script>
</head>
<body>
<input type="button" id="btn" value="加载数据">
<table>
<thead>
<tr>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
</thead>
<tbody id="content">
<%--从后台加载过来的数据--%>
</tbody>
</table>
</body>
4.3.4验证用户名
@RequestMapping("/a3")
public String a3(String name,String pwd){
String msg="";
if (name!=null){
if ("admin".equals(name)){
msg="ok";
}else {
msg="用户名有误";
}
}
if (pwd!=null){
if ("1234".equals(pwd)){
msg="ok";
}else {
msg="密码有误";
}
}
return msg;
}
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/statics/js/jquery.js"></script>
<script>
function n() {
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"name":$("#name").val()},
success:function (data) {
if (data.toString()==="ok"){
$("#nameinfo").css("color","green")
}else {
$("#nameinfo").css("color","red");
}
$("#nameinfo").html(data)
}
})
}
function p() {
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"pwd":$("#pwd").val()},
success:function (data) {
if (data.toString()==="密码有误"){
$("#pwdinfo").css("color","red");
}else {
$("#pwdinfo").css("color","green");
}
$("#pwdinfo").html(data)
}
})
}
</script>
</head>
<body>
<p>
用户名:<input type="text" id="name" οnblur="n()">
<span id="nameinfo"></span>
</p>
<p>
密码:<input type="text" id="pwd" οnblur="p()">
<span id="pwdinfo"></span>
</p>
</body>
5.拦截器
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
过滤器与拦截器的区别:拦截器是AOP思想的具体应用。拦截器更高效一点。
过滤器:
- servlet规范中的一部分,任何java web工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
拦截器 :
- 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的
5.1自定义拦截器
想要自定义拦截器,必须实现 HandlerInterceptor 接口。
新建一个Moudule ,添加web支持,配置web.xml 和 applicationContext.xml 文件,导入jar包,配置tomcat测试一下。
编写一个拦截器
public class MyInterceptor implements HandlerInterceptor { //return true;会执行下一个拦截器,并且放行去执行controller的方法 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("=========处理前========="); return true; } //作用:用来做拦截日志 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("=========处理后=========="); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("=======清理==========="); } }
配置拦截器
<!--配置拦截器--> <mvc:interceptors> <mvc:interceptor> <!--/** 包括路径及其子路径--> <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截--> <!--/admin/** 拦截的是/admin/下的所有--> <mvc:mapping path="/**"/> <!--bean配置的就是拦截器--> <bean class="moli.config.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
测试
@RequestMapping("/t") public String test(){ System.out.println("sd"); return "ok"; }
5.2登录判断验证
index.jsp
<a href="${pageContext.request.contextPath}/user/tologin">登陆页面</a><br>
<a href="${pageContext.request.contextPath}/user/main">首页</a>
login.jsp
<form action="${pageContext.request.contextPath}/user/login" method="post">
用户名:<input type="text" name="name"/><br>
密码:<input type="text" name="pwd"/><br>
<input type="submit" value="提交"/><br>
</form>
main.jsp
<h1>首页</h1>
<span>${nameinfo}</span>
<p>
<a href="${pageContext.request.contextPath}/user/goout">注销</a>
</p>
@Controller
@RequestMapping("/user")
public class LoginController {
@RequestMapping("/main")
public String main(){
return "main";
}
@RequestMapping("/tologin")
public String tologin(){
return "login";
}
@RequestMapping("/login")
public String login(String name , String pwd, HttpSession session){
//把用户信息存在session中
System.out.println("name="+name);
session.setAttribute("nameinfo",name);
return "main";
}
@RequestMapping("/goout")
public String out( HttpSession session){
session.removeAttribute("nameinfo");
return "login";
}
}
拦截器及配置:
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//放行:判断什么情况下登录了
//用户已经登录可以放行
HttpSession session = request.getSession();
if (session.getAttribute("nameinfo")!=null){
return true;
}
//已经在登陆页面可以放行
if (request.getRequestURI().contains("/user/tologin")){
return true;
}
//已经在登陆页面可以放行
if (request.getRequestURI().contains("/user/login")){
return true;
}
//用户没有登录跳转到登陆页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
<mvc:interceptor>
<mvc:mapping path="/user/*"/>
<bean class="moli.config.LoginInterceptor"/>
</mvc:interceptor>
6.文件上传和下载
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。
Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。Spring MVC使用Apache Commons FileUpload技术实现了一个multipartResolver实现类:CommonsMultipartResolver。
导入jar包
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
6.1上传
index.jsp
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
配置bean:multipartResolver
【注意!!!这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!】
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
两种上传文件的方式:
@Controller
public class fileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException{
//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接回到首页!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名 : "+uploadFileName);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream(); //文件输入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
//读取写出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
// 采用file.transferTo 来保存上传的文件
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "redirect:/index.jsp";
}
}
6.2下载
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "基础语法.jpg";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}