视频https://www.bilibili.com/video/BV1Sb411s7qa
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XcSd8s0J-1584950168386)(G:\大学\csdn\springMvc\入门需求.jpg)]
配置环境
首先要在web.xml配置servlet,作用是页面发的任何的请求都会经过servlet
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
编写配置文件
然后需要在resources里编写一个springmvc.xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
TomCat中导入项目
入门程序
用于接收页面的请求,并返回方法。
开启springmvc注解支持
- springmvc.xml
<mvc:annotation-driven/>
整体逻辑
初始化servlet,使它能读取springmvc.xml配置文件 --> 在配置文件中扫描controller所在的包 --> 将controller封装成对象用于方法的传递 --> 利用视图解析器找到返回页面所在位置
在配置文件中配置扫描路径
- springmvc.xml
<!-- 配置spring创建容器时要扫描的包 -->
<context:component-scan base-package="com.zxm"></context:component-scan>
加@Controller注解
-
将controller中的方法封装成一个对象,方便传送给前端。
-
path对应的是返回的路径。
-
return后的字符串想叫什么都行,但在springmvc默认中,它代表返回了一个该字符串所对应的jsp页面,如以下代码就需要一个hello.jsp,位置处于WEB-INF/pages/hello.jsp
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String hello(){
System.out.println("hello");
return "hello";
}
}
servlet初始化
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 配置servlet启动时加载对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
- classpath:springmvc.xml 代表给 org.springframework.web.servlet.DispatcherServlet 这个类初始化读取文件。
视图解析器
而我们在controller类中返回的页面路径计算机怎么去找到呢?这里就用到了视图解析器,位于springmvc.xml中。
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
- prefix表示文件所在的目录。
- suffix表示文件的后缀名。
添加a标签
在index.jsp中添加a标签,启动项目,点击后成功跳转到hello.jsp的页面。
<a href="hello">入门程序</a>
总结
REQUESTMAPPING
相当于一个映射,path是路径,每次服务器发出和path路径相同的请求,后台就知道该调这个方法了。
属性
-
value 和 path功能类似,都是指定返回路径。注解中只传路径的时候可以省略这两个单词,直接以字符串形式输入,@ReaquestMapping("/hello")
-
method 指请求方式,页面的超链接跳转都是get请求,如果改成@RequestMapping(mathod = “RequestMethod.POST”),页面跳转就会出错。
引用类型的封装
建立实体类,继承serializable序列化接口,它的作用是将对象转化成流。
解决post请求中文乱码问题
web.xml
<!-- 过滤器,解决post请求中文乱码-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
自定义格式类型转换
-
编写转换类,继承convert接口
-
springmvc.xml中进行配置
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.zxm.convert.StringToDateConvert"/> </set> </property> </bean>
-
在支持中开启
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
restful编程格式
响应
转发
request.getRequestDispatcher("/WEB-INF/pages/hello.jsp").forward(request, response);
- 路径之所以要写这么详细,是因为转发的时候不会调用视图解析器,所以路径需要自己写出来。
return "forward:/WEB-INF/pages/hello.jsp";
- 这是另一种转发方式,"forward:"是格式不能变动,路径的原理和上面一样。
重定向
response.sendRedirect(request.getContextPath() + "/response.jsp");
- 不写具体路径是因为WEB-INF是受保护的文件夹,之前的forward是服务器内部访问,所以可以使用,但现在是外部访问,访问不到。
- 重定向路径只写"/response.jsp"访问的是http://localhost:8888/response.jsp,会404.
- 重定向路径只写"response.jsp"访问的是http://localhost:8888/springmvc_day01_01_start_war/user/response.jsp,会404.
- WEB-INF受保护,所以直接重定向跳不了WEB-INF里面的文件。
return "redirect:/response.jsp";
- 重定向的另一种方法,这里不需要加前面的项目名,因为底层源码已经把这些处理好了。
静态资源拦截
web.xml中配置的DispatcherServlet会拦截静态资源,需要在springmvc.xml中解除对静态资源的拦截。
<mvc:resources mapping="/js/**" location="/js/"/>
- location如果和mapping一样加**,前端会找不到jquery那个文件,导致仍然被拦截。
Ajax
$.ajax({
url:"user/testAjax",
contentType:"application/json; charset=UTF-8",
data:'{"username":"hehe", "date":"2012/12/12"}',
dataType:"json",
type:"post",
success:function(data){
}
});
public Void testAjax(@RequestBody String body)
- ajax返回的是json类型的数据,要拿到整个数据体需要用@RequestBody注解。
Jackson
public @ResponseBody User testJackson(@RequestBody User user)
- @ResponseBody User 将整个实体类以json形式返回给前端,记得要导入jackson的jar包。
文件上传
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PoS9kSGk-1584950168397)(G:\BaiduNetdiskDownload\springmvc\SpringMVC-02\截图\03-原理.bmp)]
配置文件解析器
-
springmvc.xml
-
500错误,找不到指定路径:我的是因为没有创建uploads文件夹,在报错提示的对应路径下创建指定文件夹就可以了。
-
id="multipartResolver" //名字必须叫这个,不能改
-
maxUploadSize //上传文件大小最大值,value内单位是字节
-
MultipartFile upload //必须和上传表单中,file对应的name一致,如<input type="file" name="upload">
//SpringMVC上传文件
@RequestMapping("/testFile")
public String testFile(HttpServletRequest request, MultipartFile upload) throws Exception {
String path = request.getSession().getServletContext().getRealPath("/uploads/"); //上传位置
//判断文件是否存在
File file = new File(path);
if (file == null)
file.mkdirs();
//获取上传文件名
String filename = upload.getOriginalFilename();
//把名称设成唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
//完成文件上传
upload.transferTo(new File(path, filename));
System.out.println("SpringMVC文件上传成功...");
return "hello";
}
跨服务器上传
-
新建tomcat,改变端口号和JMX port防止重复
-
导入jar包
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency>
-
405报错
tomcat/conf/web.xml路径下,在web.xml中去掉只读部分。
<init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param>
//跨服务器上传文件
@RequestMapping("/testFile2")
public String testFile2(MultipartFile upload) throws Exception {
//定义上传文件服务器路径
String path = "http://localhost:9090/fileUploadServer_war_exploded/uploads/";
//获取上传文件名
String filename = upload.getOriginalFilename();
//把名称设成唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
//创建客户端对象
Client client = Client.create();
//和另一个服务器进行连接
WebResource webResource = client.resource(path + filename);
//上传文件
webResource.put(upload.getBytes());
System.out.println("跨服务器文件上传成功...");
return "hello";
}
异常处理
- Ctrl + Alt + T,快捷键给指定字段添加try,catch
处理异常
@RequestMapping("/testExcepion")
public String testExcepion() throws SysException {
System.out.println("Exception...");
try {
int a = 1 / 0;
} catch (Exception e) {
//打印异常信息
e.printStackTrace();
//抛出自定义异常
throw new SysException("错误...");
}
return "hello";
}
处理器
-
instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例。
-
https://www.cnblogs.com/alsf/p/9134552.html
1、返回指定页面
ModelAndView构造方法可以指定返回的页面名称,
也可以通过setViewName()方法跳转到指定的页面 ,
2、返回所需数值
使用addObject()设置需要返回的值,addObject()有几个不同参数的方法,可以默认和指定返回对象的名字。
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常业务逻辑
*/
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
SysException se = null;
if(e instanceof SysException){
se = (SysException) e;
}
else {
se = new SysException("ERROR...");
}
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg", e.getMessage());
mv.setViewName("error");
return mv;
}
}
配置异常处理器
- springmvc.xml
<bean id="sysExceptionResolver" class="com.zxm.exception.SysExceptionResolver"/>
拦截器
- HandlerInterceptor接口,1.8新特性中已经将方法全部实现过了,所以继承接口不用实现方法,想写方法可以重写方法,Ctrl + O可以快捷挑选方法进行重写。
拦截器类
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 预处理,Controller方法执行前
* return true,放行,执行下一个拦截器,如果没有,执行Controller中的方法
* return false,不放行
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...");
return true;
}
}
//不放行的话可以使用request进行页面的跳转
request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
return false;
//后处理方法,Controller执行之后,hello.jsp执行之前
postHandle
//hello.jsp执行之后,该方法会执行,此处不能再跳其他页面了,因为已经响应完了
afterCompletion
配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<!-- 要拦截的方法-->
<mvc:mapping path="/user/*"/>
<!-- 不拦截的方法
<mvc:exclude-mapping path=""/>-->
<!-- 配置拦截器对象 -->
<bean class="com.zxm.interceptor.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
SSM整合
创建数据库
create database ssm;
use ssm;
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);
搭建环境
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<mysql.version>5.1.6</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency> <!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency> <!-- log end -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
整合Spring框架
-
applicationContext.xml
<!-- 开启注解的扫描 --> <context:component-scan base-package="com.zxm"> <!-- 不扫描的注解 --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
-
service交给IOC容器
@Service("accountService") //把这个类交给springIOC容器去管理 public class AccountServiceImpl implements AccountService { public List<Account> findAll() { System.out.println("业务层:查询全部..."); return null; } @Override public void saveAccount(Account account) { System.out.println("业务层:添加信息..."); } }
-
测试类
@Test public void Test1(){ //加载配置文件 ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //获取对象 AccountService as = (AccountService) ac.getBean("accountService"); //调用方法 as.findAll(); }
整合SpringMVC
搭建环境
具体参考前面的入门程序步骤。
-
编写springmvc.xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置spring创建容器时要扫描的包 --> <context:component-scan base-package="com.zxm"> <!-- 只扫描Controller注解 --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <mvc:resources mapping="/js/**" location="/js/"/> <mvc:annotation-driven/> </beans>
-
编写web.xml,初始化servlet和解决中文乱码问题。
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 配置servlet启动时加载对象 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 过滤器,解决post请求中文乱码--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
-
编写Controller文件
@Controller @RequestMapping("/account") public class AccountController { @RequestMapping(path = "/findAll") public String findAll(){ System.out.println("表现层,查询全部..."); return "list"; } }
整合Spring和SpringMVC
-
我们需要在Controller方法中添加Service,并注入,以此来调用业务层的方法。但此时Spring文件虽然配置了,可是并没有去调用它,所以我们仅仅只是扫描了MVC所对应的Controller包,而没有扫描过Spring配置下的包。因此我们需要在web.xml中进行初始化配置,让服务器初始化的时候加载spring配置文件。
-
web-app标红是因为内部顺序不对,改为filter->listener->sevlet即可.
<!-- 配置Spring监听器,默认只加载WEB-INF下的applicationContext.xml --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 设置配置文件路径 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
-
注入service并执行。
@Controller @RequestMapping("/account") public class AccountController { @Autowired private AccountService accountService; @RequestMapping(path = "/findAll") public String findAll(){ System.out.println("表现层,查询全部..."); accountService.findAll(); return "list"; } }
整合Mybatis
搭建Mybatis环境及测试
-
编写配置文件,resouces/SqlMapConfig.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> <!-- 配置环境 --> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///ssm"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!-- 引入映射配置文件 --> <mappers> <!-- <mapper class="com.zxm.dao.AccountDao"></mapper>--> <package name="com.zxm.dao"/> </mappers> </configuration>
-
实现dao接口
public interface AccountDao { //查询全部 @Select("select * from account") public List<Account> findAll(); //保存账户信息 @Insert("insert into account (name, money) values (#{name}, #{money})") public void saveAccount(Account account); }
-
测试
public class TestMybatis { /** * 测试查询 * @throws Exception */ @Test public void Test1() throws Exception { //配置文件 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建SqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession对象 SqlSession session = factory.openSession(); //获取到代理对象 AccountDao dao = session.getMapper(AccountDao.class); //查询全部 List<Account> list = dao.findAll(); for (Account account: list) { System.out.println(account); } //关闭资源 session.close(); in.close(); } /** * 测试保存 * @throws Exception */ @Test public void Test2() throws Exception { Account account = new Account(); account.setName("懒羊羊"); account.setMoney(400.0); //配置文件 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建SqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession对象 SqlSession session = factory.openSession(); //获取到代理对象 AccountDao dao = session.getMapper(AccountDao.class); //保存 dao.saveAccount(account); //提交事务 session.commit(); //关闭资源 session.close(); in.close(); } }
整合Mybatis
-
applicationContext.xml中需要配置,配置完后之前的SqlMapConfig就可以删除了。
<!-- Spring整合Mybatis框架 --> <!-- 配置连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql:///ssm?characterEncoding=utf8"/> <property name="user" value="root"/> <property name="password" value="123456"/> </bean> <!-- 配置SqlSessionFactory工厂 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置AccountDao所在包 --> <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.zxm.dao"/> </bean>
-
给AccountDao加上注解,将它交给SpringIOC容器
@Repository public interface AccountDao
-
在service层中注入dao和编写方法
@Service("accountService") //把这个类交给springIOC容器去管理 public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; public List<Account> findAll() { System.out.println("业务层:查询全部..."); return accountDao.findAll(); } @Override public void saveAccount(Account account) { System.out.println("业务层:添加信息..."); accountDao.saveAccount(account); } }
-
在Controller中将service获取到的信息返回到前端
@RequestMapping(path = "/findAll") public String findAll(Model model){ System.out.println("表现层,查询全部..."); List<Account> list = accountService.findAll(); model.addAttribute("list", list); return "list"; }