springMVC第三天学习笔记
文章目录
SSM 整合
1.数据库环境搭建
数据库表结构如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y3qxnsHE-1608379310525)(.\img\表结构.jpg)]
建表sql语句见 资料\ssm.sql
2.工程环境搭建
2.1 在project中创建web模块
2.2 在pom.xml文件中导入坐标
<packaging>war</packaging>
<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>
</properties>
<dependencies>
<!--mybatis环境-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--mysql环境-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--spring整合jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!--分页插件坐标-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<!--springmvc环境-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--jackson相关坐标3个-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<!--servlet环境-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--其他组件-->
<!--junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--spring整合junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies>
<build>
<!--设置插件-->
<plugins>
<!--具体的插件配置-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
2.3 补全工程目录,创建基本包结构
2.4 在domain包下创建实体类
-
User.java
public class User { private Integer uid; private String username; private String password; private String realname; private Integer gender; private Date birthday; // get set 省略 }
-
Result.java
public class Result { // 是否成功 private boolean flag; // 成功之后响应的核心数据 private Object data; // 提示消息 private String message; // 状态码 private Integer code; // 成功 public Result(Object data, String message, Integer code) { this.flag = true; this.data = data; this.message = message; this.code = code; } // 失败 public Result(String message, Integer code) { this.flag = false; this.message = message; this.code = code; } // get set 省略 }
-
Code.java
public class Code { // 操作结果编码 public static final Integer SAVE_OK = 20011; public static final Integer UPDATE_OK = 20021; public static final Integer DELETE_OK = 20031; public static final Integer GET_OK = 20041; public static final Integer SAVE_ERROR = 20010; public static final Integer UPDATE_ERROR = 20020; public static final Integer DELETE_ERROR = 20030; public static final Integer GET_ERROR = 20040; // 校验结果编码 public static final Integer DATA_LENGTH_ERROR = 30001; public static final Integer DATA_VALUE_ERROR = 30002; }
3.springmvc基础环境完善
3.1 配置web.xml文件
<!--请求乱码过滤器-->
<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>
<!--前端控制器-->
<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:spring-mvc.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>
3.2 在resources目录下创建spring-mvc.xml文件,编写基本配置
<!--包扫描:暂时扫描itheima包-->
<context:component-scan base-package="com.itheima"/>
<!--注解驱动-->
<mnc:annotation-driven/>
<!--静态资源排除-->
<mvc:default-servlet-handler/>
3.3 在controller包下创建UserController,在类中创建测试方法
@Controller
public class UserController {
@RequestMapping("/helloWorld")
@ResponseBody
public String helloWorld(){
return "helloWorld";
}
}
3.4 在浏览器中输入http://localhost/helloWorld
进行测试
4.整合mybatis
4.1 在resources下创建jdbc.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver
# 自行修改ip地址
jdbc.url=jdbc:mysql://192.168.93.129:3306/ssm
jdbc.username=root
jdbc.password=root
4.2 在dao包下创建UserDao接口
public interface UserDao {
public List<User> findAll();
}
4.3 在resources下的com/itheima/dao
目录下创建UserDao接口对应的映射配置文件UserDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.UserDao">
<select id="findAll" resultType="User">
select * from user
</select>
</mapper>
4.4 在service包下创建UserService接口
public interface UserService {
public List<User> findAll();
}
4.5 在service.impl包下创建UserServiceImpl实现类
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
4.6 在springmvc配置文件中添加整合mybatis相关配置
<!--加载jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置创建SqlSession对象的工厂Bean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.itheima.domain"/>
</bean>
<!--配置dao接口所在包-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.itheima.dao"/>
</bean>
4.7 修改UserController,注入UserService,调用UserService的findAll方法
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findAll")
@ResponseBody
public Result findAll(){
List<User> userList = userService.findAll();
Result result = new Result(userList,"查询成功", Code.GET_OK);
return result;
}
}
4.8 通过postman进行测试
整合后工程结构
5.spring与springmvc配置分离
实际开发中,为了便于维护,spring-mvc.xml文件中只负责springmvc针对web层的相关配置,对于其它层的信息应该配置到spring的applicationContext.xml文件中。因此,需要将spring-mvc.xml
文件中部分内容进行分离。
5.1 在resources下创建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"
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">
<!--包扫描:不扫描Controller注解-->
<context:component-scan base-package="com.itheima">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--加载jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置创建SqlSession对象的工厂Bean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.itheima.domain"/>
</bean>
<!--配置dao接口所在包-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.itheima.dao"/>
</bean>
</beans>
此配置文件中配置springmvc之外的内容,如service,dao,aop,事务相关配置。
存在的问题
目前存在的问题是,spring-mvc.xml文件已经通过DispatcherServlet加载,而applicationContext.xml文件没有被加载。
解决方案
- spring-web 包中提供了一个继承自
ServletContextListener
的监听器ContextLoaderListener
- 该监听器用于在服务器启动时加载spring的核心配置文件
- 由于spring的核心配置文件名是可以自定义的,所以需要通过全局初始化参数指定配置文件的名称
5.2 修改web.xml文件,配置监听器,用于加载spring核心配置文件,并通过全局初始化参数指定配置文件名称
<!--配置用于加载spring核心配置文件的监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置全局初始化参数,指定spring核心配置文件名称-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
5.3 修改spring-mvc.xml
文件中的包扫描,只扫描controller
包
<!--包扫描-->
<context:component-scan base-package="com.itheima.controller"/>
5.4 重启项目,进行测试
6.事务管理配置
6.0 导入aspectjweaver坐标
<!--aspectjweaver-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
6.1 修改applicationContext.xml文件,加入事务管理器配置,并开启注解事务支持
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启注解事务支持-->
<tx:annotation-driven/>
6.2 在需要进行事务管理的业务接口中加入@Transactional注解
- 接口上指定通用配置
- 方法上指定特有配置
@Transactional
public interface UserService {
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public List<User> findAll();
}
7. 分页插件配置
7.1 修改applicationContext.xml,在SqlSessionFactoryBean配置中加入分页插件配置
<!--配置创建SqlSession对象的工厂Bean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.itheima.domain"/>
<!--配置分页插件-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<!--可选配置-->
<property name="properties">
<props>
<!--配置方言-->
<prop key="helperDialect">mysql</prop>
<!--查询页码大于最大页码时返回最后一页数据-->
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
7.2 修改业务层代码,加入分页参数
-
UserService.java
@Transactional public interface UserService { @Transactional(readOnly = true,propagation = Propagation.SUPPORTS) public PageInfo findAll(int pageNum, int pageSize); }
-
UserServiceImpl.java
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public PageInfo findAll(int pageNum, int pageSize) { // 设置分页参数 PageHelper.startPage(pageNum, pageSize); List<User> list = userDao.findAll(); return new PageInfo(list); } }
7.3 修改controller代码,加入分页参数
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findAll")
@ResponseBody
public Result findAll(int pageNum, int pageSize){
PageInfo pageInfo = userService.findAll(pageNum, pageSize);
Result result = new Result(pageInfo,"查询成功", Code.GET_OK);
return result;
}
}
7.4 重启项目,通过Postman进行测试
返回数据如下:
{
"flag": true,
"data": {
"pageNum": 1,
"pageSize": 3,
"size": 3,
"startRow": 1,
"endRow": 3,
"total": 8,
"pages": 3,
"list": [
{
"uid": 1,
"username": "zhangsan",
"password": "123",
"realname": "张三",
"gender": 0,
"birthday": 652806000000
},
{
"uid": 2,
"username": "lisi",
"password": "123",
"realname": "李四",
"gender": 0,
"birthday": 650041200000
},
{
"uid": 3,
"username": "wangwu",
"password": "123",
"realname": "王五",
"gender": 1,
"birthday": 647276400000
}
],
"prePage": 0,
"nextPage": 2,
"isFirstPage": true,
"isLastPage": false,
"hasPreviousPage": false,
"hasNextPage": true,
"navigatePages": 8,
"navigatepageNums": [
1,
2,
3
],
"navigateFirstPage": 1,
"navigateLastPage": 3,
"firstPage": 1,
"lastPage": 3
},
"message": "查询成功",
"code": 20041
}
8.统一异常处理配置
8.1 自定义异常类com.itheima.exception.BusinessException
public class BusinessException extends RuntimeException {
// 用于封装错误的状态码
private Integer code;
public BusinessException(Integer code) {
this.code = code;
}
public BusinessException(String message, Integer code) {
super(message);
this.code = code;
}
public BusinessException(String message, Throwable cause, Integer code) {
super(message, cause);
this.code = code;
}
// 必须生成get方法,用于在异常处理器中获取异常错误码
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
8.2 创建基于注解的统一异常处理器com.itheima.exception.ProjectExceptionAdvice
@Component
@ControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(BusinessException.class)
@ResponseBody
public Result doBusinessException(BusinessException e){
// 获取异常的状态码
Integer code = e.getCode();
// 获取异常的提示消息
String message = e.getMessage();
// 将状态码和提示消息封装到Result对象
Result result = new Result(message, code);
return result;
}
}
8.3 修改UserController
中的findAll
方法,加入页码校验逻辑,页码不合法时抛出自定义异常
@RequestMapping("/findAll")
@ResponseBody
public Result findAll(int pageNum, int pageSize){
if (pageNum <= 0){
throw new BusinessException("页码必须大于0", Code.DATA_VALUE_ERROR);
}
PageInfo pageInfo = userService.findAll(pageNum, pageSize);
Result result = new Result(pageInfo,"查询成功", Code.GET_OK);
return result;
}
8.4 重启服务器,通过Postman进行测试,测试时pageNum
参数设置为小于1的值
9.配置类替换web,applicationContext,spring-mvc三个xml配置文件
9.1 替换applicationContext类
SpringConfig.java
@Configuration
@ComponentScan(value = "com.itheima",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
@EnableTransactionManagement
@Import(JdbcConfig.class)
public class SpringConfig {
@Bean("transactionManager")
public PlatformTransactionManager getPlatformTransactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
JdbcConfig.java
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String usernmae;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setPassword(password);
dataSource.setUsername(usernmae);
dataSource.setUrl(url);
dataSource.setDriverClassName(driver);
return dataSource;
}
}
MybatisConfig.java
@Configuration
@Import(JdbcConfig.class)
public class MybatisConfig {
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer(){
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.itheima.dao");
return configurer;
}
@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource,
Interceptor interceptor){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setTypeAliasesPackage("com.itheima.domain");
factoryBean.setDataSource(dataSource);
factoryBean.setPlugins(interceptor);
return factoryBean;
}
@Bean
public Interceptor getInterceptor(){
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect","mysql");
properties.setProperty("reasonable","true");
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}
9.2 替换spring-mvc类
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
9…3 替换web类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext app = new AnnotationConfigWebApplicationContext();
app.register(SpringMvcConfig.class);
return app;
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext app = new AnnotationConfigWebApplicationContext();
app.register(SpringConfig.class);
return app;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter",filter);
registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD),false,"/*");
}
}