SpringMVC
ssm: Spring SpringMVC Mybatis
MCV
- 模型 (dao, service)
- 视图 (jsp)
- 控制器 (servlet)
1.Java web
- servlet
- doGet
- doPost
- web.xml
- 注册servlet
- 映射
- jsp
2.SpringMVC-hello
2.1 start
-
web.xml
- 注册 DispatcherServlet
- 映射
<?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> <!--关联一个springmvc配置文件: [servlet-name]-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别 1--> <load-on-startup>1</load-on-startup> </servlet> <!-- / 匹配所有请求,不包括 .jsp /* 匹配所有请求 包括 .jsp --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
springmvc-servlet.xml
- 注册bean
- 处理器映射器 BeanNameUrlHandlerMapping
- 处理器适配器 SimpleControllerHandlerAdapter
- 视图解析器 InternalResourceViewResolver
- 控制器
<?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"> <!--处理器映射器--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!--处理器适配器--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"></property> <!--后缀--> <property name="suffix" value=".jsp"></property> </bean> <bean id="/hello" class="cqu.ma.controller.HelloController"></bean> </beans>
- 注册bean
-
控制器
package cqu.ma.controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg","hello springMVC"); mv.setViewName("hello"); // : /WEB-INF/jsp/hello.jsp return mv; } }
-
jsp
/WEB-INF/jsp/hello.jsp
<%-- Created by IntelliJ IDEA. User: ma Date: 2021/8/12 Time: 16:36 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> ${msg} </body> </html>
404 错误排查
- web 项目依赖的包没有打包(检查控制台输出,项目缺少依赖的包)
- 解决:项目结构–>Artifacts–>模块–>output layout :在WEB-INF目录下新建目录lib 并添加依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YZ7cW0L-1629202684029)(C:\Users\ma\MyWorkplace\code\LongWayOfJava\5.2-SpringMVC.assets\QQ截图20210812171921.png)]
3.2 使用注解
-
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> <!--关联一个springmvc配置文件: [servlet-name]-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别 1--> <load-on-startup>1</load-on-startup> </servlet> <!-- / 匹配所以请求,不包括 .jsp /* 匹配所以请求 包括 .jsp --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
springmvc-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: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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--自动扫描包--> <context:component-scan base-package="cqu.ma.controller"></context:component-scan> <!--让Spring MVC不处理静态资源--> <mvc:default-servlet-handler></mvc:default-servlet-handler> <!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping注解完成映射关系 要@RequestMapping注解生效 必须向上下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理 而 <mvc:annotation-driven> 配置帮助我们自动完成上述两个实例的注入 --> <mvc:annotation-driven></mvc:annotation-driven> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
-
controller
package cqu.ma.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { @RequestMapping("/h1") //@RequestMapping 也可注解类,则访问路径 ip:8080/[项目名]/类requestMapping/方法requestMapping/ public String hello(Model model){ //封装数据 model.addAttribute("msg","hello springmvc"); return "hello"; //会被视图解析器处理 jsp路径 : /WEB-INF/jsp/hello.jsp } }
总结
使用springMVC必须配置的三大件:
- 处理器映射器
- 处理器适配器
- 视图解析器
通常,只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动
3.Restful 风格
package cqu.ma.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RestfulController {
// add?a=1&b=4 ==> 函数参数会获取url上参数
@RequestMapping("/add") //@RequestMapping(value="/add", method=RequestMethod.GET) == @GetMapping("/add")
public String test1(int a, int b, Model model){
model.addAttribute("msg",a+"+"+b+"="+(a+b));
return "test";
}
// restful add/1/2 ==> a=1 b=2
@RequestMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
model.addAttribute("msg",a+"+"+b+"="+(a+b));
return "test";
}
}
4.重定向与转发
使用servlet api
HttpServletRequest
HttpServletResponse
package cqu.ma.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public void test(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
}
springmvc
-
不配置视图解析器
-
@RequestMapping("/m1/t2") public String test1(Model model){ model.addAttribute("msg","modelTest1.test1"); //转发 return "/WEB-INF/jsp/test.jsp"; // return "forward:/WEB-INF/jsp/test.jsp"; //重定向 //return "redirect:index.jsp"; }
-
配置了视图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean>
-
转发(默认)
return "test"; //==> /WEB-INF/jsp/test.jsp
重定向
return "redirect:/index.jsp";
5.数据处理
处理提交的数据
-
提交的域名称与处理方法参数名一致
// 提交: http://localhost:8080/hello?name=m @RequestMapping("/hello") public String hello(String name){ System.out.println(name); return "hello"; }
-
不一致(添加注解)
// 提交: http://localhost:8080/hello?name=m @RequestMapping("/hello") public String hello(@RequetParam("name") String userName){ System.out.println(userName); return "hello"; }
-
提交一个对象
要求提交的表单域和对象属性名一致,参数使用对象即可
User
public class User{ private int id; private String name; //getter and setter //toString }
url
http://localhost:8080/user?id=1&name=xxx
处理方法
@RequestMapping("/user") public String user(User user){ System.out.println(user); return "hello"; }
6.乱码问题解决
web.xml
<!--配置过滤器-->
<!--spring encoding 过滤器-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
7.json
javascript JSON
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
var user = {
name:"模糊",
age:3,
sex:"男"
};
var json = JSON.stringify(user);
console.log(json);
user2 = JSON.parse(json);
console.log(user2);
</script>
</head>
<body>
Controller 返回 JSON 数据
-
jackson
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.4</version> </dependency>
-
fastjson
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency>
jackson
controller
package cqu.ma.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import cqu.ma.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
public class UserController {
@RequestMapping(value = "/j1")
@ResponseBody //不会走视图解析器,会直接返回 字符串
public String json1() throws JsonProcessingException {
User user = new User("模糊",19,"男");
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(user);
return str;
}
@RequestMapping(value = "/j2")
@ResponseBody //不会走视图解析器,会直接返回 字符串
public String json2() throws JsonProcessingException {
User user = new User("模糊",19,"男");
User user2 = new User("模糊2",18,"女");
User user3 = new User("模糊3",18,"女");
User user4 = new User("模糊4",18,"女");
List<User> list = new ArrayList<>();
list.add(user);
list.add(user2);
list.add(user3);
list.add(user4);
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(list);
return str;
}
@RequestMapping(value = "/j3")
@ResponseBody //不会走视图解析器,会直接返回 字符串
public String json3() throws JsonProcessingException {
Date date = new Date();
ObjectMapper mapper = new ObjectMapper();
// 返回时间戳
//String str = mapper.writeValueAsString(date);
//自定义日期格式
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//String str = mapper.writeValueAsString(format.format(date));
//使用ObjectMapper
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
mapper.setDateFormat(format);
String str = mapper.writeValueAsString(date);
return str;
}
}
springmvc-servlet.xml
json字符编码配置
<!--json 字符编码配置-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"></constructor-arg>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"></property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
fastJson
fastJson 的三个主要的类
- JSONObject 代表 json 对象
- JSONArray 代表 json 对象数组
- JSON 代表 JSONObject 和 JSONArray 的转化
@RequestMapping("/fj1")
@ResponseBody
public String fastJson1(){
User user = new User("模糊",19,"男");
User user2 = new User("模糊2",18,"女");
User user3 = new User("模糊3",18,"女");
User user4 = new User("模糊4",18,"女");
List<User> list = new ArrayList<>();
list.add(user);
list.add(user2);
list.add(user3);
list.add(user4);
return JSON.toJSONString(list);
}
8.整合:SSM
8.1 环境
- IDEA
- Mysql
- Tomcat 9
- Maven
8.2 数据库 (mysql)
CREATE DATABASE ssmbuild;
USE ssmbuild;
CREATE TABLE books(
bookID INT(10) NOT NULL AUTO_INCREMENT,
bookName VARCHAR(100) NOT NULL,
bookCounts INT(11) NOT NULL,
detail VARCHAR(200) NOT NULL,
KEY bookID(bookID)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO books(bookID, bookName, bookCounts, detail) VALUES
(1,'Java',1,'从入门到放弃'),
(2,'Mysql',10,'从删库到跑路'),`books`
(3,'Linux',5,'从进门到进牢');
8.3 项目依赖
<!--
junit
数据库驱动,连接池
servlet
jsp
mybatis
mybatis-spring
spring
-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<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.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
8.4 mybatis层
db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
#改正:name=root 见8.7:错误2
username=root
password=root
xml配置文件
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>
<!--配置数据源 交给Spring-->
<typeAliases>
<package name="cqu.ma.pojo"/>
</typeAliases>
<mappers>
<mapper resource="cqu/ma/dao/BookMapper.xml"></mapper>
</mappers>
</configuration>
Mapper.xml cqu/ma/dao/BookMapper.xml
(resources/
路径下)
<?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="cqu.ma.dao.BookMapper">
<insert id="addBook" parameterType="Books">
insert into ssmbuild.books(bookName, bookCounts, detail)
values(#{bookName},#{bookCounts},#{detail})
</insert>
<delete id="deleteBookById" parameterType="_int">
delete from ssmbuild.books where bookID=#{id}
</delete>
<update id="updateBook" parameterType="Books">
update ssmbuild.books set bookName=#{bookName}, bookCounts=#{bookCounts}, detail=#{detail}
where bookID=#{bookID}
</update>
<select id="queryBookById" resultType="Books">
select * from ssmbuild.books where bookID=#{id}
</select>
<select id="queryAllBook" resultType="Books">
select * from ssmbuild.books;
</select>
</mapper>
java 类
- dao
- interface BookMapper
- service
- interface BookService
- BookServiceImpl
- pojo
- Books
8.5 Spring层 整合 Mybatis
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 http://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:db.properties"></context:property-placeholder>
<!--2.连接池
dbcp: 半自动化操作, 不能自动连接
c3p0: 自动化操作 (自动化加载配置文件,并且可以自动设置到对象中)
druid
hikari
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="maxPoolSize" value="30"></property>
<property name="minPoolSize" value="10"></property>
<property name="autoCommitOnClose" value="false"></property>
<property name="checkoutTimeout" value="10000"></property>
<property name="acquireRetryAttempts" value="2"></property>
</bean>
<!--3.sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!--绑定Mybatis 配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<!--配置dao接口扫描包,动态实现dao接口可以注入到Spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!--扫描包-->
<property name="basePackage" value="cqu.ma.dao"></property>
</bean>
</beans>
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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.扫描service包-->
<context:component-scan base-package="cqu.ma.service"></context:component-scan>
<!--2.将所有业务类,注入到Spring,可以通过配置,或注解实现-->
<bean id="bookServiceImpl" class="cqu.ma.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"></property>
</bean>
<!--3.声明式事务配置-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--4.aop事务支持-->
</beans>
8.6 SpringMVC 层
增加web支持
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:spring-mvc.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>
<!--编码过滤-->
<filter>
<filter-name>encodingFilter</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>encodingFilter</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.注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--2.静态资源过滤-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--3.扫描包 controller-->
<context:component-scan base-package="cqu.ma.controller"></context:component-scan>
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
8.7 错误排查
错误1
-
启动 tomcat ,注入 bookServiceImpl问题
-
解决过程:
-
单元测试:测试bookServiceImpl 获取,并执行方法
- 遇见新问题,已解决,见错误2
- 解决新问题后,测试通过
-
手动new该对象,启动 tomcat
-
报空指针异常
-
说明:springMVC整合式没有调用到service层的bean
web.xml中绑定过spring-mvc.xml
-
-
-
解决:web.xml绑定applicationContext.xml
-
错误2
- junit单元测试 bookServiceImpl:数据库连接出问题,连接的用户不是
db.properties
所设置的root用户,而显示本机用户名- 解决:将
db.properties
username=root 改为 name=root可成功
说明 username作为键 在配置c3p0 数据源时有问题 - 可能的原因 spring 在引用 ${username} 变量时并非我们
db.properties
的变量,而是一个 username=主机用户名的变量
(mybatis中并未出现此错误)
- 解决:将
9.Ajax
-
引入jQuery库
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
-
示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> <script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script> <script> function a(){ $.post({ url:"${pageContext.request.contextPath}/a1", data:{"name":$("#username").val()}, success: function (data){ $("#p1").text(data); } }); $(function (){ $("#loadData").click(function (){ $.post("${pageContext.request.contextPath}/users",function (data){ var html = ""; 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" value="加载数据" id="loadData"> <table> <thead> <tr> <td>姓名</td> <td>年龄</td> <td>性别</td> </tr> </thead> <tbody id="content"> </tbody> </table> </div> </body> </html>
@RequestMapping("/users") public List<User> getUsers(){ List<User> list = new ArrayList<>(); list.add(new User("u1",13,"m")); list.add(new User("u2",32,"w")); return list; }
10.拦截器
自定义拦截器,必须实现HandlerInterceptor
接口
拦截器拦截请求,不拦截资源
-
实现接口 (一般实现第一个方法即可)
package cqu.ma.config; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { //return true; 执行下一个拦截器,放行 //return false; 不执行下一个拦截器 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("=====处理前"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("=====处理后"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("======清理"); } }
-
注册拦截器
applicationContext.xml
<!--拦截器配置--> <mvc:interceptors> <mvc:interceptor> <!-- /** 拦截包括这个请求下面的所有请求 --> <mvc:mapping path="/**"/> <bean class="cqu.ma.config.MyInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
11.文件上传
- 表单的 enctype 属性说明
- application/x-www=form-urlencoded:默认方式,只处理表单域中的value属性值,采用这种编码方式的表单会将表单域中的值处理成URL编码方式
- multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码
- text/plain:除了把空格转换成 “+” 外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件
-
导入包
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <!--高版本的servlet-api--> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency>
-
配置
applicationContext.xml
<!--文件上传配置--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--请求的编码格式,必须和jsp的pageEncoding属性一致--> <property name="defaultEncoding" value="utf-8"></property> <!--文件大小限制,单位 字节 10485760B = 10MB--> <property name="maxUploadSize" value="10485760"></property> <property name="maxInMemorySize" value="40960"></property> </bean>
-
表单
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post"> <input type="file" name="file"> <input type="submit" value="upload"> </form>
-
controller
package cqu.ma.controller; import jdk.internal.util.xml.impl.Input; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.*; @RestController public class FileController { @RequestMapping("/upload") public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException { String uploadFileName = file.getOriginalFilename(); if("".equals(uploadFileName)){ return "redirect:/index.jsp"; } System.out.println("upload file name:"+uploadFileName); // String path = request.getServletContext().getRealPath("/upload"); File realPath = new File(path); if(!realPath.exists()){ realPath.mkdir(); } System.out.println("文件保存地址:"+realPath); InputStream inputStream = file.getInputStream(); OutputStream outputStream = new FileOutputStream(new File(realPath,uploadFileName)); int len = 0; byte[] buffer = new byte[1024]; while((len=inputStream.read(buffer))!=-1){ outputStream.write(buffer,0,len); } outputStream.close(); inputStream.close(); return "redirect:/index.jsp"; } @RequestMapping("/upload2") public String upload2(@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); file.transferTo(new File(realPath+"/"+file.getOriginalFilename())); return "redirect:/index.jsp"; } @RequestMapping("/download") public String download(HttpServletRequest request, HttpServletResponse response) throws IOException { String path = request.getServletContext().getRealPath("/upload"); String fileName = "1.PNG"; //1.设置响应头 response.reset(); 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 inputStream = new FileInputStream(file); //3.写出流 OutputStream outputStream = response.getOutputStream(); byte[] buffer = new byte[1024]; int len = 0; //4. while((len=inputStream.read(buffer))!=-1){ outputStream.write(buffer,0,len); outputStream.flush(); } outputStream.close(); inputStream.close(); return "ok"; } }
file.transferTo(new File(realPath+"/"+file.getOriginalFilename())); return "redirect:/index.jsp"; } @RequestMapping("/download") public String download(HttpServletRequest request, HttpServletResponse response) throws IOException { String path = request.getServletContext().getRealPath("/upload"); String fileName = "1.PNG"; //1.设置响应头 response.reset(); 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 inputStream = new FileInputStream(file); //3.写出流 OutputStream outputStream = response.getOutputStream(); byte[] buffer = new byte[1024]; int len = 0; //4. while((len=inputStream.read(buffer))!=-1){ outputStream.write(buffer,0,len); outputStream.flush(); } outputStream.close(); inputStream.close(); return "ok"; }
}