aop笔记
1. 通过xml配置aop
-
创建maven web工程
-
pom.xml文件导入依赖
<!-- 从这开始 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <!-- spring版本号 --> <spring.version>4.3.14.RELEASE</spring.version> <!-- log4j日志文件管理包版本 --> <slf4j.version>1.7.22</slf4j.version> <log4j.version>1.2.17</log4j.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</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-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-instrument</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-instrument-tomcat</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</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-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- mybatis 包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--mybatis spring 插件 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> <!-- 上传下载 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.1</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- pagehelper分页插件 --> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser --> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>0.9.5</version> </dependency> <!-- poi上传下载组件 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.14-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.14-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14-beta1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans --> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> </dependencies> <!-- 到这结束 -->
- 编写相应的javaBean类
package com.zjj.pojo;
public class Printer {
public void print(){
System.out.println("打印机正在打印。。。。。");
}
}
package com.zjj.pojo;
public class Logger {
public void loggerBefore(){
System.out.println("方法开始执行了。。。。。");
}
public void loggerAfter(){
System.out.println("方法执行完毕了。。。。。");
}
}
package com.zjj.pojo;
import java.util.Date;
public class Timer {
Date date=new Date();
public void showTime(){
System.out.println("当前时间是: "+date);
}
}
4. 创建spring配置文件,编写相应配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!--基于xml方式来实现aop配置-->
<bean id="p" class="com.zjj.pojo.Printer"></bean>
<bean id="log" class="com.zjj.pojo.Logger"></bean>
<bean id="time" class="com.zjj.pojo.Timer"></bean>
<!--aop配置-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="addMethods" expression="execution(* com.zjj.pojo.*.*(..) )"/>
<!--配置切面1 order 优先级 值越小 优先级越高-->
<aop:aspect id="t" ref="time" order="1">
<aop:before method="showTime" pointcut-ref="addMethods"></aop:before>
<aop:after method="showTime" pointcut-ref="addMethods"></aop:after>
</aop:aspect>
<!--配置切面2 order 优先级 值越小 优先级越高-->
<aop:aspect id="l" ref="log" order="2">
<aop:before method="loggerBefore" pointcut-ref="addMethods"></aop:before>
<aop:after method="loggerAfter" pointcut-ref="addMethods"></aop:after>
</aop:aspect>
</aop:config>
</beans>
5. 测试相应代码 ,单元测试
import com.zjj.pojo.Printer;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop1 {
@Test
public void test1(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Printer printer= (Printer) ctx.getBean("p");
printer.print();
}
}
2. 通过注解配置aop
-
创建maven web工程 同上
-
在pom.xml文件里面引入依赖 同上
-
编写相应的javaBean类
package com.zjj.pojo; import org.springframework.stereotype.Component; @Component public class Printer { public void print(){ System.out.println("打印机正在打印。。。。。"); } }
package com.zjj.pojo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
@Aspect
@Order(2)
public class Timer {
Date date=new Date();
@Around("execution(* com.zjj.pojo.*.*(..))")
public void showTime(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("开始时间是: "+date);
joinPoint.proceed();//在此方法上面的逻辑之前Before 之后的逻辑之后After
System.out.println("结束时间是: "+date);
}
}
package com.zjj.pojo;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class Logger {
@Before("execution(* com.zjj.pojo.*.*(..))")
public void loggerBefore(){
System.out.println("方法开始执行了。。。。。");
}
@After("execution(* com.zjj.pojo.*.*(..))")
public void loggerAfter(){
System.out.println("方法执行完毕了。。。。。");
}
}
-
创建spring配置文件,编写配置,并添加相应注解
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!--配置组件扫描器--> <context:component-scan base-package="com.zjj"/> <!--配置aop相应的注解支持--> <aop:aspectj-autoproxy/> </beans>
-
测试相应代码 ,单元测试
import com.zjj.pojo.Printer;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop2 {
@Test
public void test2(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Printer printer = ctx.getBean(Printer.class);
printer.print();
}
}
=========================================================================================================
SpringJDBC:
正常jdbc连接数据库流程:
- 注册驱动 修建仓库
- 获取连接 修路
- 获取Statement或者PreparedStatement对象 造车
- 执行sql操作 拉货
- 处理结果集 查询的时候会有结果集 卸货
- 关闭资源 车毁了,路砸了
spring框架: http://www.spring.io
使用spring data jdbc流程:
-
创建maven web project
-
pom.xml文件导入相关依赖
-
创建application.xml文件 spring配置文件
application.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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!--驱动名--> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <!--url--> <property name="url" value="jdbc:mysql://localhost:3306/b?characterEncoding=utf-8&useSSL=true"/> <!--用户名--> <property name="username" value="root"/> <!--密码--> <property name="password" value="123456"/> </bean> <!--配置JDBC模板--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!--配置组件扫描器--> <context:component-scan base-package="com.zjj"/> </beans>
-
创建实体类,dao层代码,service层代码,编写相应逻辑
User:
package com.zjj.pojo; public class User { Long id; String username; String password; Integer isAdmin; public User() { } public User(Long id, String username, String password, Integer isAdmin) { this.id = id; this.username = username; this.password = password; this.isAdmin = isAdmin; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getIsAdmin() { return isAdmin; } public void setIsAdmin(Integer isAdmin) { this.isAdmin = isAdmin; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", isAdmin=" + isAdmin + '}'; } }
UserDao:
package com.zjj.dao; import com.zjj.pojo.User; import java.util.List; public interface UserDao { public List<User> queryAll(); public User queryOneById(Long id); public void addOne(User user); public void updateOne(User user); public void deleteOneById(Long id); }
-
dao实现类里面 注入 JdbcTemplate
UserDaoImpl:
package com.zjj.dao.impl; import com.zjj.dao.UserDao; import com.zjj.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; @Repository public class UserDaoImpl implements UserDao { @Autowired private JdbcTemplate jdbcTemplate; /* 查询 : query() 查询所有 queryForObject() 查询单个 update() 增删改 */ @Override public List<User> queryAll() { String sql="select * from tb_user"; //将查询出来的结果集合pojo实体类对应 RowMapper<User> rowMapper=new BeanPropertyRowMapper<>(User.class); return jdbcTemplate.query(sql, rowMapper); } @Override public User queryOneById(Long id) { String sql="select * from tb_user where id=?"; //将查询出来的结果集合pojo实体类对应 RowMapper<User> rowMapper=new BeanPropertyRowMapper<>(User.class); //参数可变参数 和sql语句占位符个数及位置保持一致 return jdbcTemplate.queryForObject(sql, rowMapper, id); } @Override public void addOne(User user) { String sql="INSERT INTO `tb_user` (`id`, `username`, `password`, `isadmin`) VALUES (?, ?, ?, ?)"; jdbcTemplate.update(sql,user.getId(),user.getUsername(),user.getPassword(),user.getIsAdmin()); } @Override public void updateOne(User user) { String sql="UPDATE `tb_user` SET `username`=?, `password`=?, `isadmin`=? WHERE (`id`=?)"; jdbcTemplate.update(sql,user.getUsername(),user.getPassword(),user.getIsAdmin(),user.getId()); } @Override public void deleteOneById(Long id) { String sql="delete from tb_user where id=?"; jdbcTemplate.update(sql,id); } }
-
实现增删改查相应操作
UserService:
package com.zjj.service;
import com.zjj.pojo.User;
import java.util.List;
public interface UserService {
public void queryAll();
public void queryOneById(Long id);
public void addOne(User user);
public void updateOne(User user);
public void deleteOneById(Long id);
}
UserServiceImpl:
package com.zjj.service.impl;
import com.zjj.dao.UserDao;
import com.zjj.pojo.User;
import com.zjj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void queryAll() {
List<User> users = userDao.queryAll();
System.out.println(users);
}
@Override
public void queryOneById(Long id) {
User user = userDao.queryOneById(id);
System.out.println(user);
}
@Override
public void addOne(User user) {
userDao.addOne(user);
}
@Override
public void updateOne(User user) {
userDao.updateOne(user);
}
@Override
public void deleteOneById(Long id) {
userDao.deleteOneById(id);
}
}
7.单元测试
package test;
import com.zjj.pojo.User;
import com.zjj.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
@Test
public void testQueryAll(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService= ctx.getBean(UserService.class);
userService.queryAll();
}
@Test
public void testQueryOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService= ctx.getBean(UserService.class);
userService.queryOneById(1L);
}
@Test
public void testAddOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService= ctx.getBean(UserService.class);
User user=new User(7L,"曹浩","111111",1);
//注意主键 不能重复 唯一非空
userService.addOne(user);
}
@Test
public void testUpdateOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService= ctx.getBean(UserService.class);
User user=new User(7L,"孙权","222222",0);
//注意主键 不能重复 唯一非空
userService.updateOne(user);
}
@Test
public void testDeleteOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService= ctx.getBean(UserService.class);
//注意主键 不能重复 唯一非空
userService.deleteOneById(7L);
}
}
增加AOP切入功能:
在service层增删改查逻辑里面切入时间日志:
-
编写切面类
package com.zjj.pojo; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import java.util.Date; @Component @Aspect public class Logger { Date date=new Date(); @Around("execution(* com.zjj.service.impl.*.*(..))") public void logger(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("开始执行时间是: "+date); joinPoint.proceed(); System.out.println("执行结束时间是: "+date); } }
-
配置切面注解支持
<!--aop注解支持--> <aop:aspectj-autoproxy/>
-
测试调用
@Test public void testQueryAll(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService= ctx.getBean(UserService.class); userService.queryAll(); }
-
运行结果
开始执行时间是: Mon Mar 29 11:21:56 CST 2021 [User{id=1, username='张三', password='123456', isAdmin=0}, User{id=2, username='李四2', password='111111', isAdmin=1}, User{id=3, username='wangwu', password='111111', isAdmin=0}, User{id=5, username='武松', password='7843784', isAdmin=1}, User{id=6, username='武松', password='7843784', isAdmin=1}] 执行结束时间是: Mon Mar 29 11:21:56 CST 2021
Spring事务
事务概念:
一系列操作指令的集合,组成一个事务。成功同时成功,有一个不成功就都不成功。
特征:
数据库事务 transanction 正确执行的四个基本要素。
ACID: 原子性(Atomicity)、一致性(Correspondence)、隔离 性(Isolation)、持久性(Durability)。
(1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
(2)一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
(3)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
(4)持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
两种实现方式:
基于xml方式实现声明式事务
-
pom文件里面添加事务的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency>
-
在xml配置文件配置事务的相关配置
applicationContext.xml
<!--配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置事务的通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 配置事务的属性 isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。 propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。 read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。 timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。 rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。 no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。 --> <tx:attributes> <tx:method name="*" propagation="REQUIRED" read-only="false"/> <tx:method name="add*" propagation="REQUIRED" read-only="false"/> <tx:method name="update*" propagation="REQUIRED" read-only="false"/> <tx:method name="query*" propagation="SUPPORTS" read-only="true"></tx:method> </tx:attributes> </tx:advice> <!-- 配置aop--> <aop:config> <!-- 配置切入点表达式--> <aop:pointcut id="pt1" expression="execution(* com.zjj.service.impl.*.*(..))"></aop:pointcut> <!--建立切入点表达式和事务通知的对应关系 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor> </aop:config>
-
UserServiceImpl里面编写方法
@Override public void addTwo() { User user1=new User(7L,"张飞","123456",1); User user2=new User(1L,"刘备","123456",0); userDao.addOne(user1);//正常可以执行成功 userDao.addOne(user2);//主键重复 必定添加失败 报错 //由于切入了事务,user1和user2都一起失败 事务 要么一起成功 要么一起失败 }
-
Test单元测试
@Test public void testAddTwo(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService= ctx.getBean(UserService.class); userService.addTwo(); }
最终结果user1和user2都没有添加成功,因为user2失败,所以一起失败! 事务要么一起成功,要么一起失败
基于注解方式来实现声明式事务
-
pom.xml文件引入spring-tx依赖 同上
-
在applicatiionContext.xml文件里面配置事务管理器及事务的注解支持
<!--注解方式配置事务--> <!--配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--配置事务的注解驱动--> <tx:annotation-driven transaction-manager="transactionManager"/>
-
在要事务操作的类上面配置注解
UserServiceImpl
@Service @Transactional public class UserServiceImpl implements UserService { ... }
-
单元测试调用
@Test public void testAddTwo(){ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService= ctx.getBean(UserService.class); userService.addTwo(); }
结果同上,全部没有添加进去,因为事务 一起失败
MyBatis笔记:
什么是MyBatis?
- 基于java的数据库持久化框架。 使用java开发,做数据持久化。
- 它是一个轻量级,半自动的orm持久化框架。一个轻量级,一个orm框架(Hibernate)数据库表和对象映射。
- 通过映射xml来完成数据操作。在映射文件里面写sql语句
ORM: Object Relation Mapping 对象关系映射
mybatis环境搭建:
使用maven工程,mybatis是对jdbc的封装
0. 数据库表
1. 创建maven project
2. pom.xml 文件里面引入 mybatis和mysql依赖
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
3. 创建实体类, dao接口
User:
package com.zjj.pojo;
public class User {
private Long id;
private String username;
private String password;
private Integer isadmin;
public User() {
}
public User(Long id, String username, String password, Integer isadmin) {
this.id = id;
this.username = username;
this.password = password;
this.isadmin = isadmin;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getIsadmin() {
return isadmin;
}
public void setIsadmin(Integer isadmin) {
this.isadmin = isadmin;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", isadmin=" + isadmin +
'}';
}
}
UserDao:
package com.zjj.dao;
import com.zjj.pojo.User;
public interface UserDao {
public User findUserById(Long id);
}
4. 创建并配置mybatis配置文件
需要先引入mybatis-3-config.dtd文件
settings---->Schemas and DTDs------>右边点击 + 新建 ------>弹框 uri 输入 http://mybatis.org/dtd/mybatis-3-config.dtd file 选择本机mybatis-3-config.dtd文件 ---->apply—>ok
创建数据库连接的properties文件 db.properties,配置数据库连接相关信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/b?characterEncoding=utf-8&userSSL=false
jdbc.username=root
jdbc.password=123456
创建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>
<!-- 加载属性文件 -->
<properties resource="db.properties">
<!--properties中还可以配置一些属性名和属性值 -->
</properties>
<!-- 全局配置参数,需要时再设置 -->
<!-- http://www.mybatis.org/mybatis-3/zh/configuration.html -->
<!-- 别名定义 -->
<typeAliases>
<package name="com.zjj.pojo"/>
</typeAliases>
<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="mapper/UserMapper.xml"/>
</mappers>
</configuration>
5. 创建并配置mybatis映射文件
UserMapper.xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zjj.dao.UserDao">
<select id="findUserById" resultType="User" parameterType="long">
select * from tb_user where id=#{id}
</select>
</mapper>
6. 单元测试调用
package test;
import com.zjj.dao.UserDao;
import com.zjj.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class Test1 {
@Test
public void testQueryOne() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession();
UserDao userDao= session.getMapper(UserDao.class);
User user = userDao.findUserById(1L);
System.out.println(user);
session.close();
}
}
MyBatis配置文件:
类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<typeAliases>
<typeAlias alias="User" type="com.zjj.pojo.User"/>
<typeAlias alias="Student" type="com.zjj.pojo.Student"/>
</typeAliases>
当这样配置时,User可以用在任何使用 com.zjj.pojo.User 的地方。
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="com.zjj.pojo"/>
</typeAliases>
Mappers 映射文件(映射文件路径)
Mapper配置的几种方法:
第一种(常用)
如:
第二种
使用完全限定路径
如:
第三种
使用mapper接口类路径
如:
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
第四种(推荐)
注册指定包下的所有mapper接口
如:
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
MyBatis映射文件:
Insert:
MySQL、SQL Server等数据库的表格可以采用自动递增的字段作为主键。
有时可能需要使用这个刚刚产生的主键,用以关联其他业务
UserMaper.xml
<!-- 添加一个用户,成功后将主键值回填给id(User类的属性)-->
<insert id="addUser" parameterType="User" keyProperty="id" useGeneratedKeys="true">
INSERT INTO tb_user ( `username`, `password`, `isadmin`) VALUES ( #{username}, #{password}, #{isadmin})
</insert>
Test测试类:
@Test
public void testInsert() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession(true);
UserDao userDao= session.getMapper(UserDao.class);
User user=new User("关羽","123456",1);
userDao.addUser(user);
System.out.println(user);
session.close();
}
基于xml的映射和基于接口方式的映射:
基于xml方式映射:
直接定位到xml映射文件里面的某个标签
@Test
public void test1() throws IOException {
//加载配置文件 并读取 通过IO流
//1. 获取输入流
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession();
//namespace.id
/*
selectOne() 查询单个
selectList() 查询所有
insert() 添加
update() 修改
delete() 删除
*/
User u = session.selectOne("com.zjj.dao.UserDao.queryUserById", 1L);
System.out.println(u);
session.close();
}
基于接口方式来映射:
//基于接口方式来映射
@Test
public void test2() throws IOException {
//加载配置文件 并读取 通过IO流
//1. 获取输入流
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession();
//获取接口对象
UserDao userDao = session.getMapper(UserDao.class);
User user = userDao.queryUserById(2L);
System.out.println(user);
session.close();
}
mybatis单表增删改查:
-
工程结构,配置信息同上
-
UserDao接口里面增删改查方法
UserDao:
package com.zjj.dao; import com.zjj.pojo.User; import java.util.List; public interface UserDao { //查询单个 public User queryUserById(Long id); //查询所有 public List<User> queryAllUsers(); //添加 public void addUser(User user); //添加,并获取添加之后的自增的主键Id public void addUser2(User user); //修改 public void updateUser(User user); //删除 public void deleteUserById(Long id); }
-
UserMapper.xml映射文件里面配置增删改查映射
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace 值必须和接口路径保持一致--> <mapper namespace="com.zjj.dao.UserDao"> <!-- id值必须和接口里面的方法名保持一致 --> <select id="queryUserById" parameterType="long" resultType="User"> select * from tb_user where id= #{id} </select> <!--查询所有 --> <select id="queryAllUsers" resultType="User"> select * from tb_user </select> <!-- 添加,,并获取添加之后的自增的主键Id --> <insert id="addUser2" parameterType="User" keyProperty="id" useGeneratedKeys="true"> INSERT INTO tb_user ( `username`, `password`, `isadmin`) VALUES ( #{username},#{password} ,#{isadmin} ) </insert> <!-- 添加 --> <insert id="addUser" parameterType="User"> INSERT INTO tb_user ( `username`, `password`, `isadmin`) VALUES ( #{username},#{password} ,#{isadmin} ) </insert> <!--修改--> <update id="updateUser" parameterType="User"> UPDATE tb_user SET username=#{username}, `password`=#{password}, `isadmin`=#{isadmin} WHERE (`id`= #{id}); </update> <!-- 删除 --> <delete id="deleteUserById" parameterType="long"> delete from tb_user where id=#{id} </delete> </mapper>
-
单元测试测试调用
package test; import com.zjj.dao.UserDao; import com.zjj.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class Test1 { //基于xml方式来映射 @Test public void test1() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession session = sqlSessionFactory.openSession(); //namespace.id /* selectOne() 查询单个 selectList() 查询所有 insert() 添加 update() 修改 delete() 删除 */ User u = session.selectOne("com.zjj.dao.UserDao.queryUserById", 1L); System.out.println(u); session.close(); } //基于接口方式来映射 @Test public void test2() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession session = sqlSessionFactory.openSession(); //获取接口对象 UserDao userDao = session.getMapper(UserDao.class); User user = userDao.queryUserById(2L); System.out.println(user); session.close(); } @Test public void testQueryAll() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession session = sqlSessionFactory.openSession(); //获取接口对象 UserDao userDao = session.getMapper(UserDao.class); List<User> users = userDao.queryAllUsers(); System.out.println(users); session.close(); } @Test public void testInsert() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //sqlSessionFactory.openSession(true); 设置自动提交 SqlSession session = sqlSessionFactory.openSession(true); //获取接口对象 UserDao userDao = session.getMapper(UserDao.class); User user=new User("吕布","123456",1); userDao.addUser(user); //增删改会对数据库里面的数据发生改变,必须提交事务 //session.commit();//手动提交 session.close(); } @Test public void testInsert2() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //sqlSessionFactory.openSession(true); 设置自动提交 SqlSession session = sqlSessionFactory.openSession(true); //获取接口对象 UserDao userDao = session.getMapper(UserDao.class); User user=new User("马超","123456",1); userDao.addUser2(user); System.out.println(user); //增删改会对数据库里面的数据发生改变,必须提交事务 //session.commit();//手动提交 session.close(); } @Test public void testUpdate() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //sqlSessionFactory.openSession(true); 设置自动提交 SqlSession session = sqlSessionFactory.openSession(true); //获取接口对象 UserDao userDao = session.getMapper(UserDao.class); User user=new User(1L,"貂蝉","123456",1); userDao.updateUser(user); //增删改会对数据库里面的数据发生改变,必须提交事务 //session.commit();//手动提交 session.close(); } @Test public void testDelete() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //sqlSessionFactory.openSession(true); 设置自动提交 SqlSession session = sqlSessionFactory.openSession(true); //获取接口对象 UserDao userDao = session.getMapper(UserDao.class); userDao.deleteUserById(11L); //增删改会对数据库里面的数据发生改变,必须提交事务 //session.commit();//手动提交 session.close(); } }
使用ResultMap标签解决属性名和字段名冲突不一致的情形:
-
创建数据库表tb_stu表:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bvlr9WWQ-1634699919003)(image\tb_stu.png)]
-
Student实体类
package com.zjj.pojo; import java.util.Date; public class Student { private Integer stuId; private String stuName; private Date birthday; private String address; public Student() { } public Student(Integer stuId, String stuName, Date birthday, String address) { this.stuId = stuId; this.stuName = stuName; this.birthday = birthday; this.address = address; } public Integer getStuId() { return stuId; } public void setStuId(Integer stuId) { this.stuId = stuId; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Student{" + "stuId=" + stuId + ", stuName='" + stuName + '\'' + ", birthday=" + birthday + ", address='" + address + '\'' + '}'; } }
-
StudentDao接口
package com.zjj.dao; import com.zjj.pojo.Student; import java.util.List; public interface StudentDao { public List<Student> queryAllStudents(); }
-
StudentMapper.xml映射文件
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace 值必须和接口路径保持一致--> <mapper namespace="com.zjj.dao.StudentDao"> <resultMap id="stuResultMap" type="Student"> <!--id 主键 result 普通属性--> <id property="stuId" column="sid"/> <result property="stuName" column="sname"/> <result property="birthday" column="birthday"/> <result property="address" column="address"/> </resultMap> <select id="queryAllStudents" resultMap="stuResultMap"> select * from tb_stu </select> </mapper>
-
mybatis-config.xml配置文件中引入映射文件
<!--引入映射文件--> <mappers> <mapper resource="mapper/StudentMapper.xml"/> </mappers>
-
单元测试
package test; import com.zjj.dao.StudentDao; import com.zjj.dao.UserDao; import com.zjj.pojo.Student; import com.zjj.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class TestStu { private SqlSession session; @Before public void getSqlSession() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); session = sqlSessionFactory.openSession(); } @Test public void testQueryAll() throws IOException { //获取接口对象 StudentDao studentDao = session.getMapper(StudentDao.class); List<Student> students = studentDao.queryAllStudents(); System.out.println(students); } @After public void close(){ session.close(); } }
一对一关系:
通过resultMap标签中的association属性来配置
-
数据库表 tb_stu 学生表 和 tb_clazz 班级表
tb_stu表新增字段cid
tb_clazz表
int cid 主键 varchar cname 班级名称 varchar classroom 班级教室号
-
实体类 Student 和 Clazz 类
Student:
public class Student { private Integer stuId; private String stuName; private Date birthday; private String address; private Clazz clazz; ..... }
Clazz:
public class Clazz { private Integer id; private String className; private String classRoom; ..... }
-
接口方法
StudentDao:
//连表查询 public List<Student> queryAllStudentsInfo();
-
映射文件配置
<resultMap id="stuResultMap" type="Student"> <!--id 主键 result 普通属性--> <id property="stuId" column="sid"/> <result property="stuName" column="sname"/> <result property="birthday" column="birthday"/> <result property="address" column="address"/> <association property="clazz" resultMap="clazzResultMap"/> </resultMap> <resultMap id="clazzResultMap" type="Clazz"> <id property="id" column="cid"/> <result property="className" column="cname"/> <result property="classRoom" column="classroom"/> </resultMap> <select id="queryAllStudentsInfo" resultMap="stuResultMap"> select * from tb_stu s,tb_clazz c where s.cid=c.cid </select>
-
单元测试
@Test public void testQueryAllInfo() throws IOException { //获取接口对象 StudentDao studentDao = session.getMapper(StudentDao.class); List<Student> students = studentDao.queryAllStudentsInfo(); System.out.println(students); }
一对多关系:
通过resultMap标签中的colloction属性来配置
-
数据库表
tb_teacher:
tid int 教室编号 主键
tname varchar 教室姓名
tsubject 代课科目
tb_stu新增字段 tid 老师编号
-
实体类 Teacher
public class Teacher { private Integer teacherId; private String teacherName; private String subject; private List<Student> students; .......... }
-
StudentDao接口
package com.zjj.dao; import com.zjj.pojo.Student; import com.zjj.pojo.Teacher; import java.util.List; public interface StudentDao { //单表查询 public List<Student> queryAllStudents(); //连表查询 public List<Student> queryAllStudentsInfo(); //查询某个老师的所有信息 一对多连表 public Teacher queryTeacherById(Integer id); }
-
映射文件
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace 值必须和接口路径保持一致--> <mapper namespace="com.zjj.dao.StudentDao"> <resultMap id="clazzResultMap" type="Clazz"> <id property="id" column="cid"/> <result property="className" column="cname"/> <result property="classRoom" column="classroom"/> </resultMap> <resultMap id="stuResultMap" type="Student"> <!--id 主键 result 普通属性--> <id property="stuId" column="sid"/> <result property="stuName" column="sname"/> <result property="birthday" column="birthday"/> <result property="address" column="address"/> <association property="clazz" resultMap="clazzResultMap"/> </resultMap> <resultMap id="teacherResultMap" type="Teacher"> <id property="teacherId" column="tid"/> <result property="teacherName" column="tname"/> <result property="subject" column="tsubject"/> <collection property="students" ofType="Student" resultMap="stuResultMap"/> </resultMap> <select id="queryAllStudents" resultMap="stuResultMap"> select * from tb_stu </select> <select id="queryAllStudentsInfo" resultMap="stuResultMap"> select * from tb_stu s,tb_clazz c where s.cid=c.cid </select> <select id="queryTeacherById" parameterType="int" resultMap="teacherResultMap"> select * from tb_teacher t,tb_stu s where t.tid=s.tid and t.tid=#{id} </select> </mapper>
-
单元测试
package test; import com.zjj.dao.StudentDao; import com.zjj.dao.UserDao; import com.zjj.pojo.Student; import com.zjj.pojo.Teacher; import com.zjj.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class TestStu { private SqlSession session; @Before public void getSqlSession() throws IOException { //加载配置文件 并读取 通过IO流 //1. 获取输入流 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); session = sqlSessionFactory.openSession(); } @Test public void testQueryAll() throws IOException { //获取接口对象 StudentDao studentDao = session.getMapper(StudentDao.class); List<Student> students = studentDao.queryAllStudents(); System.out.println(students); } @Test public void testQueryAllInfo() throws IOException { //获取接口对象 StudentDao studentDao = session.getMapper(StudentDao.class); List<Student> students = studentDao.queryAllStudentsInfo(); System.out.println(students); } @Test public void testQueryTeacherById() throws IOException { //获取接口对象 StudentDao studentDao = session.getMapper(StudentDao.class); Teacher teacher = studentDao.queryTeacherById(1); System.out.println(teacher); } @After public void close(){ session.close(); } }
MyBatis配置日志显示SQL语句:
可以将mybatis执行过程中的sql语句直接在控制台上显示出来,需要相应配置:
-
pom.xml文件里面引入log4j的依赖
pom.xml
<!-- log4j --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.9.1</version> </dependency>
-
在resource目录下创建log4j的属性配置文件 log4j.properties,放在resource下面的跟根目录,直接复制即可
log4j.properties
log4j.rootLogger=debug,stdout,logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout log4j.logger.com.ibatis=DEBUG log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG log4j.logger.Java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
-
mybatis配置文件中 配置日志
mybatis-config.xml
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
-
单元测试,查看结果
idea的控制台会显示sql语句及参数
Created connection 996796369. ==> Preparing: select * from tb_user where username like "%武%" ==> Parameters: <== Columns: id, username, password, isadmin <== Row: 5, 武松, 7843784, 1 <== Row: 6, 武松, 7843784, 2 <== Total: 2 [User{id=5, name='武松', pass='7843784', isadmin=1}, User{id=6, name='武松', pass='7843784', isadmin=2}] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b69e7d1] Returned connection 996796369 to pool.
动态SQL:
-
if test 判断
if test 就是if判断 test为判断的条件
-
where if test where标签
where 标签相当于sql语句中的where关键字,但能去除第一个多余的and 或者 or
-
trim if test 自定义标签 ,可以实现 where或set的效果
trim为自定义标签 prefix前缀是什么 trim就相当于哪个标签的作用 prefixOverrides 值为and 或者 or
-
set if test 修改
set 标签相当于sql语句中的set关键字,但能去除最后一个多余的,
-
foreach 循环
foreach 循环 属性: item: 集合中的每个元素 index: 下标 collection: 集合 值为 list/array/map separator: 每个元素的分隔符 open: 整个循环以什么开头 close: 整个循环以什么结尾
例子:
UserDao接口:
package com.zjj.dao;
import com.zjj.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserDao {
//模糊查询
public List<User> queryStudentsByMohu(@Param("mohu") String mohu);
//模糊查询
public List<User> queryStudentsByMohu2(@Param("mohu") String mohu);
//查询 直接查询
public List<User> queryStudentsByUsernameAndAdmin(User user);
//查询 属性不为空根聚这个属性查询,为空则不根据这个属性查询 if test
public List<User> queryStudentsByUsernameAndAdmin2(User user);
//查询 属性不为空根聚这个属性查询,为空则不根据这个属性查询 where if test
public List<User> queryStudentsByUsernameAndAdmin3(User user);
//查询 属性不为空根聚这个属性查询,为空则不根据这个属性查询 trim if test
public List<User> queryStudentsByUsernameAndAdmin4(User user);
//更新 属性不为空则更新,为空则不更新这个字段 set if test
public void updateUser(User user);
//根据id的集合查询所有
public List<User> queryStudentsByIds(List<Long> ids);
//批量添加
public void insertBatch(List<User> users);
}
UserMapper.xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 值必须和接口路径保持一致-->
<mapper namespace="com.zjj.dao.UserDao">
<!-- ResultMap是属性名和字段名冲突-->
<resultMap id="userResultMap" type="User">
<!-- id表示主键 result普通属性 association javabean collection 集合-->
<id property="id" column="id"/>
<result property="name" column="username"/>
<result property="pass" column="password"/>
<result property="isadmin" column="isadmin"/>
</resultMap>
<select id="queryStudentsByMohu" parameterType="string" resultMap="userResultMap">
select * from tb_user where username like "%${mohu}%"
</select>
<select id="queryStudentsByMohu2" parameterType="string" resultMap="userResultMap">
select * from tb_user where username like "%${mohu}%" or password like "%${mohu}%"
</select>
<select id="queryStudentsByUsernameAndAdmin" parameterType="User" resultMap="userResultMap">
select * from tb_user where username=#{name} and isadmin=#{isadmin}
</select>
<!--if test 就是if判断 test为判断的条件-->
<select id="queryStudentsByUsernameAndAdmin2" parameterType="User" resultMap="userResultMap">
select * from tb_user where 1=1
<if test="name!=null and name!=''">
and username=#{name}
</if>
<if test="isadmin!=null and isadmin!=0">
and isadmin=#{isadmin}
</if>
</select>
<!-- where 标签相当于sql语句中的where关键字,但能去除第一个多余的and 或者 or-->
<select id="queryStudentsByUsernameAndAdmin3" parameterType="User" resultMap="userResultMap">
select * from tb_user
<where>
<if test="name!=null and name!=''">
and username=#{name}
</if>
<if test="isadmin!=null and isadmin!=0">
and isadmin=#{isadmin}
</if>
</where>
</select>
<!-- trim为自定义标签 prefix前缀是什么 trim就相当于哪个标签的作用 prefixOverrides 值为and 或者 or-->
<select id="queryStudentsByUsernameAndAdmin4" parameterType="User" resultMap="userResultMap">
select * from tb_user
<trim prefix="where" prefixOverrides="and">
<if test="name!=null and name!=''">
and username=#{name}
</if>
<if test="isadmin!=null and isadmin!=0">
and isadmin=#{isadmin}
</if>
</trim>
</select>
<!-- set 标签相当于sql语句中的set关键字,但能去除最后一个多余的,-->
<update id="updateUser" parameterType="User">
update tb_user
<set>
<if test="name!=null and name!=''">
username=#{name},
</if>
<if test="pass!=null and pass!=''">
password=#{pass},
</if>
<if test="isadmin!=null and isadmin!=0">
isadmin=#{isadmin}
</if>
</set>
where id=#{id}
</update>
<!-- foreach 循环
属性:
item: 集合中的每个元素
index: 下标
collection: 集合 值为 list/array/map
separator: 每个元素的分隔符
open: 整个循环以什么开头
close: 整个循环以什么结尾
-->
<select id="queryStudentsByIds" parameterType="List" resultMap="userResultMap">
select * from tb_user where id in
<foreach collection="list" item="id" index="i" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<insert id="insertBatch" parameterType="List">
INSERT INTO tb_user ( username, password, isadmin) VALUES
<foreach collection="list" item="item" index="index" open="" close="" separator=",">
(#{item.name}, #{item.pass}, #{item.isadmin})
</foreach>
</insert>
</mapper>
TestUser: 测试类
import com.zjj.dao.UserDao;
import com.zjj.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;
public class TestUser {
SqlSession session;
@Before
public void getSession() throws IOException {
//加载配置文件 并读取 通过IO流
//1. 获取输入流
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
session = sqlSessionFactory.openSession(true);
}
@After
public void close(){
session.close();
}
@Test
public void testQueryByMohu(){
UserDao userDao = session.getMapper(UserDao.class);
List<User> users = userDao.queryStudentsByMohu("武");
System.out.println(users);
}
@Test
public void testQueryByMohu2(){
UserDao userDao = session.getMapper(UserDao.class);
List<User> users = userDao.queryStudentsByMohu2("2");
System.out.println(users);
}
@Test
public void testQueryStudentsByUsernameAndAdmin(){
UserDao userDao = session.getMapper(UserDao.class);
User user=new User();
user.setName("武松");
user.setIsadmin(2);
List<User> users = userDao.queryStudentsByUsernameAndAdmin(user);
System.out.println(users);
}
@Test
public void testQueryStudentsByUsernameAndAdmin2(){
UserDao userDao = session.getMapper(UserDao.class);
User user=new User();
//user.setName("武松");
user.setIsadmin(2);
List<User> users = userDao.queryStudentsByUsernameAndAdmin2(user);
System.out.println(users);
}
@Test
public void testQueryStudentsByUsernameAndAdmin3(){
UserDao userDao = session.getMapper(UserDao.class);
User user=new User();
//user.setName("武松");
user.setIsadmin(2);
List<User> users = userDao.queryStudentsByUsernameAndAdmin3(user);
System.out.println(users);
}
@Test
public void testQueryStudentsByUsernameAndAdmin4(){
UserDao userDao = session.getMapper(UserDao.class);
User user=new User();
//user.setName("武松");
user.setIsadmin(2);
List<User> users = userDao.queryStudentsByUsernameAndAdmin4(user);
System.out.println(users);
}
@Test
public void testUpdateUser(){
UserDao userDao = session.getMapper(UserDao.class);
User user=new User();
user.setId(12L);
user.setName("李宁");
user.setPass("111111");
user.setIsadmin(2);
userDao.updateUser(user);
}
@Test
public void testQueryStudentsByIds(){
UserDao userDao = session.getMapper(UserDao.class);
List<Long> ids=new ArrayList();
ids.add(2L);
ids.add(6L);
ids.add(10L);
List<User> users = userDao.queryStudentsByIds(ids);
System.out.println(users);
}
@Test
public void testInsertBatch(){
UserDao userDao = session.getMapper(UserDao.class);
List<User> users=new ArrayList();
User user1=new User("大乔","123456",1);
User user2=new User("小乔","123456",0);
User user3=new User("中乔","123456",1);
users.add(user1);
users.add(user2);
users.add(user3);
userDao.insertBatch(users);
}
}
SpringMVC笔记:
springmvc是个控制层框架,封装的是servlet
mvc: model view controller
springmvc环境搭建:
-
创建maven web project
-
pom文件导入依赖
<!-- 从这开始 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <!-- spring版本号 --> <spring.version>4.3.14.RELEASE</spring.version> <!-- log4j日志文件管理包版本 --> <slf4j.version>1.7.22</slf4j.version> <log4j.version>1.2.17</log4j.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</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-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-instrument</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-instrument-tomcat</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</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> <!--springmvc--> <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> <!-- mybatis 包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--mybatis spring 插件 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> <!-- 上传下载 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.1</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- pagehelper分页插件 --> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser --> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>0.9.5</version> </dependency> <!-- poi上传下载组件 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.14-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.14-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14-beta1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans --> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.30</version> </dependency> </dependencies> <!-- 到这结束 -->
-
web.xml里面配置springmvc相关配置
<!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> <display-name>Archetype Created Web Application</display-name> <!--部署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:springmvc.xml</param-value> </init-param> <!-- 表示容器在启动时立即加载servlet --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 处理所有URL--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
编写Controller方法逻辑
HelloController
package com.zjj.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { @RequestMapping("/hello") public String hello(){ return "hello"; } }
-
编写前端页面
hello.jsp 位于web-inf/jsp目录底下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> Hello World!!! </body> </html>
-
配置Springmvc配置文件
springmvc.xml 在resource根目录下创建springmvc.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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描的包 可以自动识别该包下的所有的注解 --> <context:component-scan base-package="com.zjj" /> <!-- 注解驱动 表示对springmvc相关注解的支持 --> <mvc:annotation-driven> </mvc:annotation-driven> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
-
浏览器访问测试,展示效果
http://localhost:8080/springmvc0100_war/hello
springmvc执行原理(面试题):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oIF2InBu-1634699919005)(image\springmvc.png)]
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
springmvc前后端取值传值:
处理post中文乱码问题
在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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
取值:
- login.jsp登录页面
<%--
Created by IntelliJ IDEA.
User: mumusan
Date: 2021/4/24
Time: 16:04
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>
<form action="login1" method="post">
用户名: <input type="text" name="username"><br>
密码: <input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
- UserController:
package com.zjj.controller;
import com.zjj.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
@Controller
public class UserController {
//通过request对象来取值
@RequestMapping("/login1")
public String login1(HttpServletRequest request){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("用户名: "+username+"密码: "+password);
return "list";
}
//参数名必须和前端表单name属性值保持一致
@RequestMapping("/login2")
public String login2(String username,String password){
System.out.println("用户名: "+username+"密码: "+password);
return "list";
}
//当参数名和属性名不一致时,通过注解@RequestParam来配置对应关系
@RequestMapping("/login3")
public String login3(@RequestParam(name = "username") String name, @RequestParam(name = "password") String pass){
System.out.println("用户名: "+name+"密码: "+pass);
return "list";
}
//通过javabean来取值,前端表单name属性值必须和实体类属性名称对应一致
@RequestMapping("/login4")
public String login4(User user){
System.out.println("用户名: "+user.getUsername()+"密码: "+user.getPassword());
return "list";
}
}
- 实体类User:
package com.zjj.pojo;
public class User {
private Integer id;
private String username;
private String password;
//构造方法,gettersetter方法,toString方法略
}
- 浏览器访问:
http://localhost:8080/springmvc0100_war/login.jsp
传值:
-
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="login7" method="post"> 用户名: <input type="text" name="username"><br> 密码: <input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> </html>
-
UserController
//传值 //通过ModelAndView @RequestMapping("/login5") public ModelAndView login5(User user){ ModelAndView modelAndView=new ModelAndView("list"); modelAndView.addObject("user",user); return modelAndView; } //通过Model对象 @RequestMapping("/login6") public String login6(User user, Model model){ model.addAttribute("user",user); return "list"; } //通过Map集合 @RequestMapping("/login7") public String login7(User user, Map map){ map.put("user",user); return "list"; }
-
list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> 主页面 用户名:${user.username} 密码: ${user.password} </body> </html>
-
浏览器访问测试
http://localhost:8080/springmvc0100_war/login.jsp
springmvc类型转换和格式化:
类型转换器:
Spring MVC 框架的 Converter<S,T> 是一个可以将一种数据类型转换成另一种数据类型的接口,这里 S 表示源类型,T 表示目标类型。也可以自定义类型转换器。
demo: 有一个应用 springMVCDemo 希望用户在页面表单中输入信息来创建商品信息。当输入“apple,10.58,200”时表示在程序中自动创建一个 new Goods,并将“apple”值自动赋给 goodsname 属性,将“10.58”值自动赋给 goodsprice 属性,将“200”值自动赋给 goodsnumber 属性。
-
前端input.jsp
input.jsp 注意: 商品数据信息此时以字符串形式某种格式来传输
<form action="good" method="post"> 请输入商品信息(格式为apple,10.58,200) <input type="text" name="goods"><br/> <input type="submit" value="提交"> </form>
-
编写实体类Goods
Goods:
package com.zjj.pojo; public class Goods { private String goodsName; private double price; private int nums; public Goods() { } public Goods(String goodsName, double price, int nums) { this.goodsName = goodsName; this.price = price; this.nums = nums; } public String getGoodsName() { return goodsName; } public void setGoodsName(String goodsName) { this.goodsName = goodsName; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getNums() { return nums; } public void setNums(int nums) { this.nums = nums; } @Override public String toString() { return "Goods{" + "goodsName='" + goodsName + '\'' + ", price=" + price + ", nums=" + nums + '}'; } }
-
后台GoodsController取表单值
注意: 因为前台是所有属性是字符串类型的,后台我直接以Goods对象来接受,是取不到值的,所以需要类型转换,将String转换为Goods,需要自定义类型转换器
package com.zjj.controller; import com.zjj.pojo.Goods; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class GoodsController { @RequestMapping("/good") public String myGood(@RequestParam("goods")Goods good, Model model){ model.addAttribute("good",good); return "showGoods"; } }
-
前端showGoods.jsp,用于展示controller传过来的数据
此时是取不到值的,因为类型不一致
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> 您输入的商品信息是:${good} 商品名称是: ${good.goodsName} 价格是: ${good.price} 数量: ${good.nums} </body> </html>
-
编写自定义类型转换器GoodsConverter
实现Converter<String, Goods>接口 String为源类型,Goods为目标类型
package com.zjj.convert; import com.zjj.pojo.Goods; import org.springframework.core.convert.converter.Converter; public class GoodsConverter implements Converter<String, Goods> { @Override public Goods convert(String s) { //以,拆分 String[] arrs = s.split(","); if(arrs!=null&&arrs.length==3){ Goods goods=new Goods(arrs[0],Double.parseDouble(arrs[1]),Integer.parseInt(arrs[2])); return goods; } return null; } }
-
在springmvc配置文件里面配置类型转换器
<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描的包 可以自动识别该包下的所有的注解 --> <context:component-scan base-package="com.zjj" /> <!--注册类型转换器--> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.zjj.convert.GoodsConverter"/> </list> </property> </bean> <!-- 注解驱动 表示对springmvc相关注解的支持 --> <mvc:annotation-driven conversion-service="conversionService"> </mvc:annotation-driven> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
-
浏览器访问,展示运行效果
http://localhost:8080/springmvc0100_war/input.jsp
格式转换器:
-
编写addStu.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="addStu" method="post"> <table> <tr> <td>学号:</td> <td><input type="text" name="stuNo"></td> </tr> <tr> <td>姓名:</td> <td><input type="text" name="stuName"></td> </tr> <tr> <td>生日</td> <td><input type="date" name="birthday"></td> </tr> <tr> <td></td> <td><input type="submit" name="添加学生"></td> </tr> </table> </form> </body> </html>
-
编写实体类Student
package com.zjj.pojo; import java.util.Date; public class Student { private int stuNo; private String stuName; private Date birthday; public Student() { } public Student(int stuNo, String stuName, Date birthday) { this.stuNo = stuNo; this.stuName = stuName; this.birthday = birthday; } public int getStuNo() { return stuNo; } public void setStuNo(int stuNo) { this.stuNo = stuNo; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String toString() { return "Student{" + "stuNo=" + stuNo + ", stuName='" + stuName + '\'' + ", birthday=" + birthday + '}'; } }
-
编写StudentController
controller里面不能处理date日期类型的数据,会报400错误,类型不匹配,需要格式转换器
package com.zjj.controller; import com.zjj.pojo.Student; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class StudentController { @RequestMapping("/addStu") public String addStudent(Student student, Model model){ System.out.println(student); model.addAttribute("stu",student); return "showStu"; } }
-
编写showStu.jsp,用来显示controller传过来的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <html> <head> <title>Title</title> </head> <body> 学号: ${stu.stuNo} 学生姓名: ${stu.stuName} 生日:<fmt:formatDate value="${stu.birthday}" pattern="yyyy年MM月dd日"/> </body> </html>
-
编写自定义格式转换器DateFormatter
package com.zjj.convert; import org.springframework.format.Formatter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class DateFormatter implements Formatter<Date> { //日期格式化对象 private SimpleDateFormat dateFormat; public SimpleDateFormat getDateFormat() { return dateFormat; } public void setDateFormat(SimpleDateFormat dateFormat) { this.dateFormat = dateFormat; } //解析 @Override public Date parse(String s, Locale locale) throws ParseException { return dateFormat.parse(s); } //显示 @Override public String print(Date date, Locale locale) { return dateFormat.format(date); } }
-
springmvc配置格式转换器
<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描的包 可以自动识别该包下的所有的注解 --> <context:component-scan base-package="com.zjj" /> <!--转换器--> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 配置自定义类型转换器--> <property name="converters"> <list> <bean class="com.zjj.convert.GoodsConverter"/> </list> </property> <!-- 配置自定义格式转换器--> <property name="formatters"> <list> <bean class="com.zjj.convert.DateFormatter"> <property name="dateFormat" value="yyyy-MM-dd"/> </bean> </list> </property> </bean> <!-- 注解驱动 表示对springmvc相关注解的支持 --> <mvc:annotation-driven conversion-service="conversionService"> </mvc:annotation-driven> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
-
浏览器访问,测试运行效果
http://localhost:8080/springmvc0100_war/addStu.jsp
springmvc统一异常的处理:
统一处理某一类异常,能够减少代码的重复度和复杂度,有利于代码的维护。
- 局部控制
@ExceptionHandler
使用@ExceptionHandler注解作用在方法上面,参数是具体的异常类型。一旦系统抛出这种类型的异常时,会引导到该方法来处理。但是它的缺陷很明显
处理异常的方法和出错的方法(或者异常最终抛出来的地方)必须在同一个controller,不能全局控制。
FFFController:
package com.zjj.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class FFFController {
@RequestMapping("error002")
@ResponseBody
public String error002(){
int i=1/0;
return null;
}
}
EEEController:
package com.zjj.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class EEEController {
@RequestMapping("error001")
@ResponseBody
public String error001(){
int i=1/0;
return null;
}
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public String error003(){
return "runtime exception...";
}
}
测试效果:
当访问error001时,异常能够处理;当访问error002时,异常不能处理,所以处理异常的方法和出错的方法(或者异常最终抛出来的地方)必须在同一个controller,不能全局控制
- 全局处理
@ControllerAdvice @ExceptionHandler
使用@ControllerAdvice 和@ExceptionHandler 可以全局控制异常,使业务逻辑和异常处理分隔开。
GlobalExceptionHandler:
package com.zjj.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handlerAllException(Exception e){
System.out.println("handler Exception");
return "error";
}
}
error.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
处理所有的异常信息
</body>
</html>
此时再访问error002,异常就能处理,会自动跳转到error.jsp异常页面
SSM环境搭建:
1. 概述:
在写代码之前我们先了解一下这三个框架分别是干什么的?
- SpringMVC:它用于web层,相当于controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子,用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,并且调用controller层中相应的方法,(中间可能包含验证用户名和密码的业务逻辑,以及查询数据库操作,但这些都不是springmvc的职责),最终把结果返回给用户,并且返回相应的页面(当然也可以只返回json/xml等格式数据)。springmvc就是做前面和后面过程的活,与用户打交道!!
- Spring:太强大了,以至于我无法用一个词或一句话来概括它。但与我们平时开发接触最多的估计就是IOC容器,它可以装载bean(也就是我们java中的类,当然也包括service dao里面的),有了这个机制,我们就不用在每次使用这个类的时候为它初始化,很少看到关键字new。另外spring的aop,事务管理等等都是我们经常用到的。
- MyBatis:数据访问层框架,封装的是jdbc; 如果你问我它跟鼎鼎大名的Hibernate有什么区别?我只想说,他更符合我的需求。第一,它能自由控制sql,这会让有数据库经验的人(当然不是说我啦捂脸)编写的代码能搞提升数据库访问的效率。第二,它可以使用xml的方式来组织管理我们的sql,因为一般程序出错很多情况下是sql出错,别人接手代码后能快速找到出错地方,甚至可以优化原来写的sql。
2. SSM框架整合配置
2.1 开发环境
IDE: idea 2020.1
JDK: 1.8
MySql: 5.7
tomcat: 9版本
Maven: 3.6.0
2.2 完整的项目结构
配置文件,参考demo已经上传U+平台,注意参考
完成的项目结构是这样子的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YUvFKDOB-1634699919006)(image\ssm03.png)]
配置文件说明:
log4j.properties: 日志配置文件
db.properties: 数据库连接的数据源配置信息
mybatis-config.xml: mybatis配置文件
UserMapper.xml: mybatis映射文件
spring-mybatis.xml: spring和mybatis整合的配置文件,将mybatis的相关配置通过spring配置的方式来实现注入
spring-mvc.xml: springmvc的配置文件
web.xml web工程的核心配置文件
3. 创建Maven WEB工程
File---->new project------>Maven----->勾选 Create from archetype复选框------>选择 maven-archetype-webapp-- next—>输入 project name ,maven坐标---->next------->finish
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VSvbsU4p-1634699919007)(image\ssm01.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KPXVtBng-1634699919008)(image\ssm02.png)]
下一步,finish完成即可
注意: 前提是idea已经关联好本机maven,使用maven时一定要联网,一定要等项目创建成功
创建成功之后,进入到 工程的pom.xml文件里面,吧下面相关内容删掉,从name标签到bulid标签删掉
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zjj</groupId>
<artifactId>ssm0100</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!--从这开始 -->
<!--开始结束中间内容删掉,这些是自动生成的,用不着 -->
<name>ssm0100 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>ssm01</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<!--到这结束 -->
</project>
下一步: 吧maven工程的src/main/java; src/main/resources; src/test/java目录补全,没有的话新建即可
4. 在pom.xml文件中导入所需的所有的依赖
从这开始—到这结束 中间内容 复制进去尽可以
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zjj</groupId>
<artifactId>ssm0100</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- 从这开始 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<!-- spring版本号 -->
<spring.version>4.3.14.RELEASE</spring.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.7.22</slf4j.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</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-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument-tomcat</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</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>
<!-- springmvc -->
<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>
<!-- mybatis 包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--mybatis spring 插件 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!-- 上传下载 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.1</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- pagehelper分页插件 -->
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.5</version>
</dependency>
<!-- poi上传下载组件 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14-beta1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.14-beta1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14-beta1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans -->
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.30</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8082</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- 到这结束 -->
</project>
导入之后记得更新maven依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iKql5Eyx-1634699919010)(image\ssm04.png)]
5. 整合思路
1、Dao层:
mybatis-config.xml: Mybatis的配置文件;可以配置mybatis的日志信息,别名配置,分页插件等 ;
文件必须存在。
spring-mybatis.xml:mybatis整合spring,通过由spring创建数据库连接池,spring管理SqlSessionFactory、 mapper代理对象。需要mybatis和spring的整合包。
2、Service层:
3、控制层:
Springmvc框架,由springmvc管理controller
spring-mvc.xml:springmvc配置文件
6. 加入配置文件
配置文件说明:
log4j.properties: 日志配置文件
db.properties: 数据库连接的数据源配置信息
mybatis-config.xml: mybatis配置文件
UserMapper.xml: mybatis映射文件
spring-mybatis.xml: spring和mybatis整合的配置文件,将mybatis的相关配置通过spring配置的方式来实现注入
spring-mvc.xml: springmvc的配置文件
web.xml web工程的核心配置文件
记得所有配置搭完之后最后再启动服务器;启动服务器 不能有报错信息。如果有报错提示,说明配置信息有问题
1. db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/b?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
注意: 其中url中数据库名,数据库密码一定要和自己的保持一致
2. log4j.properties
里面内容无需改动,直接复制即可;配置日志信息,执行操作时可以看到sql语句及参数
log4j.rootLogger=debug,stdout,logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.Java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
3. mybatis-config.xml
mybatis配置文件;注意不要忘了setting里面配置mybatis-3-config.dtd 这个,否则标签没有提示功能
注意: 别名的配置包名一定要和自己的pojo实体类包名保持一致;
pagehelper分页插件是mybatis的一个分页插件,可以很好地实现分页功能, 配上吧
<?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>
<!-- 配置日志信息 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 别名配置方式二 -->
<typeAliases>
<!-- 配置该包底下的所有的类默认使用类名表示别名 -->
<package name="com.zjj.pojo"/>
</typeAliases>
<!-- 配置分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
4. spring-mybatis.xml
spring和mybatis整合的配置文件,其实就是把mybatis的sqlSessionFactory,数据源,事务等信息通过spring来给他注入
注意: 这个配置 包名一定要和自己dao的包名保持一致
映射文件默认在resources/mapper/*Mapper.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 引入外部properties文件 -->
<context:property-placeholder location="classpath:/db.properties" />
<!-- 配置数据源 -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<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>
<!-- 配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 引入mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 引入mybatis映射文件 -->
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
</bean>
<!-- 自动扫描 将Mapper接口生成代理注入到Spring 基于xml方式的-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zjj.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- 配置引入映射文件 基于注解方式的 -->
<!--
<bean class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.zjj.dao.UserDao" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
-->
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务的注解驱动 -->
<tx:annotation-driven/>
</beans>
5. web.xml
在WEB-INF目录下,这个文件一定要配置,不能忘记;注意注意注意!!!
<!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>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
<!-- 配置中文乱码过滤器 -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置spring在web项目中的使用 配置spring的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置springmvc的核心分发器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 引入springmvc的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 配置servlet的加载时机 1表示tomcat启动的时候加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- / 代表项目名底下所有 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- ssm配置静态资源访问2 某种类型的资源文件 的访问-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
</web-app>
6. spring-mvc.xml
springmvc的配置文件
注意: <context:component-scan base-package=“com.zjj” /> 包名一定写成所有组件的父包
<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置自动扫描的包 可以自动识别该包下的所有的注解 -->
<context:component-scan base-package="com.zjj" />
<!-- 注解驱动 表示对springmvc相关注解的支持 -->
<!-- json 转换器 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<description>JSON转换器</description>
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置类似于全局的拦截器 如果项目中用到拦截器,需要配此项,如果没用的到拦截器,不能配,否则会报错-->
<!--
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<bean class="com.bw.util.PermissionIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
-->
<!-- 配置上传解析器 -->
<!-- 设置文件上传大小 -->
<!-- 配置编码 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="MaxUploadSize">
<value>6000000</value>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<!--静态资源的处理-->
<mvc:default-servlet-handler/>
<!-- 静态资源访问配置
1. 在springmvc配置文件里面配某个目录的访问
2. 在web.xml文件里面配置某种后缀名的文件可以访问
两种配置方式选择一种
-->
<!-- 配置静态资源的映射 -->
<!-- <mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/img/" mapping="/img/**" />
-->
</beans>
7. 环境搭建
到这里,其实整个框架的搭建已经基本了,毕竟整点就是上边这堆配置文件嘛,接下来,编写每层的代码。
参考如下架构
父包:
com.zjj 下面子包 pojo,dao,service,controller
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HfeEg9Kz-1634699919011)(image\ssm03.png)]
1. 数据库表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o6ifFDl6-1634699919012)(image\ssm05.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oHNAwJF5-1634699919013)(image\ssm06.png)]
2. pojo实体类User
User:
package com.zjj.pojo;
public class User {
private Long id;
private String username;
private String password;
private Integer isadmin;
public User() {
}
public User(Long id, String username, String password, Integer isadmin) {
this.id = id;
this.username = username;
this.password = password;
this.isadmin = isadmin;
}
public User(String username, String password, Integer isadmin) {
this.username = username;
this.password = password;
this.isadmin = isadmin;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getIsadmin() {
return isadmin;
}
public void setIsadmin(Integer isadmin) {
this.isadmin = isadmin;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", isadmin=" + isadmin +
'}';
}
}
3. dao层接口
UserDao:
package com.zjj.dao;
import com.zjj.pojo.User;
import java.util.List;
public interface UserDao {
//查询所有
public List<User> queryAllUsers();
}
4. mybatis映射文件
UserMapper.xml 注意路径 位于 resources/mapper目录下
**注意: **namespace 值必须和接口路径保持一致
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 值必须和接口路径保持一致-->
<mapper namespace="com.zjj.dao.UserDao">
<!--查询所有 -->
<select id="queryAllUsers" resultType="User">
select * from tb_user
</select>
</mapper>
5. service层代码
UserService:
package com.zjj.service;
import com.zjj.pojo.User;
import java.util.List;
public interface UserService {
//查询所有
public List<User> queryAllUsers();
}
UserServiceImpl:
注意:@Service @Transactional 注解的配置
package com.zjj.service.impl;
import com.zjj.dao.UserDao;
import com.zjj.pojo.User;
import com.zjj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public List<User> queryAllUsers() {
return userDao.queryAllUsers();
}
}
6. controller层代码
UserController:
package com.zjj.controller;
import com.zjj.pojo.User;
import com.zjj.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/list")
public String queryAllUsers(Model model){
List<User> users = userService.queryAllUsers();
model.addAttribute("list",users);
return "list";
}
}
7. 前端页面
list.jsp页面位于 WEB-INF/jsp目录底下,视图解析器里面有相应的前缀和后缀的配置
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<center>
<h1>学生信息管理系统</h1>
<table width="60%" height="40%">
<tr>
<td>编号</td>
<td>姓名</td>
<td>密码</td>
<td>管理员</td>
</tr>
<c:forEach items="${list}" var="u">
<tr>
<td>${u.id}</td>
<td>${u.username}</td>
<td>${u.password}</td>
<td>${u.isadmin}</td>
</tr>
</c:forEach>
</table>
</center>
</body>
</html>
8. 启动tomcat服务器,浏览器访问,测试运行效果
url: http://localhost:8080/ssm0100_war/user/list
运行效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ahLS1MtI-1634699919014)(image/ssm07.png)]
环境搭建成功!!!
后续功能点:
登录 注册 增删改查 模糊查询 区间查询 分页(pagehelper分页插件)
demo1: 使用SSM实现用的的登录和注册功能:
springmvc里面正常返回值后面会加视图解析器的前缀和后缀;
但是请求转发和重定向不会加前缀和后缀,直接跳转到forward或者redirect的地址
springmvc实现请求转发和重定向的方式:
return “forward:地址” 请求转发
return “redirect:地址” 重定向
ssm环境搭建
大前提,环境搭建搭建成功,直接往里面填写代码
eg1: 实现登录功能
-
数据库表user
还使用环境搭建的tb_user表 id username password isadmin
-
编写pojo实体类 User
public class User { private Long id; private String username; private String password; private Integer isadmin; //................ }
-
login.jsp 放在web根路径下,它是入口文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <center> <h1>登录页面</h1> <form action="login" method="post"> <table> <tr> <td>用户名</td> <td><input type="text" name="username"></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password"></td> </tr> <tr> <td><input type="submit" value="登录"></td> <td><a href="register.jsp">立即注册</a></td> </tr> </table> </form> </center> </body> </html>
-
dao层接口及映射文件配置
UserDao
public User queryUserByUsernameAndPassword(User user);
UserServiceImpl
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace 值必须和接口路径保持一致--> <mapper namespace="com.zjj.dao.UserDao"> <resultMap id="userResultMap" type="User"> </resultMap> <!-- 登录 --> <select id="queryUserByUsernameAndPassword" resultMap="userResultMap" parameterType="User"> select * from tb_user where username=#{username} and password=#{password} </select> </mapper>
-
service层接口及其实现
UserService:
package com.zjj.service; import com.zjj.pojo.User; public interface UserService { //登录 public User queryUserByUsernameAndPassword(User user); }
UserServiceImpl:
package com.zjj.service.impl; import com.zjj.dao.UserDao; import com.zjj.pojo.User; import com.zjj.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User queryUserByUsernameAndPassword(User user) { return userDao.queryUserByUsernameAndPassword(user); } }
-
controller中login()方法
UserController:
package com.zjj.controller; import com.zjj.pojo.User; import com.zjj.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class UserController { @Autowired private UserService userService; @RequestMapping("/login") public String login(User user,Model model){ User htUser=userService.queryUserByUsernameAndPassword(user); return "stulist"; } }
-
主页面stulist.jsp: 登录成功跳转主页面 位于web/inf/jsp目录底下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> 主页面 </body> </html>
-
浏览器访问测试
http://localhost:8080/ssm0100_war/login.jsp
eg2:实现注册功能
-
register.jsp 位于web根目录底下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <center> <h1>注册页面</h1> <form action="register" method="post"> <table> <tr> <td>用户名</td> <td><input type="text" name="username"></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password"></td> </tr> <tr> <td><input type="radio" name="isadmin" value="1">管理员</td> <td><input type="radio" name="isadmin" value="2" checked>普通用户</td> </tr> <tr> <td><input type="submit" value="注册"></td> <td><input type="reset" value="重置"></td> </tr> </table> </form> </center> </body> </html>
-
dao层接口及映射文件配置
UserDao:
public int insertUser(User user);
UserMapper.xml:
<!--注册--> <insert id="insertUser" parameterType="User"> insert into tb_user values (0,#{username},#{password},#{isadmin}) </insert>
-
service层接口及其实现
UserService:
//注册 public boolean addUser(User user);
UserServiceImpl:
@Override public boolean addUser(User user) { int row = userDao.insertUser(user); if(row>0){ return true; } return false; }
-
controller中register()方法
注册成功,重定向到login.jsp; 注册失败,回到register.jsp
@RequestMapping("/register") public String register(User user,Model model){ boolean flag=userService.addUser(user); if(flag){ return "redirect:login.jsp"; } return "redirect:register.jsp"; }
-
浏览器访问测试
http://localhost:8080/ssm0100_war/register.jsp
demo2: 实现查询所有学生信息功能
-
设计数据表表tb_stu
int sid; varchar sname; date birthday;varchar address ; varchar photo
-
编写实体类Student
package com.zjj.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor public class Student { private Integer id; private String stuName; private Date birthday; private String address; private String photo;//头像 }
-
编写dao层及映射文件
StudentDao:
package com.zjj.dao; import com.zjj.pojo.Student; import java.util.List; public interface StudentDao { //查询所有 public List<Student> queryAllStudents(); }
StudentMapper.xml:
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zjj.dao.StudentDao"> <resultMap id="stuResultMap" type="Student"> <id property="id" column="sid"/> <result property="stuName" column="sname"/> <result property="birthday" column="birthday"/> <result property="address" column="address"/> <result property="photo" column="photo"/> </resultMap> <!-- 查询所有 --> <select id="queryAllStudents" resultMap="stuResultMap"> select * from tb_stu </select> </mapper>
-
编写service层及实现类
StudentService:
package com.zjj.service; import com.zjj.pojo.Student; import java.util.List; public interface StudentService { public List<Student> queryAllStudents(); }
StudentServiceImpl:
package com.zjj.service.impl; import com.zjj.dao.StudentDao; import com.zjj.pojo.Student; import com.zjj.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class StudentServiceImpl implements StudentService { @Autowired private StudentDao studentDao; @Override public List<Student> queryAllStudents() { return studentDao.queryAllStudents(); } }
-
编写Controller里面的查询所有信息的逻辑
StudentController:
@ResponseBody注解表示将返回值以json数据格式显示在浏览器上面
package com.zjj.controller; import com.zjj.pojo.Student; import com.zjj.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.util.List; @Controller public class StudentController { @Autowired private StudentService studentService; /* @RequestMapping("list") @ResponseBody public List<Student> listAllStudents(){ return studentService.queryAllStudents(); }*/ @RequestMapping("list") public String listAllStudents(Model model){ List<Student> students = studentService.queryAllStudents(); model.addAttribute("list",students); return "stulist"; } }
-
编写stulist.jsp
<%-- Created by IntelliJ IDEA. User: mumusan Date: 2021/5/17 Time: 10:36 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <html> <head> <title>Title</title> </head> <body> <center> <h1>学生管理系统</h1> <table width="60%" heigh="40%"> <tr> <td>编号</td> <td>学生姓名</td> <td>生日</td> <td>地址</td> <td>头像</td> <td><a href="">添加学生信息</a></td> </tr> <c:forEach items="${list}" var="s"> <tr> <td>${s.id}</td> <td>${s.stuName}</td> <td> <fmt:formatDate value="${s.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate> </td> <td>${s.address}</td> <td> <img src="${s.photo}" width="150px" height="150px"/></td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr> </c:forEach> </table> </center> </body> </html>
-
浏览器访问测试
将登陆成功之后路径重定向到list
if(htUser!=null){ return "redirect:list"; }
直接访问登录页面,登录成功之后就自动跳转到列表页面
如果在web.xml里面配上欢迎页,tomcat启动的时候将默认访问该页面
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
demo3: 使用PageHelper实现分页功能
-
引入PageHelper分页插件依赖
<!-- pagehelper分页插件 --> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency>
-
在mybatis配置文件里面配置分页的拦截器
mybatis-config.xml
<!-- 配置分页插件 --> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库--> <property name="helperDialect" value="mysql"/> <property name="reasonable" value="true"/> </plugin> </plugins>
-
编写service接口及实现类分页的方法
StudentService
//分页查询 public PageInfo<Student> queryStudentsByPage(int currentPage, int pageSize);
StudentServiceImpl
@Override public PageInfo<Student> queryStudentsByPage(int currentPage, int pageSize) { //传入参数:当前页和每页条数 PageHelper.startPage(currentPage,pageSize); List<Student> students = studentDao.queryAllStudents(); //通过包装获取分页所需的其他值 PageInfo<Student> pageInfo = new PageInfo<>(students); return pageInfo; }
-
编写分页的controller
StudentController:
@RequestMapping("listpage") public String listAllStudents(Integer currentPage,Integer pageSize,Model model){ if(currentPage==null){ currentPage=1; } if(pageSize==null){ pageSize=3; } PageInfo<Student> page = studentService.queryStudentsByPage(currentPage, pageSize); model.addAttribute("page",page); return "stulistpage"; }
-
编写前端的分页页面
stulistpage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" isErrorPage="false" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <html> <head> <title>Title</title> </head> <body> 欢迎${sessionScope.user.username}登陆 <center> <h1>学生管理系统</h1> <table width="60%" heigh="40%"> <tr> <td>编号</td> <td>学生姓名</td> <td>生日</td> <td>地址</td> <td>头像</td> <td><a href="toadd">添加学生信息</a></td> </tr> <c:forEach items="${page.list}" var="s"> <tr> <td>${s.id}</td> <td>${s.stuName}</td> <td> <fmt:formatDate value="${s.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate> </td> <td>${s.address}</td> <td> <img src="show?path=${s.photo}" width="150px" height="150px"/> </td> <td> <a href="load?id=${s.id}">修改</a> <a href="delete?id=${s.id}">删除</a> <a href="download?path=${s.photo}">删除</a> </td> </tr> </c:forEach> </table> <input type="button" onclick="toFirst()" value="首页"> <input type="button" onclick="toPrev()" value="上一页"> 当前页${page.pageNum}|${page.pages}总页数 <input type="button" onclick="toNext()" value="下一页"> <input type="button" onclick="toLast()" value="尾页"> 每页显示<input type="text" size="2" id="pageNo" value="${page.pageSize}">条记录 </center> </body> <script> function toFirst() { var pageSize= document.getElementById("pageNo").value; location.href="listpage?currentPage=1&pageSize="+pageSize; } function toPrev() { var pageSize= document.getElementById("pageNo").value; location.href="listpage?currentPage=${page.prePage}&pageSize="+pageSize; } function toNext() { var pageSize= document.getElementById("pageNo").value; location.href="listpage?currentPage=${page.nextPage}&pageSize="+pageSize; } function toLast() { var pageSize= document.getElementById("pageNo").value; location.href="listpage?currentPage=${page.lastPage}&pageSize="+pageSize; } </script> </html>
-
修改登录成功之后跳转到分页的逻辑
登录成功之后跳转到分页的逻辑,并且登录成功之后吧登陆的用户信息c存到HttpSession对象里面,
进而可以在首页展示登录用户的信息
UserController
@RequestMapping("/login") public String login(User user, HttpServletRequest request){ User htUser = userService.login(user); //判断是否登录成功 if(htUser!=null){ HttpSession session = request.getSession(); session.setAttribute("user",htUser); return "redirect:listpage"; } //return "redirect:login.jsp"; 重定向 // return "forward:login.jsp"; 请求转发 return "redirect:login.jsp"; }
-
浏览器访问测试
http://localhost:8080/stuManage_war/login.jsp
demo4: 实现学生信息的增删改查功能
项目目录结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EInfLP8k-1634699919016)(image\crud01.png)]
思路:
添加:
由于add.jsp位于WEB-INF目录底下,WEB-INF下的文件内容客户端浏览器无法直接访问,所以需要经过后台中转下
<a href="toadd">添加学生信息</a>------>toAdd的后台controller------->add.jsp
----->用户输入添加数据,点击添加按钮,跳转到后台add的controller------>
添加成功,回到listpage分页列表;失败,回到add.jsp继续添加
删除:
根据id来删除该行的数据信息
<a href="delete?id=${s.id}">删除</a>------> delete 删除的后台controller
------->删除成功,回到listpage分页列表
修改:
修改功能需要用户再原数据的基础之上吧原数据修改成新数据,所以需要先获取原数据,获取原数据的过程就是查询单个的过程,所以修改时需要先根据id来查询单个
<a href="load?id=${s.id}">修改</a>------>load 后台查询单个------>回到update.jsp 原数据回显到修改页面
--------> 点击修改按钮,实现修改功能-------->update 后台修改功能------>修改成功,回到listpage分页列表
步骤:
-
dao层及映射文件配置
StudentDao:
package com.zjj.dao; import com.zjj.pojo.Student; import java.util.List; public interface StudentDao { //查询所有 public List<Student> queryAllStudents(); //查询单个 public Student queryStudentById(int id); //添加学生 public int addStudent(Student student); //修改学生 public int updateStudent(Student student); //删除学生 public int deleteStudentById(int id); }
StudentMapper.xml:
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zjj.dao.StudentDao"> <resultMap id="stuResultMap" type="Student"> <id property="id" column="sid"/> <result property="stuName" column="sname"/> <result property="birthday" column="birthday"/> <result property="address" column="address"/> <result property="photo" column="photo"/> </resultMap> <!-- 查询所有 --> <select id="queryAllStudents" resultMap="stuResultMap"> select * from tb_stu </select> <insert id="addStudent" parameterType="Student"> INSERT INTO tb_stu (sname, birthday, address, photo) VALUES (#{stuName},#{birthday},#{address},#{photo}); </insert> <select id="queryStudentById" parameterType="int" resultMap="stuResultMap"> select * from tb_stu where sid=#{id} </select> <update id="updateStudent" parameterType="Student"> UPDATE tb_stu SET sname=#{stuName}, birthday=#{birthday}, address=#{address}, photo=#{photo} WHERE sid=#{id} </update> <delete id="deleteStudentById" parameterType="int"> delete from tb_stu where sid=#{id} </delete> </mapper>
-
service层及实现类代码
StudentService:
package com.zjj.service; import com.github.pagehelper.PageInfo; import com.zjj.pojo.Student; import java.util.List; public interface StudentService { //查询所有 public List<Student> queryAllStudents(); //分页查询 public PageInfo<Student> queryStudentsByPage(int currentPage, int pageSize); //查询单个 public Student queryStudentById(int id); //添加学生 public boolean addStudent(Student student); //修改学生 public boolean updateStudent(Student student); //删除学生 public boolean deleteStudentById(int id); }
StudentServiceImpl:
package com.zjj.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.zjj.dao.StudentDao; import com.zjj.pojo.Student; import com.zjj.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class StudentServiceImpl implements StudentService { @Autowired private StudentDao studentDao; @Override public List<Student> queryAllStudents() { return studentDao.queryAllStudents(); } @Override public PageInfo<Student> queryStudentsByPage(int currentPage, int pageSize) { //传入参数:当前页和每页条数 PageHelper.startPage(currentPage,pageSize); List<Student> students = studentDao.queryAllStudents(); //通过包装获取分页所需的其他值 PageInfo<Student> pageInfo = new PageInfo<>(students); return pageInfo; } @Override public Student queryStudentById(int id) { return studentDao.queryStudentById(id); } @Override public boolean addStudent(Student student) { int row = studentDao.addStudent(student); if(row>0){ return true; } return false; } @Override public boolean updateStudent(Student student) { int row = studentDao.updateStudent(student); if(row>0){ return true; } return false; } @Override public boolean deleteStudentById(int id) { int row = studentDao.deleteStudentById(id); if(row>0){ return true; } return false; } }
-
controller层代码
StudentController:
package com.zjj.controller; import com.github.pagehelper.PageInfo; import com.zjj.pojo.Student; import com.zjj.service.StudentService; import com.zjj.util.LoadUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; @Controller public class StudentController { @Autowired private StudentService studentService; /* @RequestMapping("list") @ResponseBody public List<Student> listAllStudents(){ return studentService.queryAllStudents(); }*/ @RequestMapping("list") public String listAllStudents(Model model){ List<Student> students = studentService.queryAllStudents(); model.addAttribute("list",students); return "forward:/stulist.jsp"; } @RequestMapping("listpage") public String listAllStudents(Integer currentPage,Integer pageSize,Model model){ if(currentPage==null){ currentPage=1; } if(pageSize==null){ pageSize=3; } PageInfo<Student> page = studentService.queryStudentsByPage(currentPage, pageSize); model.addAttribute("page",page); return "stulistpage"; } @RequestMapping("add") public String addStudent(Student student, MultipartFile img){ String photo = LoadUtil.uploadPhoto(img); student.setPhoto(photo); boolean flag = studentService.addStudent(student); if(flag){ return "redirect:listpage"; } return "redirect:toadd"; } @RequestMapping("toadd") public String toAdd(){ return "add"; } @RequestMapping("update") public String updateStudent(Student student){ boolean flag = studentService.updateStudent(student); return "redirect:listpage"; } @RequestMapping("delete") public String deleteStudent(int id){ studentService.deleteStudentById(id); return "redirect:listpage"; } @RequestMapping("load") public String loadStudent(int id, Model model){ Student student = studentService.queryStudentById(id); model.addAttribute("s",student); return "update"; } }
-
日期类型的格式转换器代码编写及配置
由于add或update是有日期类型的数据,而springmvc无法直接取到日期类型的数据,所以需要自定义一个日期类型的格式转换器
DateFormatter:
package com.zjj.convert; import org.springframework.format.Formatter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class DateFormatter implements Formatter<Date> { //日期格式化对象 private SimpleDateFormat dateFormat; public SimpleDateFormat getDateFormat() { return dateFormat; } public void setDateFormat(SimpleDateFormat dateFormat) { this.dateFormat = dateFormat; } //解析 @Override public Date parse(String s, Locale locale) throws ParseException { return dateFormat.parse(s); } //显示 @Override public String print(Date date, Locale locale) { return dateFormat.format(date); } }
spring-mvc.xml:
<!-- 注解驱动 表示对springmvc相关注解的支持 --> <!-- json 转换器 --> <mvc:annotation-driven conversion-service="conversionService"> ...... </mvc:annotation-driven> <!--转换器--> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 配置自定义格式转换器--> <property name="formatters"> <list> <bean class="com.zjj.convert.DateFormatter"> <property name="dateFormat" value="yyyy-MM-dd"/> </bean> </list> </property> </bean>
-
前端页面
stulistpage.jsp:
<table width="60%" heigh="40%"> <tr> <td>编号</td> <td>学生姓名</td> <td>生日</td> <td>地址</td> <td>头像</td> <td><a href="toadd">添加学生信息</a></td> </tr> <c:forEach items="${page.list}" var="s"> <tr> <td>${s.id}</td> <td>${s.stuName}</td> <td> <fmt:formatDate value="${s.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate> </td> <td>${s.address}</td> <td> <img src="${s.photo}" width="150px" height="150px"/> </td> <td> <a href="load?id=${s.id}">修改</a> <a href="delete?id=${s.id}">删除</a> </td> </tr> </c:forEach> </table>
add.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <center> <h1>添加学生</h1> <form action="add" method="post"> <table> <tr> <td>姓名</td> <td><input type="text" name="stuName"></td> </tr> <tr> <td>生日</td> <td><input type="date" name="birthday"></td> </tr> <tr> <td>地址</td> <td><input type="text" name="address"></td> </tr> <tr> <td>头像</td> <td><input type="text" name="photo"></td> </tr> <tr> <td><input type="submit" value="添加学生"></td> <td><input type="reset" value="重置"></td> </tr> </table> </form> </center> </body> </html>
update.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<center>
<h1>修改学生</h1>
<form action="update" method="post">
<table>
<tr>
<td>编号</td>
<td><input type="text" name="id" value="${s.id}" readonly></td>
</tr>
<tr>
<td>姓名</td>
<td><input type="text" name="stuName" value="${s.stuName}"></td>
</tr>
<tr>
<td>生日</td>
<td><input type="date" name="birthday" value="${s.birthday}"></td>
</tr>
<tr>
<td>地址</td>
<td><input type="text" name="address" value="${s.address}"></td>
</tr>
<tr>
<td>头像</td>
<td><input type="text" name="photo" value="${s.photo}"></td>
</tr>
<tr>
<td><input type="submit" value="修改学生"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
- 浏览器访问测试效果
demo5: 使用拦截器实现用户未经登录不能访问主逻辑功能
-
创建LoginInterceptor,实现HandlerInterceptor接口
3个方法,拦截的时机不同:
boolean preHandle(): 方法执行之前拦截; 返回值true表示放行,false表示拦截
void postHandle(): 方法接收请求之后,解析视图之前拦截
void afterCompletion(): 方法执行完毕,视图渲染结束之后执行
package com.zjj.inter; import com.zjj.pojo.User; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class LoginInterceptor implements HandlerInterceptor { //方法执行之前拦截 @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { HttpSession session = httpServletRequest.getSession(); User user = (User) session.getAttribute("user"); //true 放行 false拦截 if(user!=null){ return true; } httpServletResponse.sendRedirect("login.jsp"); return false; } //方法接收请求之后,解析视图之前拦截 @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } //方法执行完毕,视图渲染结束之后执行 @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
-
在springmvc配置文件里面进行拦截器的配置
spring-mvc.xml
<!-- 配置类似于全局的拦截器 如果项目中用到拦截器,需要配此项,如果没用的到拦截器,不能配,否则会报错--> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/login"/> <bean class="com.zjj.inter.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
说明:
/** 表示拦截所有
<mvc:exclude-mapping path="/login"/> 表示放行的路径
这个路径要和自己的拦截器路径保持一致
- 测试访问其他的逻辑,如果未经登录,会被拦截,回到login.jsp
demo6: 实现用户头像的上传下载功能:
-
上传下载的工具类
为了方便起见,直接将相关方法封装到了一个工具类里面了,静态方法,直接调用方便
LoadUtil:
package com.zjj.util; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; public class LoadUtil { //上传图片 public static String uploadPhoto(MultipartFile loadimg){ //获取绝对路径 String path ="D:/upload"; File f=new File(path); //如果不存在,直接创建 if(!f.exists()){ f.mkdirs(); } //获取图片名称 String filename = loadimg.getOriginalFilename(); //拼接的图片路径 String filepath=path+"/"+filename; File file = new File(filepath); //上传图片 try { loadimg.transferTo(file); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return filepath; } //回显图片 public static void showPhoto(String photo,HttpServletResponse response){ //获取图片的当前路径 放入读 FileInputStream fis=null; //用response 获取一个写对象的流 ServletOutputStream os=null; try { fis = new FileInputStream(photo); os = response.getOutputStream(); //提高读写的速度 byte[] b=new byte[1024]; //边读边写 while(fis.read(b)!=-1){ os.write(b); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(os!=null){ os.close(); } if(fis!=null){ fis.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //下载 public static void downLoad(String filepath,HttpServletRequest request, HttpServletResponse response){ //设置文件的MiMe类型 response.setContentType(request.getSession().getServletContext().getMimeType(filepath)); //设置content-dispsition response.setHeader("Content-Disposition", "attachment;filename="+filepath); //读取目标文件,通过response将目标文件写到客户 try { //读取文件 InputStream in = new FileInputStream(filepath); OutputStream out=response.getOutputStream(); //写文件 byte[] b=new byte[1024]; while(in.read(b)!=-1){ out.write(b); } in.close(); out.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
-
add.jsp页面改造
add.jsp
注意:
method=“post” enctype=“multipart/form-data” : method必须post请求, enctype="multipart/form-data"表示处理二进制文件
type=“file”: 图片使用文件上传框
<form action="add" method="post" enctype="multipart/form-data"> <table> ....... <%-- <tr> <td>头像</td> <td><input type="text" name="photo"></td> </tr>--%> <tr> <td>请上传头像:</td> <td><input type="file" name="img"></td> </tr> <tr> <td><input type="submit" value="添加学生"></td> <td><input type="reset" value="重置"></td> </tr> </table> </form>
-
后台controller实现上传下载功能
StudentController:
//添加
@RequestMapping("add")
public String addStudent(Student student, MultipartFile img){
String photo = LoadUtil.uploadPhoto(img);
student.setPhoto(photo);
boolean flag = studentService.addStudent(student);
if(flag){
return "redirect:listpage";
}
return "redirect:toadd";
}
//显示头像
@RequestMapping("show")
public void showPhoto(String path, HttpServletResponse response){
LoadUtil.showPhoto(path,response);
}
//下载
@RequestMapping("download")
public void download(String path, HttpServletRequest request,HttpServletResponse response){
LoadUtil.downLoad(path, request, response);
}
-
listpage.jsp 显示图片
由于某些情况下图片不能直接显示,所以需要显示图片的逻辑,就是controller里面的showPhoto()方法
<c:forEach items="${page.list}" var="s"> <tr> ......... <td> <img src="show?path=${s.photo}" width="150px" height="150px"/> </td> <td> <a href="load?id=${s.id}">修改</a> <a href="delete?id=${s.id}">删除</a> <a href="download?path=${s.photo}">下载图片</a> </td> </tr> </c:forEach>
-
测试效果
demo7: 实现登录页面的国际化显示:
-
在resources目录下新建两个properties文件,文件名及内容如下
message_en.properties:
username=username password=password login=login register=register title=Login Page
message_zh_CN.properties:存储的是中文(unicode码):
username=\u7528\u6237\u540d password=\u5bc6\u7801 login=\u767b\u9646 register=\u7acb\u5373\u6ce8\u518c title=\u767b\u9646\u9875\u9762
不会转的使用这个工具类:
public class TestBianMa { public static void main(String[] args) { String uname = "登陆页面"; for (int i = 0; i < uname.length(); i++) { char unamechar = uname.charAt(i); System.out.print(gbEncoding(String.valueOf(unamechar))); } } /** * 把中文转成Unicode编码 * * @param gbString * @return */ private static String gbEncoding(final String gbString) { char[] utfBytes = gbString.toCharArray(); String unicodeBytes = ""; for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) { String hexB = Integer.toHexString(utfBytes[byteIndex]); if (hexB.length() <= 2) { hexB = "00" + hexB; } unicodeBytes = unicodeBytes + "\\u" + hexB; } return unicodeBytes; } }
-
在springmvc xml中配置国际化信息
默认中文
<!--国际化配置--> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="/message"/> </bean> <bean id="cookieLocaleResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> <property name="defaultLocale" value="zh_CN"/> <property name="cookieName" value="language"/> </bean>
-
jsp中登录页面
login.jsp
注意:需要引入spring的标签库:<%@ taglib prefix=“spring” uri=“http://www.springframework.org/tags”%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <html> <head> <title>Title</title> </head> <body> <center> <h1> <spring:message code="title"/> </h1> <form action="login" method="post"> <table> <tr> <td> <spring:message code="username"/></td> <td><input type="text" name="username"></td> </tr> <tr> <td> <spring:message code="password"/></td> <td><input type="password" name="password"></td> </tr> <tr> <td><input type="submit" value="<spring:message code='login'/>"></td> <td><a href="register.jsp"><spring:message code="register"/></a></td> </tr> </table> </form> </center> </body> </html>
-
一般中文是默认语言,所以需要设置英文成默认语言,以win10为例
设置 —》 时间和语言 —》左侧选择 区域和语言
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMxKGDbG-1634699919017)(image\i18n.png)]
没有英文的就需要添加语言
到此就实现了国际化,效果如下:
中文状态下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZVxnESs-1634699919018)(image\zh_CN.png)]
切换英文:
刷新浏览器:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPL4w3dq-1634699919019)(image\en.png)]
SpringBoot环境搭建:
1.项目目录结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHOimtwR-1634699919020)(image\boot01.png)]
2.新建maven工程
注意: maven project: 不是maven web project
3.添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springboot-0100</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
4. 编写application.properties文件
在resources根目录底下,文件名固定,不能改
application.properties: 是SpringBoot的全局配置文件
server.port=8181
5. 编写main方法
Application:
package com.zjj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
6. 编写controller
HelloController:
package com.zjj.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("hello")
public String hello(){
return "hello world!!!!";
}
}
7. 启动main方法
8.浏览器访问测试
http://localhost:8181/hello
运行效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ft7QV8Tv-1634699919021)(image\boot02.png)]
注意:
浏览器访问的端口号和配置文件的端口号一致,
main方法所在的类必须在所有组件的父包里面,这样它会自动扫描
springboot里面内置了tomcat;直接启动main方法即启动tomcat服务器
SpringBoot+MyBatis实现增删改查
1. 设计数据库表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EzHVEo7R-1634699919022)(image\boot04.png)]
2. 新建maven project
注意:不是maven web project,不需要勾选那个复选框
3. pom文件添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bw</groupId>
<artifactId>stuManage-boot</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
spring-boot-starter-parent org.springframework.boot 2.1.4.RELEASE
表示父工程是个SpringBoot项目,继承它自己就成为一个SpringBoot工程了
4. 配置项目配置信息 application.yml
配置文件有两种格式: properties和yml
properties:里面格式是键值对
yml: 一定要注意缩进;相同层次的缩进必须保持相同,否则会有语法问题
server:
port: 8989
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/b?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password: 123456
mybatis:
type-aliases-package: com.zjj.pojo
mapper-locations: classpath:mapper/*Mapper.xml
logging:
level:
com:
zjj:
dao: debug
5. 编写main方法
SpringBoot项目的启动类,必须加上注解@SpringBootApplication
@MapperScan(“com.zjj.dao”): 表示扫描dao层
package com.zjj;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.zjj.dao")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class,args);
}
}
6. 编写pojo实体类
package com.zjj.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer id;
private String stuName;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
private String address;
private String photo;//头像
}
7. 编写dao层代码及映射文件
接口上面必须加注解@Mapper
package com.zjj.dao;
import com.zjj.pojo.Student;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface StudentDao {
//查询所有
public List<Student> queryAllStudents();
public int addStudent(Student student);
public int deleteStudentById(Integer id);
public int updateStudent(Student student);
public Student queryOneStudentById(Integer id);
}
StudentMapper.xml映射文件,位于resources/mapper目录底下
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zjj.dao.StudentDao">
<resultMap id="stuResultMap" type="Student">
<id property="id" column="sid"/>
<result property="stuName" column="sname"/>
<result property="birthday" column="birthday"/>
<result property="address" column="address"/>
<result property="photo" column="photo"/>
</resultMap>
<!-- 查询所有 -->
<select id="queryAllStudents" resultMap="stuResultMap">
select * from tb_stu
</select>
<select id="queryOneStudentById" parameterType="int" resultMap="stuResultMap">
select * from tb_stu where sid=#{id}
</select>
<insert id="addStudent" parameterType="Student">
INSERT INTO `tb_stu` (`sid`, `sname`, `birthday`, `address`, `photo`) VALUES (0, #{stuName}, #{birthday}, #{address}, #{photo})
</insert>
<update id="updateStudent" parameterType="Student">
UPDATE tb_stu SET `sname`=#{stuName}, `birthday`=#{birthday}, `address`=#{address}, `photo`=#{photo} WHERE `sid`=#{id}
</update>
<delete id="deleteStudentById" parameterType="int">
delete from tb_stu where sid=#{id}
</delete>
</mapper>
8. 编写service层代码及实现类
Service接口:
package com.zjj.service;
import com.zjj.pojo.Student;
import java.util.List;
public interface StudentService {
public List<Student> queryAllStudents();
public boolean addStudent(Student student);
public boolean deleteStudentById(Integer id);
public boolean updateStudent(Student student);
public Student queryOneStudentById(Integer id);
}
Service实现类: 注解上面的注解 @Service @Transactional
package com.zjj.service.impl;
import com.zjj.dao.StudentDao;
import com.zjj.pojo.Student;
import com.zjj.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Override
public List<Student> queryAllStudents() {
return studentDao.queryAllStudents();
}
@Override
public boolean addStudent(Student student) {
int row = studentDao.addStudent(student);
if(row>0){
return true;
}
return false;
}
@Override
public boolean deleteStudentById(Integer id) {
int row = studentDao.deleteStudentById(id);
if(row>0){
return true;
}
return false;
}
@Override
public boolean updateStudent(Student student) {
int row = studentDao.updateStudent(student);
if(row>0){
return true;
}
return false;
}
@Override
public Student queryOneStudentById(Integer id) {
return studentDao.queryOneStudentById(id);
}
}
9. 编写controller层代码及实现类
@RestController 表示返回json数据到浏览器上面
package com.zjj.controller;
import com.zjj.pojo.Student;
import com.zjj.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping
public List<Student> listAllStudents(){
return studentService.queryAllStudents();
}
@GetMapping("/{id}")
public Student loadStudentById(@PathVariable int id){
return studentService.queryOneStudentById(id);
}
@PostMapping
public boolean addStudent(@RequestBody Student student){
return studentService.addStudent(student);
}
@PutMapping
public boolean updateStudent(@RequestBody Student student){
return studentService.updateStudent(student);
}
@DeleteMapping("{id}")
public boolean deleteStudentById(@PathVariable int id){
return studentService.deleteStudentById(id);
}
}
10. 启动main方法
SpringBoot内置Tomcat,启动main方法即启动tomcat
SpringBoot对jsp支持不好,一般SpringBoot项目使用前后端分离
11.使用PostMan访问测试效果
下载PostMan测试软件
Vue语法:
参考文档: https://www.runoob.com/vue2/vue-tutorial.html
环境: nodejs
前端开发工具: Visual Studio Code
自行下载安装:
nodejs安装步骤参考网上教程,需要配置环境变量;
VSC: 安装成功后 安装两个插件:
扩展 菜单搜索 Chinese Language 中文插件 Live Server服务器 安装即可
vue-demo:
需要下载并引入vue.min.js vue的库文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>vue语法</h1>
<h1>您的生日是:{{
new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
}}
</h1>
<h1>您的生日是:{{birth}} </h1>
欢迎您: {{name}}<br>
<font color="red" v-text="name"></font>
<font color="red" v-html="name"></font>
num:{{num}}<br>
num: <input v-model="num"/><br>
num1: {{num1}} num2: {{num2}}
请输入第一个数: <input v-model="num1"/>
请输入第二个数: <input v-model="num2"/>
和是:{{sum}} {{add2()}}
求和: <input type="button" value="求和" @click="add"/><br>
地址:<input v-model="person.address"/>
取对象属性:
name: {{person.name}} age: {{person.age}} address: {{person.address}}<br>
取数组:
{{arr}}
循环遍历:
<ul v-for="a in arr">
<li v-text="a"></li>
</ul>
<br>
<!-- a 表示某元素 i 表示下标-->
<ul v-for="(a,i) in arr">
<li v-text="i"></li>
</ul>
<br>
<p v-if="num>num1">{{num}}</p>
<p v-if="num<=num1">{{num1}}</p>
<table border="1">
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td><a href="#">添加</a></td>
</tr>
<tr v-for="s in list">
<td>{{s.id}}</td>
<td>{{s.name}}</td>
<td>{{s.age}}</td>
<td>
<a href="#">删除</a>
<a href="#">修改</a>
</td>
</tr>
</table>
</div>
</body>
<script src="js/vue.min.js"></script>
<script>
new Vue({
el: "#app",
data: {
name: "<h1>张三</h1>",
num: 23,
num1:0,
num2:0,
sum:0,
person:{
name: "李四",
age:23,
address:"北京"
},
arr:["噢噢噢噢","嗯嗯呃呃","哈哈哈","啊啊啊"],
list:[],
birthday:1529032123201 // 毫秒值
},
methods: {
add: function(){
this.sum=parseInt(this.num1)+parseInt(this.num2);
},
add2: function(){
return parseInt(this.num1)+parseInt(this.num2);
}
},
//页面加载事件
created () {
this.list=[
{id:'1',name:'王五',age:23},
{id:'2',name:'赵柳',age:24},
{id:'3',name:'张德',age:18}
]
},
computed:{
birth(){// 计算属性本质是一个方法,但是必须返回结果
const d = new Date(this.birthday);
return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDay();
}
}
})
</script>
</html>
使用VUE搭建前端页面,实现前后端对接:
注意:
页面需要引入3个库文件:
vue的库文件, ajax的库文件, 日期处理的库文件
stulist: 列表页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>学生列表</h1>
<table >
<tr>
<td>编号</td>
<td>学生姓名</td>
<td>生日</td>
<td>地址</td>
<td>头像</td>
<td><a href="add.html">添加学生</a></td>
</tr>
<tr v-for="s in list">
<td>{{s.id}}</td>
<td>{{s.stuName}}</td>
<td>
{{moment(s.birthday).format("YYYY-MM-DD")}}
</td>
<td>{{s.address}}</td>
<td>{{s.photo}}</td>
<td>
<input type="button" @click="update(s.id)" value="修改"/>
<input type="button" @click="del(s.id)" value="删除"/>
</td>
</tr>
</table>
</div>
</body>
<script src="js/vue.min.js"></script>
<script src="js/axios.min.js"></script>
<script src="js/moment-with-locales.js"></script>
<script>
new Vue({
el: "#app",
data: {
id:0,
list:[] //集合使用[] 对象使用{}
},
//初始化方法 被创建的时候执行的逻辑
created () {
this.getData();
},
methods: {
getData: function(){
axios.get("http://127.0.0.1:8989").then(
resp=>{
this.list=resp.data;
console.log(this.list);
}
);
},
del: function(id){
this.id=id;
axios.delete("http://127.0.0.1:8989/"+this.id).then(
resp=>{
console.log(resp);
if(resp.data){
alert("删除成功");
location="stulist.html";
}else{
alert("删除失败");
}
}
);
},
update:function(id){
window.sessionStorage.setItem("id",id);
location="update.html";
}
}
})
</script>
</html>
add.html: 添加页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>添加学生</h1>
<table>
<tr>
<td>学生姓名</td>
<td><input v-model="stu.stuName"/></td>
</tr>
<tr>
<td>生日</td>
<td><input type="date" v-model="stu.birthday"/></td>
</tr>
<tr>
<td>地址</td>
<td><input v-model="stu.address"/></td>
</tr>
<tr>
<td>头像</td>
<td><input v-model="stu.photo"/></td>
</tr>
<tr>
<td><input type="button" @click="fanhui" value="返回"/></td>
<td>
<input type="button" @click="chongzhi" value="重置"/>
<input type="button" @click="save" value="保存"/>
</td>
</tr>
</table>
</div>
</body>
<script src="js/vue.min.js"></script>
<script src="js/axios.min.js"></script>
<script src="js/moment-with-locales.js"></script>
<script>
new Vue({
el: "#app",
data:
{
stu: {
id: 0,
stuName: "",
birthday: moment(new Date()).format("YYYY-MM-DD"),
address:"",
photo:""
}
},
methods: {
fanhui: function(){
location="stulist.html";
},
chongzhi:function(){
location="add.html";
},
//保存方法
save: function(){
axios.post("http://127.0.0.1:8989",this.stu).then(
resp=>{
console.log(resp);
if(resp.data){
alert("添加成功");
location="stulist.html";
}else{
alert("添加失败");
}
}
);
}
}
})
</script>
</html>
update.html: 修改页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>修改学生</h1>
<table>
<tr>
<td>学生编号</td>
<td><input v-model="stu.id" readonly/></td>
</tr>
<tr>
<td>学生姓名</td>
<td><input v-model="stu.stuName"/></td>
</tr>
<tr>
<td>生日</td>
<td><input type="date" v-model="stu.birthday"/></td>
</tr>
<tr>
<td>地址</td>
<td><input v-model="stu.address"/></td>
</tr>
<tr>
<td>头像</td>
<td><input v-model="stu.photo"/></td>
</tr>
<tr>
<td>
<input type="button" @click="update()" value="修改"/>
</td>
<td>
<input type="button" @click="fanhui" value="返回"/>
</td>
</tr>
</table>
</div>
</body>
<script src="js/vue.min.js"></script>
<script src="js/axios.min.js"></script>
<script src="js/moment-with-locales.js"></script>
<script>
new Vue({
el: "#app",
data:
{
stu: {
id: 0,
stuName: "",
birthday: moment(new Date()).format("YYYY-MM-DD"),
address:"",
photo:""
}
},
created () {
this.load();
},
methods: {
fanhui: function(){
location="stulist.html";
},
//修改方法
update: function(){
axios.put("http://127.0.0.1:8989",this.stu).then(
resp=>{
console.log(resp);
if(resp.data){
alert("修改成功");
location="stulist.html";
}else{
alert("修改失败");
}
}
);
},
load:function(){
var id=window.sessionStorage.getItem("id");
console.log("id: "+id);
axios.get("http://127.0.0.1:8989/"+id).then(
resp=>{
console.log(resp);
this.stu=resp.data;
}
);
}
}
})
</script>
</html>
前端直接右键 live-server 服务器运行打开即可
后台Controller上加个注解: @CrossOrigin 解决跨域问题
什么是跨域问题? 百度一下