需要实现的整体功能:
- 登录
- 反馈信息列表展示
- 查询反馈信息
- 发表反馈
1.数据库设计
创建数据库 |
创建表结构及其约束 |
添加测试数据 |
工具:PHP、Navicat
create table tab_user(
id int primary key auto_increment,
uname varchar(30) not null,
pwd varchar(255) not null
);
insert into tab_user(uname,pwd)values('张散','123456');
insert into tab_user(uname,pwd)values('李思','123456');
insert into tab_user(uname,pwd)values('王武','123456');
select * from tab_user;
create table tab_feedback(
id int primary key auto_increment,
commit_time datetime,
title varchar(100) not null,
content varchar(255) not null,
open int,
author int references tab_user(id)
);
insert into tab_feedback(author,commit_time,title,content,open)values(1,'2021-05-24 15:21:48','反馈测试','我是反馈测试的内容',0);
insert into tab_feedback(author,commit_time,title,content,open)values(1,'2021-05-24 15:04:30','饭菜不好','食堂饭菜不好吃,建议引入高级厨师',1);
insert into tab_feedback(author,commit_time,title,content,open)values(2,'2021-05-24 15:02:43','噪音污染','学校旁工地晚上施工,影响休息',1);
insert into tab_feedback(author,commit_time,title,content,open)values(3,'2021-05-24 15:04:09','学校超市东西价格昂贵','学校超市一家独大,商品价格设置不合理',0);
select * from tab_feedback;
delete from tab_feedback where id=3;
update tab_feedback set commit_time='2023-05-5 20:02:43',title='标题',content='内容',open='' where id =1;
select * from tab_feedback inner join tab_user on tab_feedback.author=tab_user.id
2.框架搭建
根据所用技术搭建项目框架;创建web项目导入jar包和js文件并部署到TomCat中
ssm框架配置;工具:IDEA
1.springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--1.让springMVC框架只管理com.chen.controller-->
<context:component-scan base-package="com.zhan.controller"/>
<!--2.配置视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--3.静态资源不拦截-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/fonts/**" location="/fonts/"/>
<mvc:resources mapping="/img/**" location="/img/"/>
<!--4.开启注解驱动:默认会加载试图映射器和视图适配器-->
<mvc:annotation-driven/>
</beans>
2.spring.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1.让spring框架管理com.chen包中所有的对象,但是排除使用了Controller注解的类-->
<context:component-scan base-package="com.zhan">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--2.让spring框架的jdbc管理数据库的连接-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--3.配置SqlSessionFactoryBean,把SqlSessionFactory对象交给IOC管理,他会自动创建
sqlSession对象,会根据mapper接口再创建代理对象-->
<bean id="factoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.zhan.bean"/>
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!--4.配置扫描器,扫描mapper文件,让mybatis知道要创建什么接口的实现类-->
<bean id="scannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zhan.dao"/>
</bean>
</beans>
3.mybatis.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>
<!-- <settings>-->
<!-- <setting name="logImpl" value="log4j"/>-->
<!-- </settings>-->
</configuration>
4.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置监听器,检测servlet容器创建的时候加载 spring.xml-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<!--2.配置核心控制器DispatcherServlet,创建的时候加载 springmvc.xml-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--3.配置字符集过滤器,设置中文编码-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
配置完成后测试是否能够运行成功,页面是否跳转;
注意:按照规范:字段名、实体类属性、变量首字母要小写,类名要大写;
bean层:实体类User和Feedback
1.登录的业务逻辑
1.首先在前端设计一个表单,提交表单时根据name属性在后端的控制器中自动参数绑定:
2.后端根据获取到的用户名和密码执行数据库查询,判断用户是否可以登录:
3.登录后一定要把当前用户信息存入session中;
dao层:接口UserDao
@Repository
public interface UserDao {
@Select("select * from tab_user where uname=#{uname}")
User selectByName(String uname);
}
service层:接口UserService
public interface UserService {
User selectByName(String uname);
}
实现类UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
@Override
public User selectByName(String uname) {
return userDao.selectByName(uname);
}
}
Controller层:UserController
@Controller
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/login")
public ModelAndView login(String uname, String pwd, HttpSession session){
ModelAndView mv = new ModelAndView();
// System.out.println(uname);
// System.out.println(pwd);
User user = userService.selectByName(uname);
// System.out.println(user);
if(user!=null){
if(user.getPwd().equals(pwd)){
session.setAttribute("user",user);
mv.setViewName("redirect:/findAll");
}else {
mv.addObject("error","密码错误!");
mv.setViewName("error");
}
}else{
mv.addObject("error","用户名不存在!");
mv.setViewName("error");
}
return mv;
}
}
登录页:login.jsp
οnsubmit=return check() 是一个HTML表单中的属性,表示在提交表单时调用一个名为check()的JavaScript函数来验证表单的输入是否合法。如果check()函数返回true,则表单提交成功,否则表单提交失败。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页</title>
<script src="js/jquery.min.js"></script>
<script>
function check(){
var uname = $("#uname").val();
var pwd = $("#pwd").val();
if(uname==null || uname==''){
alert("用户名不能为空!")
return false;
}
if(pwd==null || uname==''){
alert("密码不能为空!")
return false;
}
return true;
}
</script>
</head>
<body>
<h2>欢迎登录!</h2>
<form action="login" method="post" onsubmit="return check()">
用户名:<input type="text" id="uname" name="uname" value=""/><br>
密码:<input type="password" id="pwd" name="pwd" value=""/><br>
<input type="submit" id="btn" value="登录"/>
</form>
</body>
</html>
错误页:error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>错误页</title>
</head>
<body>
${error}
</body>
</html>
2.数据列表查询的业务逻辑
1.获取当前session中的用户对象;
2.根据用户的id执行数据表的关联查询:(mybatis中需要配置一对一的自动关联映射关系)
3.把查询的数据列表发送给主页,做数据展示;
dao层:接口FeedBackDao
@Repository
public interface FeedBackDao {
List<Feedback> selectByAuthor(int author);
}
mapper映射:FeedBackDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhan.dao.FeedBackDao">
<!--定义自定义映射关系-->
<resultMap id="fbMap" type="com.zhan.bean.Feedback">
<id property="id" column="id"/>
<result property="commit_time" column="commit_time"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<result property="open" column="open"/>
<!--配置一对一映射:自动关联查询 使用外键author 执行该用户信息的查询,把查到的用户对象赋值给 实体类属性user-->
<association property="user" column="author" select="com.zhan.dao.UserDao.selectById"></association>
</resultMap>
<select id="selectByAuthor" parameterType="int" resultMap="fbMap">
select * from tab_feedback where author=#{author};
</select>
</mapper>
service层:接口FeedBackService
public interface FeedBackService {
List<Feedback> selectByAuthor(int author);
}
实现类FeedBackServiceImpl
@Service
public class FeedBackServiceImpl implements FeedBackService {
@Autowired
FeedBackDao feedBackDao;
@Override
public List<Feedback> selectByAuthor(int author) {
return feedBackDao.selectByAuthor(author);
}
}
Controller层:FeedBackController
@Controller
public class FeedBackController {
@Autowired
FeedBackService feedBackService;
@RequestMapping("/findAll")
public ModelAndView findAll(HttpSession session){
ModelAndView mv = new ModelAndView();
//查询当前登录用户发布的问题反馈
User user = (User) session.getAttribute("user");
System.out.println(user);
//根据用户的id 查询 问题反馈表
List<Feedback> feedbackList = feedBackService.selectByAuthor(user.getId());
System.out.println(feedbackList);
mv.addObject("feedbackList",feedbackList);
mv.setViewName("zhuye");
return mv;
}
}
主页:zhuye.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!--fmt标签可以对日期进行转换和解析-->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<table>
<thead>
<tr>
<th>编号</th>
<th>反馈人</th>
<th>反馈时间</th>
<th>反馈标题</th>
<th>反馈内容</th>
<th>公开状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${feedbackList}" var="feedback">
<td>${feedback.id}</td>
<td>${feedback.user.uname}</td>
<td><fmt:formatDate value="${feedback.commit_time}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate></td>
<td>${feedback.title}</td>
<td>${feedback.content}</td>
<td>
<c:if test="${feedback.open==0}">不公开</c:if>
<c:if test="${feedback.open==1}">公开</c:if>
</td>
<td>待定</td>
</tr>
</c:forEach>
<tr>
</tbody>
</table>
</body>
</html>
3.模糊查询
dao层:接口FeedBackDao
@Repository
public interface FeedBackDao {
List<Feedback> seach(Feedback feedback);
}
mapper映射:FeedBackDao.xml
<select id="seach" parameterType="com.zhan.bean.Feedback" resultMap="fbMap">
select * from tab_feedback where author=#{user.id} and title like concat('%',#{title},'%') and open=#{open};
</select>
service层:接口FeedBackService
public interface FeedBackService {
List<Feedback> seach(Feedback feedback);
}
实现类FeedBackServiceImpl
@Service
public class FeedBackServiceImpl implements FeedBackService {
@Autowired
FeedBackDao feedBackDao;
@Override
public List<Feedback> seach(Feedback feedback) {
return feedBackDao.seach(feedback);
}
}
Controller层:FeedBackController
@RequestMapping("/seach")
public ModelAndView seach(Feedback feedback,HttpSession session){
ModelAndView mv = new ModelAndView();
feedback.setUser((User) session.getAttribute("user"));
List<Feedback> feedbackList = feedBackService.seach(feedback);
mv.addObject("feedbackList",feedbackList);
mv.setViewName("zhuye");
return mv;
}
zhuye.jsp补充
<form action="seach" method="post">
公开状态<select name="open">
<option value="1">公开</option>
<option value="0">不公开</option>
</select>
反馈标题:<input type="text" id="title" name="title" value="">
<input type="submit" id="btn" value="查询">
</form>
4.信息的添加的业务逻辑
1.设计表单,录入数据信息,提交表单时根据name属性在后端的控制器中使用实体类自动参数绑定
2.添加时,页面录入数据和数据库字段数量不一致,此时需要后端进行数据的补充确保数据库字段所有的数据准备够;
---用户信息的补充后端是通过session获得当前登录的用户;
---时间默认是当前时间;
---某些状态在后端赋默认状态值;
--某些字段是通过计算得到的;
3.补充数据库添加所需要的全部数据库,执行数据库插入操作;
dao层:接口FeedBackDao
@Repository
public interface FeedBackDao {
int insert(Feedback feedback);
}
mapper映射:FeedBackDao.xml补充
<insert id="insert" parameterType="com.zhan.bean.Feedback">
insert into tab_feedback(commit_time,title,content,open,author)
values(#{commit_time},#{title},#{content},#{open},#{user.id});
</insert>
service层:接口FeedBackService
public interface FeedBackService {
int insert(Feedback feedback);
}
实现类FeedBackServiceImpl
@Service
public class FeedBackServiceImpl implements FeedBackService {
@Autowired
FeedBackDao feedBackDao;
@Override
public int insert(Feedback feedback) {
return feedBackDao.insert(feedback);
}
}
Controller层:FeedBackController补充
@RequestMapping("/add")
public ModelAndView add(Feedback feedback,HttpSession session){
ModelAndView mv = new ModelAndView();
System.out.println("前端提交的数据:"+feedback);
User user = (User) session.getAttribute("user");
feedback.setUser(user);
System.out.println("前端提交的数据:"+feedback);
int n = feedBackService.insert(feedback);
if(n>0){
mv.setViewName("redirect:/findAll");
}else{
mv.addObject("error","添加商品出错啦!");
mv.setViewName("error");
}
return mv;
}
zhuye.jsp补充
<h3>
<a href="add.jsp">发表反馈</a>
</h3>
5.删除的业务逻辑
1.在主页设计一个超链接,指定请求的地址并通过?传递给后端主键id;
2.在后端控制器获得id,并进行数据的删除操作;
3.判断受影响的行数大于0,则重新请求findAll,再次查询最新的数据并跳转到主页:
5.修改
业务逻辑:
1.在主页设计一个超链接,指定请求的地址并通过?传递给后端主键id:
2.后端根据id查询完整信息,然后把数据显示在数据展示页面的表单元素中:
3.用户根据需要修改字段的值,点击修改把最新数据提交给后端:
修改的时候也可能是变化的,记住一点,前端提供的值不够,后端需要补充!!!!!
-用户信息的补充后端是通过session获得当前登录的用户:
--时间默认是当前时间;
-某些状态在后端赋默认状态值;
-某些字段是通过计算得到的: I
4.后端拿到最新的数据进行数据库的更新操作;
dao层:接口FeedBackDao
@Repository
public interface FeedBackDao {
int delete(int id);
}
mapper映射:FeedBackDao.xml补充
<delete id="delete" parameterType="int">
delete from tab_feedback where id = #{id};
</delete>
service层:接口FeedBackService补充
public interface FeedBackService {
int delete(int id);
}
实现类FeedBackServiceImpl
@Service
public class FeedBackServiceImpl implements FeedBackService {
@Autowired
FeedBackDao feedBackDao;
@Override
public int delete(int id) {
return feedBackDao.delete(id);
}
}
Controller层:FeedBackController
@RequestMapping("/del")
public ModelAndView del(int id){
ModelAndView mv=new ModelAndView();
int i = feedBackService.delete(id);
if(i>0){
mv.setViewName("redirect:/findAll");
}else{
mv.addObject("error","删除商品出错啦!");
mv.setViewName("error");
}
return mv;
}
zhuye.jsp补充
<td>
<%--待定--%>
<a href="del?id=${feedback.id}">删除</a>
</td>
6.修改的业务逻辑
1.在主页设计一个超链接,指定请求的地址并通过?传递给后端主键id;
2.后端根据id查询完整信息,然后把数据显示在数据展示页面的表单元素中:
3.用户根据需要修改字段的值,点击修改把最新数据提交给后端;
修改的时候也可能是变化的,记住一点,前端提供的值不够,后端需要补充!!!!!
-用户信息的补充后端是通过session获得当前登录的用户;
-时间默认是当前时间:
--某些状态在后端赋默认状态值;
--某些字段是通过计算得到的:
4.后端拿到最新的数据进行数据库的更新操作:对
5.判断受影响的行数大于0,则重新请求findAll,再次查询最新的数据井跳转到主页;
dao层:接口FeedBackDao
@Repository
public interface FeedBackDao {
Feedback selectById(int id);
int update(Feedback feedback);
}
mapper映射:FeedBackDao.xml补充
<select id="selectById" parameterType="int" resultMap="fbMap">
select * from tab_feedback where id=#{id};
</select>
<update id="update" parameterType="com.zhan.bean.Feedback">
update tab_feedback set commit_time=#{commit_time},title=#{title},content=#
{content},open=#{open} where id=#{id};
</update>
service层:接口FeedBackService
public interface FeedBackService {
Feedback selectById(int id);
int update(Feedback feedback);
}
实现类FeedBackServiceImpl
@Service
public class FeedBackServiceImpl implements FeedBackService {
@Autowired
FeedBackDao feedBackDao;
@Override
public Feedback selectById(int id) {
return feedBackDao.selectById(id);
}
@Override
public int update(Feedback feedback) {
return feedBackDao.update(feedback);
}
}
Controller层:FeedBackController
@RequestMapping("/findById")
public ModelAndView findById(int id){
ModelAndView mv=new ModelAndView();
Feedback feedback = feedBackService.selectById(id);
mv.addObject("feedback",feedback);
mv.setViewName("show");
return mv;
}
@RequestMapping("/update")
public ModelAndView update(Feedback feedback){
ModelAndView mv=new ModelAndView();
int i = feedBackService.update(feedback);
if(i>0){
mv.setViewName("redirect:/findAll");
}else{
mv.addObject("error","修改商品出错啦!");
mv.setViewName("error");
}
return mv;
}
zhuye.jsp补充
<td>
<%--待定--%>
<a href="findById?id=${feedback.id}">修改</a>
</td>
补充修改页:show.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>修改页</title>
</head>
<body>
<h2>修改页</h2>
<form action="update" method="post">
<input type="hidden" id="id" name="id" readonly="readonly" value="${feedback.id}">
反馈人:<input type="text" id="uname" name="user.uname" readonly="readonly" value="${feedback.user.uname}"> <br>
反馈时间:<input type="date" id="commit_time" name="commit_time" value="<fmt:formatDate value="${feedback.commit_time}" pattern="yyyy-MM-dd"></fmt:formatDate>"> <br>
反馈标题:<input type="text" id="title" name="title" value="${feedback.title}"> <br>
反馈内容:<input type="text" id="content" name="content" value="${feedback.content}"> <br>
是否公开:<input type="radio" name="open" <c:if test="${feedback.open==1}">checked="checked"</c:if> value="1">公开
<input type="radio" name="open" <c:if test="${feedback.open==0}">checked="checked"</c:if> value="0">不公开 <br>
<input type="submit" id="btn" value="修改"> <br>
</form>
</body>
</html>
页面效果
补充知识
EL表达式获取对象的属性通过的是getter方法
字段转义
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${feedback.open==1}">checked="checked"</c:if>
//springmvc框架默认支持的格式是:yyyy/MM/dd 也可以通过注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
//@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
private Date commit_time;
日期转义
<!--fmt标签可以对日期进行转换和解析-->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
反馈时间:<input type="date" id="commit_time" name="commit_time" value="<fmt:formatDate value="${feedback.commit_time}" pattern="yyyy-MM-dd"></fmt:formatDate>"> <br>
<fmt:formatDate value="${feedback.commit_time}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>