CSDN对maven项目的部署开发
从配置Maven环境到写出第一个Maven项目_05年的程序员的博客-CSDN博客
1.回顾JDBC项目开发步骤
2.Mybatis框架sql书写位置以及dao层不方法重载的原因
3.Maven+MyBatis项目开发思路
1.建表+书写实体类
①注意:实例类必须实现Serializable实现序列化
②下载lombok使用注解替代快捷键生成全参构造、无参构造、toString(可以不用,但有必要)
package com.gr.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * /*@Data 这个注解就会帮你生成get和set方法,无参构造,toString * @AllArgsConstructor 有参构造 * @NoArgsConstructor 无参构造*/ @Data @AllArgsConstructor @NoArgsConstructor public class Student implements Serializable { private Integer id; private String name; private String sex; private String tel; private Integer age; public Student(String name, String sex, String tel, Integer age) { this.name = name; this.sex = sex; this.tel = tel; this.age = age; } }
2.新建maven项目
①修改GroupID com.gr
②补全项目结构
③根据需求添加及修改配置文件引入依赖
注意:webapp一旦无蓝点证明如下标签没有在pom.xml配置,配置后点击屏幕右侧maven刷新项目
<packaging>war</packaging>
1.在pom.xml下引入依赖
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.gr</groupId> <artifactId>MyBatisStudentManageProject</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>utf-8</project.build.sourceEncoding> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <packaging>war</packaging> <!--指定引入的依赖mysql,servlet,jstl--> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--lombok依赖可以帮助我们自动生成getset方法和构造方法--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- 引入mybatis依赖 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.30</version> </dependency> </dependencies> </project>
2.resources根目录下添加设置mybatis-config.xml文件(配置文件1)
位置:main/resources
<?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> <!-- 提升mybatis体验的标签:--> <typeAliases> <!-- typeAliases 父标签中可以有多个子标签 作用:用来给实体类型起短别名 xxxMapper.xml中如果项目中有很多方法,每个方法都要写resultType的全类名,太麻烦 type:实体类型全类名 alias:短别名 1.定义短别名后依然可以使用全类名 2.短别名不区分大小写,但尽量保持一致 3.<mapper namespace="全类名">绝对不能使用短别名 问题:实体类太多需要一个一个配置,解决办法package子标签 --> <typeAlias type="com.gr.entity.User" alias="u"/> <!-- 比typeAliases常用,只需要配置一个 package:为指定包下所有实体类批量注册短别名,短别名默认是类名(有配置方式:) (示例:com.gr.entity.User ==>User) name:设置entity包的路径 <package name="com.gr.entity"/> --> </typeAliases> <!-- environment:环境(数据库环境) --> <environments default="dev"> <environment id="dev"> <!-- transactionManager 事务管理器 type:设置事务管理的方式 JDBC:手动管理 MANAGED:交给有事务管理能力的容器或框架(Spring)管理 --> <transactionManager type="JDBC"></transactionManager> <!-- dataSource:连接池(提高程序访问数据库的性能) type: POOLED 使用连接池 UNPOOLED 不使用连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <!-- &html和xml中有特殊含义,&开头;结尾 >大于 &表示最普通的与& 使用时不能加空格--> <property name="url" value="jdbc:mysql://localhost:3306/mybatisstudentmanage?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <!-- 123456??--> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 注册,指定dao接口对应的映射文件mapper.xml的路径,设置原因:mybatis只会读取当前主配置文件,权限定名依然要写/--> <mappers> <mapper resource="com/gr/dao/UserDaoMapper.xml"/> <mapper resource="com/gr/dao/StudentDaoMapper.xml"/> </mappers> </configuration>
3.resources根目录下添加设置log4j.properties(配置文件2)
位置:main/resources
log4j.rootLogger=DEBUG, stdout # SqlMap logging configuration... log4j.logger.com.ibatis=DEBUG log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.sqlmap.engine.cache.CacheModel=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientImpl=DEBUG log4j.logger.com.ibatis.sqlmap.engine.builder.xml.SqlMapParser=DEBUG log4j.logger.com.ibatis.common.util.StopWatch=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG log4j.logger.java.sql.ResultSet=DEBUG # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4.resources目录下建分层com/gr/dao文件夹下加入替换daoimpl的xxxMapper.xml,用来书写sql替换书写繁琐的dao层实现类
模板 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.gr.dao.xxxMapper"> </mapper> 依照模板书写sql实现dao层方法 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.gr.dao.StudentDao"> <select id="selectAllStudent" resultType="com.gr.entity.Student"> select s_id id,name,sex,tel,age from t_student </select> <insert id="insertStudent"> insert into t_student values(null,#{name},#{sex},#{tel},#{age}) </insert> <delete id="deleteStudentById"> delete from t_student where s_id=#{id} </delete> <update id="updateStudent"> update t_student set name=#{name},sex=#{sex},tel=#{tel},age=#{age} where s_id=#{id} </update> <select id="selectStudentById" resultType="com.gr.entity.Student"> select s_id id,name,sex,tel,age from t_student where s_id=#{id} </select> <select id="selectByPage" resultType="com.gr.entity.Student"> select s_id id,name,sex,tel,age from t_student limit #{start},#{pageSize} </select> <select id="selectCount" resultType="int"> select count(*) cou from t_student </select> </mapper>
3.书写dao层并测试
①根据需求书写dao层方法,养成习惯方法上面加文档注释
package com.gr.dao; import com.gr.entity.Student; import com.gr.entity.User; import org.apache.ibatis.annotations.Param; import java.util.List; public interface StudentDao { Student selectStudentById(Integer id); List<Student> selectAllStudent(); void deleteStudentById(Integer id); void insertStudent(Student student); void updateStudent(Student student); /** * 查询当前页要显示几条数据 * @param start 要从数据库第几条开始查 * @param pageSize 一页查询几条 * @return 当前页几条数据 */ List<Student> selectByPage(@Param("start") int start,@Param("pageSize") int pageSize); //查询数据库表里面有几条数据 int selectCount(); }
注意:书写完查询所有就可以写分页了,这里直接拿小帅哥总结好的分页思路!
首先正常的分页如果是第一次写可以在查询全部的表格写完后在此基础上再做修改。 需要增加的参数:从第几条开始 start,查询几条数据 , pageSize(自己定),总数据条数 allCount ,当前页数 curPage , 总页数 allPage 书写顺序: ↓ Dao层:(原查所有的方法)由于分页一页显示的是固定的条数所以需要获取limit的两个参数(从第几条开始 start,查询几条 pageSize) ↓ 实现代码:select * from 表名 limit ?,? ↓ (新增方法)用于展示获取总页数,只需获取本表一共有多少数据即可(总数据条数 allCount ) ↓ 实现代码:select count(*) cou from 表名 (cou为别名可不写) Servlet层:由于通常需要给用户显示当前页数和总页数(所以需要获取这两个参数 curPage allPage) ↓ (curPage获取思路:不管有没有先从request作用域获取,由于第一次访问所以还未进入到jsp,所以第一次一定为空,可以加一个小判断解决) ↓ 实现代码: ↓ //尝试从请求路径中获取页号,第一次获取不到,点击下一页或者上一页时候可以获取 ↓ String curPageStr=req.getParameter("curPage"); ↓ int curPage=1;//当前的页数默认值为1 ↓ if (curPageStr!=null){ ↓ curPage= Integer.parseInt(curPageStr); ↓ } ↓ (start获取思路:根据carPage和pageSize获取) ↓ 实现代码: ↓ int pageSize=3;//一页显示的条数,自定 ↓ int start=(curPage-1)*pageSize;//从第几条开始显示的 ↓ (allPage获取思路:可以用上面写出来的获取总条数除于一页的条数获取 ***但是,由于最后一页并不一定显示完全也就是说前面除法有余数,这个余数也是需要单独一页来展示出来的,所以我们用%来判断一下) ↓ 实现代码(根据自己的代码修改): ↓ //获取总条数 ↓ int count=phoneService.allCount(); ↓ //给总页数设置初始值 ↓ int allPage=0; ↓ //如果除尽则为当前页面刚好可以展示全,不需要再加一页 ↓ //如果除不尽则需要再添加一页来展示剩余数据 ↓ if (count%pageSize==0){ ↓ allPage=count/pageSize; ↓ }else { ↓ allPage=count/pageSize+1; ↓ } ↓ //总条数除于一页的条数的总页数就是总页数 ↓ session.setAttribute("allPage",allPage); jsp页面:用超链接来表示上一页下一页(如果嫌丑可以根据自己的喜好添加样式,***上面的数据记得转发过来) ↓ 这里直接展示代码: ↓ <div >当前是第${作用域.curPage}页 ,共${作用域.allPage}页</div> ↓ <a href="${pageContext.request.contextPath}这里是Servlet的注解地址?curPage=${作用域.curPage-1} >上一页</a> ↓ <a href="${pageContext.request.contextPath}这里是Servlet的注解地址?curPage=${作用域.curPage+1}>下一页</a> jsp页面优化:由于便于用户操作添加一个首页尾页,并且不再在第一页显示上一页和首页(解决逻辑问题) ↓ (当然可以根据此处逻辑根据自己的想法修改,如显示第一二三页直接跳转到指定页面) ↓ 代码展示:(用c标签的if判断解决) ↓ <c:if test="${作用域.curPage>1}"> ↓ <a href="${pageContext.request.contextPath}这里是Servlet的注解地址?curPage=1">首页</a> ↓ <a href="${pageContext.request.contextPath}这里是Servlet的注解地址?curPage=${作用域.curPage-1} >上一页</a> ↓ </c:if> ↓ <c:if test="${sessionScope.curPage<sessionScope.allPage}"> ↓ <a href="${pageContext.request.contextPath}这里是Servlet的注解地址?curPage=${作用域.curPage+1}>下一页</a> ↓ <a href="${pageContext.request.contextPath}这里是Servlet的注解地址?curPage=${作用域.allPage}">尾页</a> ↓ </c:if> 这是插件实现:(包自行找,这里是maven导入) 这种写法dao和业务类都比较复杂。我们可以通过mybatis的PageHelper简化我们的开发。 具体步骤: 1. 引入依赖包 <!--mybatis的分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.11</version> </dependency> 1. 在mybatis主配置文件mybatis-config.xml中注册该插件。 要写在实体类别名下面,数据源配置的上面 <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins> 2. 只要在dao里面提供查询所有的方法。 3. 调用dao的时候需要两行代码 SqlSession session = MybatisUtil.getSession(); ProductDao pd = session.getMapper(ProductDao.class); //设置分页信息。第一个参数是页号,第二个参数是一页显示的条数 PageHelper.startPage(1, 3); //查询全部 List<Product> proList = pd.selectAll(); //把查询全部返回的数据封装到PageInfo对象里面。 PageInfo<Product> pi=new PageInfo<>(proList); List<Product> list = pi.getList();//获取到当前页的所有数据 pi.getNextPage();//下一页的页号 pi.getPages();//总页数 boolean hasNextPage = pi.isHasNextPage();//是否有下一页 boolean hasPreviousPage = pi.isHasPreviousPage();//是否有上一页 pi.getPageNum();//当前页号 session.close();
注意:配置mybatis-config.xml 避免dao层测试出现让人头秃的异常
<!-- 注册,指定dao接口对应的映射文件mapper.xml的路径,设置原因:mybatis只会读取当前主配置文件,权限定名依然要写/--> <mappers> <mapper resource="com/gr/dao/UserDaoMapper.xml"/> <mapper resource="com/gr/dao/StudentDaoMapper.xml"/> </mappers>
②在com/gr/dao目录下,根据xxxMapper模板书写dao接口替换原来繁琐的jdbc中的sql语句,一种sql对应一种标签
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.gr.dao.StudentDao"> <select id="selectAllStudent" resultType="com.gr.entity.Student"> select s_id id,name,sex,tel,age from t_student </select> <insert id="insertStudent"> insert into t_student values(null,#{name},#{sex},#{tel},#{age}) </insert> <delete id="deleteStudentById"> delete from t_student where s_id=#{id} </delete> <update id="updateStudent"> update t_student set name=#{name},sex=#{sex},tel=#{tel},age=#{age} where s_id=#{id} </update> <select id="selectStudentById" resultType="com.gr.entity.Student"> select s_id id,name,sex,tel,age from t_student where s_id=#{id} </select> <select id="selectByPage" resultType="com.gr.entity.Student"> select s_id id,name,sex,tel,age from t_student limit #{start},#{pageSize} </select> <select id="selectCount" resultType="int"> select count(*) cou from t_student </select> </mapper>
③在main同级test包下com/gr/test文件夹,新建XxxDaoTest,基于junit@Test的方式,public void TestXxx(){}
注意:不要在此测试类建主函数,建立主函数就不允许在下面写同级测试方法,失去使用junit的意义
package com.gr.test; import com.gr.entity.Student; import com.gr.service.StudentService; import com.gr.service.impl.StudentServiceImpl; import com.gr.util.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class StudentDaoTest { @Test public void TestSelectAll(){ SqlSession session= MyBatisUtils.openSession(); StudentService studentService=new StudentServiceImpl(); List<Student> studentList = studentService.selectAllStudent(); for (Student s:studentList ) { System.out.println(s); } session.commit(); } @Test public void TestInsert(){ SqlSession session= MyBatisUtils.openSession(); StudentService studentService=new StudentServiceImpl(); Student student=new Student("瑞雯","女","666",16); studentService.insertStudent(student); session.commit(); } @Test public void TestDelete(){ SqlSession session= MyBatisUtils.openSession(); StudentService studentService=new StudentServiceImpl(); studentService.deleteStudentById(7); session.commit(); } @Test public void TestUpdate(){ SqlSession session= MyBatisUtils.openSession(); StudentService studentService=new StudentServiceImpl(); studentService.updateStudent(new Student(6,"锐萌萌","女","665",19)); session.commit(); } @Test public void TestSelectById(){ SqlSession session= MyBatisUtils.openSession(); StudentService studentService=new StudentServiceImpl(); Student student=studentService.selectStudentById(6); System.out.println(student); session.commit(); } }
4.书写service层
以User+student管理系统为例
package com.gr.service; import com.gr.entity.Student; import org.apache.ibatis.annotations.Param; import java.util.List; public interface StudentService { public Student selectStudentById(Integer id); public List<Student> selectAllStudent(); public void deleteStudentById(Integer id); public void insertStudent(Student student); public void updateStudent(Student student); /** * 查询当前页要显示几条数据 * @param start 要从数据库第几条开始查 * @param pageSize 一页查询几条 * @return 当前页几条数据 */ List<Student> selectByPage(@Param("start") int start, @Param("pageSize") int pageSize); //查询数据库表里面有几条数据 int selectCount(); }
4.1一个参数
方法:
public User selectUserById(Integer id);
mapper.xml
<select id="selectUserById" resultType="com.baizhi.entity.User"> select user_id as userId,user_name as username,password from t_user where user_id = #{a} </select>
一个参数时,#{}中内容可以任意,实战时#{}中保持和参数名相同。
4.2多个参数
方法:
public User selectUserByNameAndPassword(@Param("username")String name,@Param("password")String password);
mapper.xml
<select id="selectUserByNameAndPassword" resultType="com.baizhi.entity.User"> select user_id as userId,user_name as username,password from t_user where user_name = #{username} and password = #{password} </select>
多个参数时,使用Param注解给参数起别名,在mapper.xml中#{}里填注解值。注意:一个参数时,也可以使用Param注解,但是一旦使用注解,#{}中必须使用注解值。
4.3对象参数
不使用Param注解时:#{}中直接使用属性名
-
方法:
public void updateUser(User u);
-
mapper.xml
<update id="updateUser"> update t_user set user_name = #{username}, password = #{password} where user_id = #{userId} </update>
使用注解时:#{}中填 注解名.属性名
-
方法
public void updateUser(@Param("user")User u);
-
mapper.xml
<update id="updateUser"> update t_user set user_name = #{user.username}, password = #{user.password} where user_id = #{user.userId} </update>
实战时:一个参数时不用注解,多个参数时使用注解。
4.4 MyBatisUtils工具类
MyBatisUtils:抽取MyBatis编程中共性的代码。
基本思路:
第1版MyBatisUtils
public class MyBatisUtils { //创建SqlSession public static SqlSession openSession() { //1 读取配置文件 InputStream in = null; try { in = Resources.getResourceAsStream("mybatis-config.xml"); }catch(Exception e) { e.printStackTrace(); throw new RuntimeException(e); } //2 创建SqlSessionFactory对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3 创建SqlSession对象 SqlSession sqlSession= factory.openSession(); return sqlSession; } //关闭sqlSession public static void close(SqlSession sqlSession) { sqlSession.close(); } }
优化的思路:
-
Resources:读取配置文件(IO读取)
建议:读取配置文件只发生一次,定义在静态代码块中
-
SqlSessionFactory:创建SqlSession对象
建议:重量级对象(占据更多的内存),应该保证其单例
-
SqlSession:封装了一个Connection
建议:保证service和dao获取到同1个sqlSession
MyBatisUtils最终版本
public class MyBatisUtils { //2 创建SqlSessionFactory对象 private static SqlSessionFactory factory; static { //1 读取配置文件 InputStream in = null; try { in = Resources.getResourceAsStream("mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(in); }catch(Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } //创建SqlSession public static SqlSession openSession() { //3 创建SqlSession对象 SqlSession sqlSession= factory.openSession(); return sqlSession; } //关闭sqlSession public static void close(SqlSession sqlSession) { sqlSession.close(); } }
利用工具类的优化书写ServiceImpl,以学生管理系统业务层为例
package com.gr.service.impl; import com.gr.dao.StudentDao; import com.gr.entity.Student; import com.gr.service.StudentService; import com.gr.util.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import java.util.ArrayList; import java.util.List; public class StudentServiceImpl implements StudentService { @Override public Student selectStudentById(Integer id) { SqlSession session=null; Student student=null; try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 student=studentDao.selectStudentById(id); session.commit(); }finally { MyBatisUtils.close(session); } return student; } @Override public List<Student> selectAllStudent() { SqlSession session=null; List<Student> list=new ArrayList<>(); try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 list=studentDao.selectAllStudent(); session.commit(); }finally { MyBatisUtils.close(session); } return list; } @Override public void deleteStudentById(Integer id) { SqlSession session=null; try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 studentDao.deleteStudentById(id); session.commit(); }finally { MyBatisUtils.close(session); } } @Override public void insertStudent(Student student) { SqlSession session=null; try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 studentDao.insertStudent(student); session.commit(); }finally { MyBatisUtils.close(session); } } @Override public void updateStudent(Student student) { SqlSession session=null; try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 studentDao.updateStudent(student); session.commit(); }finally { MyBatisUtils.close(session); } } @Override public List<Student> selectByPage(int start, int pageSize) { SqlSession session=null; List<Student> studentList=null; try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 studentList=studentDao.selectByPage(start,pageSize); session.commit(); }finally { MyBatisUtils.close(session); } return studentList; } @Override public int selectCount() { SqlSession session=null; int n=0; try { session= MyBatisUtils.openSession();//1.获取sqlSession对象 StudentDao studentDao=session.getMapper(StudentDao.class);// 2.获取dao对象 n=studentDao.selectCount(); session.commit(); }finally { MyBatisUtils.close(session); } return n; } }
5.书写jsp页面
5.1登录:
表单form action="${pageContext.request.contextPath}/login" method="post"
提交表单(button或input-submit)至LoginController(@WebServlet("/login"))
<div class="bottom" style="text-align: center;"> <!-- 这个button也可以提交表单,不需要改成submit --> <button style="text-align: center;">Login</button> </div> 或 <input type="submit" value="登录">
LoginController
package com.gr.controller; import com.gr.entity.User; import com.gr.service.UserService; import com.gr.service.impl.UserServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** *LoginController登录成功的User可以重定向至查询所有controller,登录失败重定向至登录界面 */ @WebServlet("/login") public class LoginController extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { UserService userService=new UserServiceImpl(); //1.收参 String username= req.getParameter("username"); String password= req.getParameter("password"); //2.处理业务 User user =userService.loginByNameAndPassword(username,password); System.out.println(user); if (user!=null){ resp.sendRedirect(req.getContextPath()+"/selectAllStudent"); }else { resp.sendRedirect(req.getContextPath()+"/index.jsp"); } } }
登录写完后,一般建议设置两个filter
1.CharSetFilter
package com.gr.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/user/*") public class CharSetFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //设置编码 servletRequest.setCharacterEncoding("utf-8"); servletResponse.setContentType("text/html;charset=utf-8");//直接设置响应头编码 servletResponse.setCharacterEncoding("utf-8"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
注意:编解码集设置的filter可以把拦截范围设置为/*
2.CheckStudentLoginFilter
package com.gr.filter; import com.gr.entity.Student; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; @WebFilter(urlPatterns = "/user/*")//拦截user下的 public class CheckStudentLoginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { /**获取session对象 * servletRequest是HttpServletRequset的父类,servletRequest没有getSession方法 解决办法:向下强转 * 为什么没有new();???? */ HttpServletRequest request=(HttpServletRequest) servletRequest;//获取请求对象 HttpSession session =request.getSession(); HttpServletResponse response=(HttpServletResponse) servletResponse;//获取响应对象 //从session作用域中获取对应登录成功的对象 Student student=(Student) session.getAttribute("student"); if (student!=null){//如果学生对象不为空说明登录成功,放行 filterChain.doFilter(request,servletResponse); }else { response.sendRedirect(request.getContextPath()+"login.jsp"); } } @Override public void destroy() { } }
5.2查询所有:
①书写SelectAllXxxController
/** *查询所有学生 * Controller类型的Servlet * 依赖于service层 * 作用:调用service层中查询所有学生的方法,返回一个List集合,将集合放入request作用域中,在jsp中取出集合打印至页面 */ @WebServlet("/user/findAllStudent") package com.gr.controller; import com.gr.entity.Student; import com.gr.service.StudentService; import com.gr.service.impl.StudentServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; //@WebServlet("/selectAllStudent") public class SelectAllStudentController extends HttpServlet { StudentService studentService=new StudentServiceImpl(); @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<Student> studentList= studentService.selectAllStudent(); req.setAttribute("studentList",studentList); req.getRequestDispatcher("/student_list.jsp").forward(req,resp); } }
查询成功将集合放入request作用域并跳转至查询所有jsp将request作用域中的集合
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>学生信息表</title> </head> <body> <form action="${pageContext.request.contextPath}/multiDelete"> <table border="1px" align="center"> <caption >学生信息表</caption> <center><a href="${pageContext.request.contextPath}/addstudent.jsp" class="btn btn-primary radius">添加学生信息</a></center> <thead> <tr > <th width="25"><input type="submit" class="btn btn-primary radius" value="批量删除"/></th> <th>学生ID</th> <th>学生姓名</th> <th>学生性别</th> <th>学生电话</th> <th>学生年龄</th> <th>相关操作</th> </tr> </thead> <tbody> <c:forEach items="${requestScope.studentList}" var="student"> <tr class="text-c"> <td><input type="checkbox" value="${student.id}" name="ids"></td> <td>${student.id}</td> <td>${student.name}</td> <td>${student.sex}</td> <td>${student.tel}</td> <td>${student.age}</td> <td class="td-manage"> <a style="text-decoration:none" href="${pageContext.request.contextPath}/delStudent?id=${student.id}">删除</a> <a style="text-decoration:none" href="${pageContext.request.contextPath}/selectStudentById?id=${student.id}">修改</a> </td> </tr> </c:forEach> </tbody> </table> <center> 当前是第${curPage}页,共 ${totalPage}页 <c:if test="${curPage>1}"> <a href="${pageContext.request.contextPath}/selectAllStudent?curPage=${curPage-1}">上一页</a> </c:if> <c:if test="${curPage<totalPage}"> <a href="${pageContext.request.contextPath}/selectAllStudent?curPage=${curPage+1}">下一页</a> </c:if> </center> </form> </body> </html>
注意:查询所有的jsp中可以定义对页面显示的数据的增删改+批量删除
批量删除思路:
1.首先先将写好的展示所有表格用form表单包裹住,遍历展示所有数据过程中增加一个复选框用来将选中数据提交到后台
<form action="${pageContext.request.contextPath}/user/batchDelStudent" method="post"> <table> <thead><tr> <th><input type="submit" value="批量删除"></th>批量删除按钮提交 <td>${stu.id}</td> <td>${stu.name}</td>...在表头第一行书写批量删除按钮
书写批量删除controller,重定向至分页查询所有controller让用户知道是否操作成功
package com.gr.controller; import com.gr.service.StudentService; import com.gr.service.impl.StudentServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/multiDelete") public class MultiDeleteStudentController extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接收从student_list.jsp form表单提交过来的CheckBox选中的ids数据 String[] ids=req.getParameterValues("ids"); StudentService studentService=new StudentServiceImpl(); /**循环集合调用业务类删除方法 * 区别于studentmanage不需要在dao层使用sql枚举in书写批量删除dao方法 */ for (int i=0;i<ids.length;i++){ int id=Integer.parseInt(ids[i]); studentService.deleteStudentById(id); } //重定向到查询所有controller resp.sendRedirect(req.getContextPath()+"/selectAllStudent"); } }
2.在遍历过程中添加复选框,等于每条数据前都有一列复选框,用来选中用户想批量删除的对象
<%--复选框选中,相当于选中当前id,且复选框value就是当前id,然后点击批量删除按钮,将选中的数据提交到后台。只能批量删除不能批量修改--%> <td><input type="checkbox" value="${stu.id}" name="ids"></td>
3.增加
增删改查首先要对底层方法书写测试完备,才能保证后期调错效率,因为底层没写完毕异常了很多次了,所以要格外注意编程习惯
需要SelectXxxByPage(用户点击添加超链接)→addxxx.jsp→AddXxxController(req.getParameter接收到用户输入的添加数据,需要类型转换的注意转换,对应数据封装成对象调用业务层方法添加该对象进入mysql数据库,重定向至查询所有controller→查询所有jsp,让用户得知是否添加成功)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> <title>添加新学生</title> <link rel="stylesheet" type="text/css" href="css/adduser.css"/> </head> <body> <div class="bg"> <div class="logo lfet"></div> <div class="font lfet"> 添加新学生>>> </div> <div class="wizard right"> <form action="${pageContext.request.contextPath}/insertStudent"> <div class="content"> <div class="col"> <div class="form-group"> <%--不需要将自增id传给对象,id直接传null <input type="hidden" name="id" value="${requestScope.phone.id}">--%> <%-- <input type="hidden" name="id" value="${requestScope.student.id}">--%> <label class="lfet">学生姓名:</label> <input name="name" type="text" class="form-control error inp-bg1 left" value="${student.name}" style="outline:none;"> </div> <div class="form-group"> <label style="text-align: left;">性别:</label> <input name="sex" type="text" style="outline:none;" class="form-control error inp-bg1 left" value="${student.sex}" style="outline:none;"> </div> <div class="form-group"> <label class="lfet">手机号:</label> <input type="text" name="tel" class="form-control error dh" style="outline:none;"> </div> <div class="form-group"> <label class="lfet">年龄:</label> <input type="text" name="age" class="form-control error dh" style="outline:none;"> </div> <div class="bottom" style="text-align: center;"> <!-- 这个button也可以提交表单,不需要改成submit --> <button style="text-align: center;">提 交</button> </div> </div> </div> </form> </div> </div> </body> </html>
4.删改思路与其相同(使用td包裹住操作的超链接)
4.1删除
在查询所有的jsp的c:foreach遍历标签中添加超链接,实现每条数据后面都有删除超链接
用?id=${xxx.id}向删除controller发送要删除的数据id
<a style="text-decoration:none" href="${pageContext.request.contextPath}/delStudent?id=${student.id}">删除</a>
package com.gr.controller; import com.gr.service.StudentService; import com.gr.service.impl.StudentServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/delStudent") public class DeleteStudentById extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接收student_list传过来的数据 String idStr=req.getParameter("id"); int id=Integer.parseInt(idStr); StudentService studentService=new StudentServiceImpl(); studentService.deleteStudentById(id); /** * 删除成功,跳转到查询所有学生的servlet,然后由该servlet返回学生表验证是否查询成功 */ resp.sendRedirect(req.getContextPath()+"/selectAllStudent"); } }
4.2修改
同上在循环中添加超链接
<a style="text-decoration:none" href="${pageContext.request.contextPath}/selectStudentById?id=${student.id}">修改</a>
修改controller
package com.gr.controller; import com.gr.entity.Student; import com.gr.service.StudentService; import com.gr.service.impl.StudentServiceImpl; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/updateStudent") public class UpdateStudentController extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /**1.接收从updatestudent.jsp来的参数 * 2.将其封装为学生对象 * 3.调用业务层方法将学生对象放入实现页面修改学生信息功能 * 4.修改完成重定向到查询所有controller*/ String idStr=req.getParameter("id"); int id=Integer.parseInt(idStr); String name=req.getParameter("name"); String sex=req.getParameter("sex"); String tel=req.getParameter("tel"); String ageStr=req.getParameter("age"); int age=Integer.parseInt(ageStr); Student student=new Student(id,name,sex,tel,age); StudentService studentService=new StudentServiceImpl(); studentService.updateStudent(student); resp.sendRedirect(req.getContextPath()+"/selectAllStudent"); } }
5.运行时常见问题及解决方法见MyBatis异常文档
异常文档MyBatis框架.docx
1.mybatis-config.xml 飘红UserDaoTest中获取不到SqlSession对象
原因:没有引入MyBatis依赖和slf4j依赖
MyBatis开发步骤
终于有大神把 MyBatis 企业项目实用操作讲得明明白白了
MyBatis之SqlSessionFactory和SqlSession
框架:myBatis之SqlSessionFactory和SqlSession_自强不息,厚德载物。-CSDN博客
2. 测试类点击运行后,报sql异常
原因:xml文件中不能使用sql注释方式
3.小蓝点的设置
3. 运行时找不到mapping
原因:未在mybatis-config.xml中配置mapper路径
4. 查询单个后查询不到结果
5. 修改完分页点击登录报500 jsp语句异常
contextPath写成contextPage
6. 修改jsp数据填写完毕点击提交按钮405
出现HTTP Status 405 - HTTP method GET is not supported by this URL 原因是:
①**继承自Httpservlet的Servlet没有重写对于请求和响应的处理方法:doGet或doPost等方法,默认调用父类的doGet或doPost等方法**。
②父类HttpServlet的doGet或doPost等方法覆盖了你写的到doGet或doPost等方法。
7. 点击完添加学生 报数学运算异常