创建Java项目
file->new->Project

选中Java->选择本地安装的jdk->点击next

一直点击next直到下面图片中设置项目的名称和地址

项目结构

在项目基础上添加jar包依赖->找到对应的jar地址添加进来->当在External Libraries中存在对应的jar包名称表示添加依赖成功。

创建javaWeb项目(本地Jar包方式)
按照上操作创建好一个java普通项目
修改普通java项目为JavaWeb项目
添加项目模块支持->选择web application(4.0),记住勾选create web.xml

完成之后,可以看到项目下新建了web目录,并包含了web.xml和index.jsp文件。
在WEB-INF下新建文件夹classes(存放编译后的class文件)和lib(存放开发需要的jar包)
打开项目结构(Project Structure)

- 模块配置(注意这里的输出路径可以设置为上面创建的classes文件夹也可以使用默认的地址,只是后续上线的话,要去对应的classes文件夹中获取class文件去部署)

添加tomcat

配置Deployment,这个操作可以让Tomcat找到war包所在的位置,从而将web项目部署在Tomcat服务器上并修改下面中的application contex为/(这样项目默认访问路径为localhost:8080/index.jsp)

添加项目所需的依赖
file->project structure->Modules->dependencies->JARs Or Directories->选中创建的lib文件夹->Jar Directory->ok


- file->project structure->Modules->dependencies->library->选择Tomcat

记住要勾选上述添加的依赖

最后,可以看到导入进来了

- 最后启动项目
Maven项目整合SSM
分别讲解了Mybatis、SpringMVC,Spring,最后又将三者整合成SSM框架
参考文档
Maven创建JavaWeb项目
创建项目
使用Maven骨架创建,选择webapp,如图所示

配置项目使用Maven的配置信息

创建完成后的目录结构如下图

由此可见没有java文件夹和resources文件夹,需要自己手动新建并设置文件夹的属性

添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <!-- servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <!-- 数据库jar --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> <!-- jsp标签库 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--单元测试的依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
|
配置Tomcat
查看上面javaweb的配置Tomcat的方式
启动EL表达式配置
使用骨架创建的web项目是不能用EL表达式的
原因:idea给我们提供的代码模板默认使用的2.3版本,可以修改版本,也可以在jsp中添加代码。解决方案选择其一,推荐第二种方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 1.在jsp页面中增加 <%@ page isELIgnored="false"%>
2.修改web.xml <!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 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_3_1.xsd" version="3.1"> </web-app>
|
配置lombok插件
常用注解
@Setter/@Getter
注解在属性上,为属性提供setter/getter方法
@ToString
为类生成toString方法,输出类名和所有属性
@EqualsAndHashCode
生成equal和hashCode方法,可以通过参数,排除一些属性
@NoArgsConstructor
注解在类上,为类提供一个无参的构造方法
@RequiredArgsConstructor
会生成一个包含常量(final修饰)和标识了NotNull的变量的构造方法
@AllArgsConstructor
注解在类上,为类提供一个全参的构造方法
@Data
注解在类上相当于@Getter、@Setter、@ToString等几个注解的合集
@Log4j
注解在类上,为类提供一个属性名为log的log4j日志对象
Mybatis
原生CRUD的问题

- 编码过于繁琐
- 结果集映射成对象需要我们自己编写代码
- 性能一般
- sql语句与java代码高度耦合
ORM
Object-Relationl Mapping,对象关系映射,它的作用是在关系型数据库和对象之间做一个映射,这样我们在具体的操作数据库的时候,只要像平时操作对象一样操作它就可以了,ORM框架会根据映射完成对数据库的操作,就不需要再去和复杂的SQL语句打交道
Hibernate
- 是全自动ORM框架
- 自动进行对象和结果集的转换;sql自动生成和执行hql
- 重量级;更新慢
Mybatis
- 是半自动ORM框架
- 开发人员手动写sql
- 轻量级;更新快;灵活性好
添加依赖
1 2 3 4 5
| <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.11</version> </dependency>
|
配置文件
核心配置文件
在resources目录下新建:sqlMapConfig.xml,内容可以在官网查看,或下面代码 官网
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc_driver}"/> <property name="url" value="${jdbc_url}"/> <property name="username" value="${jdbc_username}"/> <property name="password" value="${jdbc_password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> 一会此处需要修改 </mappers> </configuration>
一会需要添加两个标签: 1.properties 配置文件,存放配置参数 2.typeAliases 自动扫描beans包,自动将类起别名,别名是:类名首字母小写
|
properties标签
可以直接在value中配置,也可以单独放到一个properties文件中,若希望将配置数据放到jdbc.properties,在xml添加
1
| <properties resource="jdbc.properties"></properties>
|

1 2 3 4
| driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username=root password=root
|
typeAliases标签
大概的意思是:如果不加typeAliases,那么在映射文件中需要将实体类的地址写全,也就是com.zhuixun.domain.UserInfo,加上之后,只需要写userInfo就知道对应的实体是哪一个
1 2 3 4
| <typeAliases> <package name="com.zhuixun.domain"></package> </typeAliases>
|
映射文件配置
新建bean对应的xml
在resource下新建相同的包名,创建一个与user_info表对应的xml映射文件
注意:
- 路径必须和domain一致
- 在resource中创建时一级一级新建文件夹,不能直接使用com.zhuixun.mapper,因为resource下会叫”.”作为文件名的一部分

补充UserInfoMapper.xml内容,可以从官网摘抄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.mybatis.example.BlogMapper"> <select id="selectBlog" resultType="Blog"> select * from Blog where id = #{id} </select> </mapper>
注意映射文件的命名空间: <mapper namespace="org.mybatis.example.BlogMapper"> 在传统模式开发下,命名空间写什么都可以,没有用,如果觉得爆红不好看可以写成domain的目录,idea就不会爆红了(但注意,实际没有其他用处) <mapper namespace="com.zhuixun.domain.UserInfo"> 具体应该写什么在 基于接口代理模式开发中说明
|
改成现在需要内容为:
1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zhuixun.domain.UserInfo"> </mapper>
|
修改核心文件配置
需要在SqlMapperConfig.xml中新增如下信息,对应刚刚新建的xml:
1 2 3
| <mappers> <mapper resource="com/zhuixun/mapper/UserInfoMapper.xml"/> </mappers>
|
初试sql
映射文件
在映射文件中编写查询的sql
1 2 3
| <select id="findUserInfoAll" resultType="com.zhuixun.domain.UserInfo"> select * from user_info </select>
|
由于我们之前配置了typeAliases标签,可以这样写,resultType代表返回类型
1 2 3
| <select id="findUserInfoAll" resultType="userInfo"> select * from user_info </select>
|
新建UserInfo实体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.zhuixun.domain;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
@Data public class UserInfo { private Long userId; private String userName; private Integer userAge; private String userSex; private String userPass; private String userStatus; private LocalDateTime createTime; private LocalDateTime updateTime; }
|
Dao层代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public void findAllUserInfo()throws Exception{ InputStream inputStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<UserInfo> userInfoList = sqlSession.selectList("findUserInfoAll"); for (UserInfo userInfo : userInfoList) { System.out.println(userInfo); } }
|
数据映射问题
目前为止,是可以查出数据,但是运行代码,会发现查出来的数据全是null
原因:虽然从数据库查询到了数据,但是数据的列名是这样的
1
| user_id user_name user_sex user_pass
|
而我们定义resultType中返回的User实体类的属性是这样的
1
| userId userName userSex userPass
|
Mybatis并不能自动的将user_id映射成userId
解决思路:
主要是让Mybatis知道user_id到底是哪一个数据,它该放到哪里,需要制定映射方案
解决1:为列取一个别名,让查出来的user_id改名为userId
1 2 3 4 5 6 7 8 9 10
| <select id="getUserInfo" resultType="userInfo"> select user_id userId,user_name userName,user_age userAge, user_sex userSex, user_pass userPass from user_info </select>
备注:通过使用 SQL,可以为表名称或列名称指定别名。 SELECT column_name AS alias_name FROM table_name; as可省略
|
写一个resultMap标签,设置id和type属性,在内部编写映射方案
- id元素:用于设置主键字段与实体类属性的映射关系
- result元素:用于设置普通字段与实体类属性的映射关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <resultMap id="resultMap" type="com.zhuixun.domain.UserInfo"> <id column="user_id" property="userId" javaType="java.lang.Long" jdbcType="BIGINT"></id> <result column="user_name" property="userName" javaType="java.lang.String" jdbcType="VARCHAR"></result> <result column="user_age" property="userAge" javaType="java.lang.Integer" jdbcType="INTEGER"></result> <result column="user_sex" property="userSex" javaType="java.lang.String" jdbcType="CHAR"></result> <result column="user_pass" property="userPass" javaType="java.lang.String" jdbcType="VARCHAR"></result> <result column="user_status" property="userStatus" javaType="java.lang.String" jdbcType="CHAR"></result> <result column="create_time" property="createTime" javaType="java.time.LocalDateTime" jdbcType="DATETIMEOFFSET"></result> <result column="update_time" property="updateTime" javaType="java.time.LocalDateTime" jdbcType="DATETIMEOFFSET"></result> </resultMap>
<select id="findUserInfoAll" resultMap="resultMap"> select * from user_info </select>
|
mybatis自定义的SQL语句中,如select语句,如果数据库表的字段为驼峰命名,即如user_name这样的形式,那么select语句执行的结果会变成null。
在mybatis文件中开始驼峰命名(推荐)
1 2 3 4 5 6 7 8
| <configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration>
|
日志管理Log4j
在开发过程中我们很多时候需要对sql进行调试,查看参数或者查看最后的sql什么样子,之前我们可以使用debug或者使用在控制台打印的方式查看,但是现在我们放到了xml中??怎么跟进sql??
需要借助日志工具Log4j2
添加依赖
1 2 3 4 5
| <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency>
|
添加log4j2.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG"> <Appenders> <Console name="Console" target="SYSTEM_ERR"> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> </Console>
<RollingFile name="RollingFile" filename="log/qst.log" filepattern="${logPath}/%d{YYYYMMddHHmmss}-fargo.log"> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> <Policies> <SizeBasedTriggeringPolicy size="10 MB" /> </Policies> <DefaultRolloverStrategy max="20" /> </RollingFile>
</Appenders>
<Loggers> <Root level="DEBUG"> <AppenderRef ref="Console" /> <AppenderRef ref="RollingFile" /> </Root> </Loggers> </Configuration>
|
基于接口代理模式开发
- Mybatis要求使用mapper作为接口文件夹名称(保证了编译后在同一文件夹),且接口名需要和映射文件同名
- mapper文件夹下放接口,接口方法名和映射文件中的id名相同
- 映射文件的命名空间namespace,在基于接口代理开发时,需要指定mapper文件夹下的接口文件

修改代码

新增mapper文件夹以及UserInfoMapper接口类
映射文件修改namespace
1 2
| <mapper namespace="com.zhuixun.mapper.UserInfoMapper"> </mapper>
|
UserInfoMapper接口定义方法与映射文件的id名一致
1 2 3 4 5
|
List<UserInfo> findUserInfoAll();
|
1 2 3
| <select id="findUserInfoAll" resultType="com.zhuixun.domain.UserInfo"> select * from user_info </select>
|
在service层修改代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class UserInfoService { public List<UserInfo> getUserInfoAll() throws Exception{ InputStream inputStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserInfoMapper userInfoMapper = sqlSession.getMapper(UserInfoMapper.class); List<UserInfo> userInfoAll = userInfoMapper.findUserInfoAll(); userInfoAll.forEach(userInfo->System.out.println(userInfo)); return userInfoAll; } }
|
SpringMvc
分析理解MVC
mybatis 替换的是DAO连接数据库
SpringMvc替换的是前端和servlet这部分

工作流程

HandlerMapping处理器映射器
- DispatcherServlet:不处理任何请求,但是接收全部请求
- HandlerMapping:处理请求,处理器Handler和URL的映射关系
- 这样DispatcherServlet就知道往哪里转发请求,即给哪个Handle

HandlerAdapter处理器适配器
调用Handler(或说servlet)中间有个适配器是为了解耦,Handler是我们编写的业务代码(Controller)
ViewReslover视图解析器
返回视图时做一个解析操作,再返回真正的视图字符串之前找到视图字符串在哪里
SpringMVC引入
1 2 3 4 5 6
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency>
|
配置前端控制器
dispatcherServlet就是一个servlet,dispatcherServlet需要接收全部请求
注意:/拦截所有的非jsp,/*拦截所有请求
在web.xml中配置servlet
1 2 3 4 5 6 7 8
| <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>
|
创建springmvc.config配置文件

配置文件中是对Springmvc各个组件配置的,现在我们没有配置,但需要在web.xml去加载这个文件
正常情况下,DispatcherServlet在初始化的时候我们可以通过给其contextConfigLocation传递参数进行设置,配置文件所在路径
1 2 3 4 5 6 7 8 9 10
| <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvcConfig.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
|
SpringMvc初步配置
基础配置:配置三大组件和我们业务控制器
创建Controller
实际上controller不会这样使用,这里只是做一个测试(如果这样一个handler写一个类,不和servlet一样了吗)
1 2 3 4 5 6 7 8 9
| public class TestController implements Controller {
@Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("/login.jsp"); return modelAndView; } }
|
配置三大组件以及添加业务控制器
1 2 3 4 5 6 7 8 9 10
| <beans> <bean name="/testController" class="com.zhuixun.controller.TestController"></bean> <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"></bean> </beans>
|
完善视图解析器
正常开发jsp我们一般会放到安全目录下,因此我们在WEB-INF下新建一个jsp目录存放我们的jsp页面

然后通过controller层返回视图
1 2 3 4 5 6 7 8 9
| public class TestController implements Controller {
@Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("/WEB-INF/jsp/login.jsp"); return modelAndView; } }
|
现在我们设置jsp的路径还是挺长(”/WEB-INF/jsp/login.jsp”),这个时候我们可以使用视图解析器的配置对返回值进行优化,修改配置文件中的视图解析器,增加两个属性
1 2 3 4 5
| <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
|
这样在访问的路径上自动添加前缀和后缀
1 2 3 4 5
| public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("/login"); return modelAndView; }
|
基于SpringMVC注解改造项目
上面的基础的改造我们发现实际上并没有比Servlet简化多少
org.springframework.stereotype.Controller注解类型用于将类的实例指定为控制器,使用@Controller注解标注的类无需继承特定的类或者实现特定的接口
- 在Springmvc配置文件中引入spring-context
- 使用<context:component-scan/ >元素配置包的扫描范围
- 在对应的类中使用@Controller对类进行注解

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?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 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.zhuixun.controller" /> <mvc:annotation-driven></mvc:annotation-driven>
<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"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
|
1 2 3 4 5 6 7
| @Controller public class UserInfoController { @RequestMapping("/toLogin") public String toLogin(){ return "login"; } }
|
静态资源问题
我们前端的常见资源有js、css、img等等,这些都是会被dispatcherServlet拦截到,所以我们需要对静态资源放行

1 2 3 4 5
| <mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
|
参数注入
乱码问题
get请求方式乱码可以修改Tomcat的server.xml,如果没有则不需要修改
post请求中文乱码,需要在web.xml中添加过滤器转码
注意:下面这个过滤器一定要写到所有过滤器之前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
时间Date
单独时间
@DateTimeFormat(pattern = “yyyy-MM-dd”)
1 2 3 4 5
| @RequestMapping("time") public String time(@DateTimeFormat(pattern = "yyyy-MM-dd") Date userTime) { System.out.println(userTime); return "restful"; }
|
实体类中有时间属性
在实体类中添加注解
1 2 3 4 5 6 7 8 9 10
| entity: @DateTimeFormat(pattern = "yyyy-MM-dd") private Date userTime;
controller中正常: @RequestMapping("timeClass") public String timeClass(UserInfo userInfo) { System.out.println(userInfo.toString()); return "restful"; }
|
响应返回
转发和重定向
转发到其他Controller
1
| return "forward:restful";
|
重定向
1
| return "redirect:/resuful";
|
响应Json
**@ResponseBody**:可以直接将返回的字符串数据作为响应内容,即设置controller返回的是一个Json数据,而不是视图
如果整个Controller类的方法都是返回Json
@RestController的作用等同于@Controller + @ResponseBody
数据校验
添加依赖
1 2 3 4 5
| <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.0.Final</version> </dependency>
|
实体类添加约束
1 2 3
| @NotNull(message = "主键id不能为空") private Long userId;
|
在方法属性设置此类需要被检查@Valid,且设置了接受错误信息的BindingResult
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RequestMapping("register") public String register(@Valid UserInfo userInfo, BindingResult bindingResult) { if (bindingResult.hasErrors()) { List<FieldError> errors = bindingResult.getFieldErrors(); for (FieldError error : errors) { System.out.println(error.getDefaultMessage()); } } System.out.println("-----------"); System.out.println(userInfo.toString()); return "login"; }
|
文件上传
SpringMVC为文件上传提供了直接支持,即MultipartResolver接口,具有即插即用特征。SpringMVC提供了CommonsMultipartResolver类,该类通过Commons FileUpload技术实现了MultipartResolver接口。因此使用SpringMVC上传功能时需要提供Commons FileUpload依赖支持。
引入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
|
在Springmvc配置文件中添加配置
1 2 3 4 5
| <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="1024000"></property> </bean>
|
jsp设置表单的提交enctype
1 2 3
| <form action="" method="post" enctype="multipart/form-data"> </form>
|
controller层接收
1 2 3 4 5 6 7 8 9 10 11
| @RequestMapping("register") public String register(MultipartFile userImg) throws IOException { System.out.println(userImg.getOriginalFilename()); String fileUrl = "D:\\" + userImg.getOriginalFilename(); File file = new File(fileUrl); userImg.transferTo(file); return "login"; }
|
文件下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @RequestMapping("/downloadFile") public ResponseEntity<byte[]> download(HttpServletRequest request) throws Exception { ServletContext servletContext = request.getServletContext(); String realPath = servletContext.getRealPath("/static/img/logo.jpg"); FileInputStream fileInputStream = new FileInputStream(realPath); byte[] bytes = new byte[fileInputStream.available()]; fileInputStream.read(bytes); fileInputStream.close(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.set("Content-Disposition","attachment;filename=logo.jpg"); return new ResponseEntity<byte[]>(bytes,httpHeaders, HttpStatus.OK); }
|
拦截器
SpringMVC中提供了Interceptor拦截器,用于拦截用户的请求并进行相应的处理,如权限认证、判断用户是否登录等。
SpringMVC拦截器是一种可插拔式的设计,当需要使用某个拦截器时,只需要在配置文件中应用该拦截器即可;当不需要该拦截器时,取消配置文件中的配置。
SpringMVC中的拦截器是通过实现HandlerInterceptor接口或继承HandlerInterceptorAdapter抽象类来完成的。
重写三个方法
preHandle
这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false
当preHandle()方法返回true时,继续向下执行处理器中的方法,否则不再向下执行
postHandle
当preHandle()方法返回true时,且在Controller方法被调用之后被调用;
postHandle()方法在DispatcherServlet进行视图返回渲染之前被调用,因此在方法中可以对Controller处理之后的ModelAndView对象进行操作
afterCompletion
这个方法在DispatcherServlet完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class TestInterceptor1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("一:1111111111"); return HandlerInterceptor.super.preHandle(request, response, handler); }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("一:2222222222"); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("一:3333333333"); HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
|
springmvc配置:
1 2 3 4 5 6 7 8
| springMVC配置: <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/*"/> <bean class="com.zhuixun.interceptor.TestInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
|
如果配置多个拦截器,拦截器的执行顺序是根据配置顺序来的
Spring
主要是通过Spring的IOC去控制对象的创建管理,和AOP做统一处理
SSM整合
spring主要帮我们解决的是依赖关系Controller-service-dao(现在Dao层不用,而mapper接口也不用我们new,它是代理类帮我们创建的,所以目前IOC帮我们的是Controller-Service层)
分析
现在我们在Service中用的是手写的Mybatis工具类,工具类的流程是:SqlSessionFactoryBuilder–>SqlSessionFactory–>SqlSession–>getMapper
原先我们使用Mybatis就是在service层中使用sqlsessionfactory和sqlsession获取mapper代理类
既然我们要解决依赖关系;需要解决Service调用代理类的依赖所以我们可以思考出来我们需要把sqlsessionfactory和sqlsession获取mapper代理类的创建都交给Spring
mapper代理类可以由SqlSession创建,所以最终我们只需要让Spring管理我们sqlsessionfactory和sqlsession对象即可
我们的最终目的是IOC可以帮我们管理Controller、Service、mapper
引入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.3.RELEASE</version> </dependency>
|
新建application.xml
创建一个配置文件(名字不太重要),进行Spring配置文件配置
数据库信息
我们需要让IOC创建sqlsessionfactory和sqlsession;必然要连接数据库,所以数据库信息需要配置到IOC中,数据库信息在jdbc.properties中,使用<context:property-placeholder >引入属性文件,将数据库连接信息放到一个对象中,方便注入
1 2 3 4 5 6 7 8
| <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean>
|
创建sqlsessionfactory
这里不需要直接创建mybatis核心包中的类SqlsessionFactory,我们引入mybatis整合spring包,使用其中的SqlSessionFactoryBean更加合适,同时配置需要注入必须得数据源,以及常用的别名扫描配置
1 2 3 4
| <bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="typeAliasesPackage" value="com.zhuixun.domain"></property> </bean>
|
创建sqlsession
我们这里也不需要单独配置管理sqlsession,而选择用整合包给我提供的一个映射文件扫描类MapperScanerConfigurer
一个映射文件扫描器,主要的作用就是扫描映射文件,生成mapper代理类,因此我们至少需要配置两个属性
- 要扫描那些映射文件
- 扫描出来的映射文件使用哪个sqlsessionFactory去处理生成代理类
1 2 3 4 5
| <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.zhuixun.mapper"></property> <property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"></property> </bean>
|
添加扫描Service层的配置
1
| <context:component-scan base-package="com.zhuixun.services"></context:component-scan>
|
Controller层已经在springmvc-config.xml中扫描过了,不需要再扫描,如果再写一个,SpringIOC会生成两个Controller对象。(SpringMVC在创建时就有一个SpringIOC容器)
Spring容器配置
在web.xml中增加项目启动创建spring容器配置,这里要使用到监听器监听应用域启动创建IOC容器
ContextLoaderListener是Spring框架帮我们提供很好的监听器直接配置使用即可
1 2 3 4 5 6 7 8
| <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
|
全部配置文件
Spring配置applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <?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:aop="http://www.springframework.org/schema/aop" 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/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean> <bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="typeAliasesPackage" value="com.zhuixun.domain"></property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.zhuixun.mapper"></property> <property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"></property> </bean> <context:component-scan base-package="com.zhuixun.services"></context:component-scan> <context:component-scan base-package="com.zhuixun.interceptor"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
|
jdbc.properties
1 2 3 4
| driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/guangxissmdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username=root password=root
|
SpringMvc配置(Springmvc-config.xml)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <?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 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.zhuixun.controller"></context:component-scan> <mvc:annotation-driven></mvc:annotation-driven>
<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"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean>
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="1024000"></property> </bean> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/toLogin"/> <bean class="com.zhuixun.interceptor.TestInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
</beans>
|
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <!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 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_3_1.xsd" version="3.1"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param>
<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
<filter> <filter-name>hidden</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hidden</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
</web-app>
|
依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency>
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency>
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> <scope>provided</scope> </dependency>
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.11</version> </dependency>
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency>
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.1</version> </dependency>
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.0.Final</version> </dependency>
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.3.RELEASE</version> </dependency>
|