架构期末项目思路和问题修改

前言

本来还很担心期末项目问题,因为我不是很会前端的编写,所以对于我来说难的不是后端,而是前端。
所以我决定等我把这个期末过了,好好的学习一下前端的相关知识。
还有就是这个期末项目的bug真的太多了,不弄点记录的后面又要搞忘

部署问题

这边建议如果不想有不必要的麻烦,我们可以直接不要老师提供的项目,我们自己新建一个maven项目
然后将包这些东西复制进去,注意pom.xml中的内容不要全部替换为老师的,自己将依赖复制进自己的pom文件中这样你可以最大限度的避免各种
的不必要的报错,还有就是配置文件的事情。
jdk版本:我这边用的19是没有任何问题的你可以不用jdk1.8的版本
maven: 最好将其配置为我之前给大家配置那个,可以最大限度的解决问题

前端界面加载问题


这个是前端jsp引擎忽略了EL表达式
如果将isELIgnored属性设置为”true”,则JSP引擎将忽略页面中的所有EL表达式。默认情况下,EL表达式是启用的,因此通常不需要显式声明这个属性
解决方法是很简单的:
在你的每个jsp页面头上加一个

1
2
3
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!-- 下面的这个 -->
<%@ page isELIgnored="false" %>

登录问题

正确的请求的路径

1
http://localhost/user/login

有可能你的请求出现404 F12 login路径

1
http://localhost/user/user/login

你需要在前端找到相应的请求 login.jsp中

1
<form id="loginform" class="sui-form" action="${pageContext.request.contextPath}/user/login"

自己检查一下是不是重复了

前端请求路径重复问题

就如上述一样,看似没有问题但是就是多了一个路径就不行
后面都是这样,当你发现请求报错的时候先看看请求路径是不是重复了
然后去找相应的请求的方法(前端的)
一般请求的方法都在my.js里面删掉第一个前缀就行

MyBatis无法找到你所调用的Mapper方法

这个问题出现在借阅书籍的地方和后续的一些方法中
这个就是在我们部署的时候出现的包不匹配的问题
你都mapper包中没有问题,但是装mapper xml文件的包有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.itheima.config;

import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;
import java.util.Properties;

public class MyBatisConfig {
/**
* 配置PageInterceptor分页插件
*/
@Bean
public PageInterceptor getPageInterceptor() {
PageInterceptor pageIntercptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("value", "true");
pageIntercptor.setProperties(properties);
return pageIntercptor;
}

/*
定义MyBatis的核心连接工厂bean,
等同于<bean class="org.mybatis.spring.SqlSessionFactoryBean">
参数使用自动装配的形式加载dataSource,
为set注入提供数据源,dataSource来源于JdbcConfig中的配置
*/
@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource, @Autowired PageInterceptor pageIntercptor) {
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
//等同于<property name="dataSource" ref="dataSource"/>
ssfb.setDataSource(dataSource);
Interceptor[] plugins = {pageIntercptor};
ssfb.setPlugins(plugins);
return ssfb;
}

/*
定义MyBatis的映射扫描,
等同于<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
*/
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
//等同于<property name="basePackage" value="com.itheima.dao"/>
msc.setBasePackage("com.itheima.mapper"); //这里设置的是映射的包名,resources/com/itheima/mapper
return msc;
}
}

msc.setBasePackage(“com.itheima.mapper”); 这映射的包名地址是resources/com/itheima/mapper
相当于你前面要加两个包com/itheima

这个需要注意

在新增员工界面输入邮件等出现乱码问题

这个地方存在两个问题

  • 有可能是数据库编码问题

    1
    2
    3
    4
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
    jdbc.username=root
    jdbc.password=123456

    在url后边追加characterEncoding=UTF-8 来将编码统一为utf-8

  • 也有可能是tomcat的问题,将tomcat的编码统一为utf-8
    这里,如果你用的是本地下载的tomcat那么需要去对应文件中,修改config文件
    当然我们一般都不这样干,我们一般是将其作为插件写在pom.xml配置文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>

加一个uriEncoding就行

重写mapper包中的sql语句

仔细看了其中的一些写法,本来是逻辑较为简单的语句写到注解中
较为复杂的写到xml映射文件中,但是这里将复杂的语句都写在了mapper中而且出现了报错看到都烦
这里我们注释掉原有的语句,将方法映射到配置文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14

// @Select({"<script>" +
// "SELECT * FROM book " +
// "where book_status !='3'" +
// "<if test=\"name != null\"> AND book_name like CONCAT('%',#{name},'%')</if>" +
// "<if test=\"press != null\"> AND book_press like CONCAT('%', #{press},'%') </if>" +
// "<if test=\"author != null\"> AND book_author like CONCAT('%', #{author},'%')</if>" +
// "order by book_borrowtime" +
// "</script>"
// })
@ResultMap("bookMap")
//分页查询图书
Page<Book> searchBooks(Book book);

BookMapper.xml中写出
注意上面提到的配置文件地址的正确映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="searchBooks" resultType="com.itheima.domain.Book">
SELECT * FROM book
WHERE book_status != '3'
<if test="name != null">
AND book_name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="press != null">
AND book_press LIKE CONCAT('%', #{press}, '%')
</if>
<if test="author != null">
AND book_author LIKE CONCAT('%', #{author}, '%')
</if>
ORDER BY book_borrowtime
</select>

剩下的都可以这样干

属性指定了映射到Java实体类

根据上述的重写mapper包中的sql语句 与原版出现了问题
就是映射问题

与Book.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.itheima.domain;
import java.io.Serializable;
public class Book implements Serializable {
private Integer id; //图书编号
private String name; //图书名称
private String isbn; //图书标准ISBN编号
private String press; //图书出版社
private String author; //图书作者
private Integer pagination;//图书页数
private Double price; //图书价格
private String uploadTime; //图书上架时间
private String status; //图书状态
private String borrower; //图书借阅人
private String borrowTime; //图书借阅时间
private String returnTime; //图书预计归还时间
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Integer getPagination() {
return pagination;
}
public void setPagination(Integer pagination) {
this.pagination = pagination;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getUploadTime() {
return uploadTime;
}
public void setUploadTime(String uploadTime) {
this.uploadTime = uploadTime;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getBorrower() {
return borrower;
}
public void setBorrower(String borrower) {
this.borrower = borrower;
}
public String getBorrowTime() {
return borrowTime;
}
public void setBorrowTime(String borrowTime) {
this.borrowTime = borrowTime;
}
public String getReturnTime() {
return returnTime;
}
public void setReturnTime(String returnTime) {
this.returnTime = returnTime;
}
}

我们对比之下可以发现,属性名字与数据库中的名字对应不上。
然后就会出现的问题就是只会查询出对应上的字段名。在本项目就会出现如下问题

发现没有,只查询出来了借阅者的名字。其他的字段都为零。如果你怀疑是sql语句的问题
那么你可以尝试只用一行语句,不加任何限制例如:

1
2
3
<select id="selectBorrowed" resultType="com.itheima.domain.Book">
SELECT * FROM book
</select>

你删除掉多余的代码后,现在就是只有一个语句,那就是查询book中的所有数据。但是执行后仍然是只有借阅者的信息
只不过多了不少的空数据到第二页。

问题解决

在原始代码中我们注意到这段写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Select("SELECT * FROM book where book_status !='3' order by book_uploadtime DESC")
@Results(id = "bookMap",value = {
//id字段默认为false,表示不是主键
//column表示数据库表字段,property表示实体类属性名。
@Result(id = true,column = "book_id",property = "id"),
@Result(column = "book_name",property = "name"),
@Result(column = "book_isbn",property = "isbn"),
@Result(column = "book_press",property = "press"),
@Result(column = "book_author",property = "author"),
@Result(column = "book_pagination",property = "pagination"),
@Result(column = "book_price",property = "price"),
@Result(column = "book_uploadtime",property = "uploadTime"),
@Result(column = "book_status",property = "status"),
@Result(column = "book_borrower",property = "borrower"),
@Result(column = "book_borrowtime",property = "borrowTime"),
@Result(column = "book_returntime",property = "returnTime")
})
Page<Book> selectNewBooks();


@Select("SELECT * FROM book where book_id=#{id}")
@ResultMap("bookMap")
//根据id查询图书信息
Book findById(String id);

// @Select({"<script>" +
// "SELECT * FROM book " +
// "where book_status !='3'" +
// "<if test=\"name != null\"> AND book_name like CONCAT('%',#{name},'%')</if>" +
// "<if test=\"press != null\"> AND book_press like CONCAT('%', #{press},'%') </if>" +
// "<if test=\"author != null\"> AND book_author like CONCAT('%', #{author},'%')</if>" +
// "order by book_borrowtime" +
// "</script>"
// })
@ResultMap("bookMap")
//分页查询图书
Page<Book> searchBooks(Book book);

我们注意到原始代码
@Results注解定义了查询结果的映射关系,将查询结果的列映射到Book实体类的属性上。其中@Result注解用于指定具体的映射
所以当我们将原始代码写到了,配置xml中。我们需要重新在xml配置中映射相关的关系
映射如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<resultMap id="bookResultMap" type="com.itheima.domain.Book">
<result property="id" column="book_id"/>
<result property="name" column="book_name"/>
<result property="isbn" column="book_isbn"/>
<result property="press" column="book_press"/>
<result property="author" column="book_author"/>
<result property="pagination" column="book_pagination"/>
<result property="price" column="book_price"/>
<result property="uploadTime" column="book_uploadtime"/>
<result property="status" column="book_status"/>
<result property="borrower" column="book_borrower"/>
<result property="borrowTime" column="book_borrowtime"/>
<result property="returnTime" column="book_returntime"/>
</resultMap>

<select id="selectBorrowed" resultType="com.itheima.domain.Book" resultMap="bookResultMap">
SELECT * FROM book
WHERE book_status IN ('1', '2')
<if test="name != null">
AND book_name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="press != null">
AND book_press LIKE CONCAT('%', #{press}, '%')
</if>
<if test="author != null">
AND book_author LIKE CONCAT('%', #{author}, '%')
</if>
ORDER BY book_borrowtime
</select>

加入resultMap=”bookResultMap” 将其映射起来就行了

借阅查询逻辑的修改

我们看原始的逻辑是,当用户点击查询的时候只是查询当前登录的用户

1
AND book_borrower = #{borrower}

限制了查询的条件,我认为这个是有问题的。当管理员需要看到所有同学的借阅信息的时候是不被允许的,所以我们需要
配置一个判定条件,如果当前条件是管理员。则查询所有的学生当前正在借阅的信息。如果不是管理员,是普通的用户则
只查询当前用户的借阅信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<select id="selectBorrowed" resultType="com.itheima.domain.Book" resultMap="bookResultMap">
SELECT * FROM book
WHERE book_status IN ('1', '2')
<choose>
<!-- 如果borrower等于'黑马程序员',则不添加借阅者条件 -->
<when test="borrower == '黑马程序员'">
<!-- 不包含借阅者条件 -->
</when>
<!-- 如果borrower不等于'黑马程序员',并且borrower不为null,则添加借阅者条件 -->
<when test="borrower != null and borrower != '黑马程序员'">
AND book_borrower = #{borrower}
</when>
</choose>
<if test="name != null">
AND book_name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="press != null">
AND book_press LIKE CONCAT('%', #{press}, '%')
</if>
<if test="author != null">
AND book_author LIKE CONCAT('%', #{author}, '%')
</if>
ORDER BY book_borrowtime
</select>

部署上云服务器出现数据无法访问问题

1
2
3
4
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
jdbc.username=root
jdbc.password=****

首先,在15版本以下是不需要com.mysql.jdbc.cj.Driver 这个的
其次是ssl拒绝了我们的访问
将useSSL=false关闭