前言
-
时间:2021.8.3
-
内容:ssm之小众网
-
备注:
- 还是ssm的知识,相对于前面的内容来说,升级的部分在于,调用了mybatis-plus里的苞米豆baomidou,可以不用再手动写sql啦~
- 自己比较熟练的部分就简单带过了一下,大部分还是详细记录了的。pom.xml导包、web.xml写过滤器和核心servlet、写domian dao service controller、加上页面、配置tomcat跑页面,这些每次新开模块都要搞一回(上回的总结相对来说也比较详细了),所以这次贴代码什么也主要是贴了变动的一些部分噢~
1 后端
1 pom.xml
-
新建一个module。
-
pom.xml里写war,刷新maven,给这个module导入一个web。
-
新建web.xml,通过配置路径可以自动生成,上面的路径在项目名后面加\src\main\webapp\,下面的路径默认是对的。
-
往pom.xml里填充项目需要的包,和之前的文件相比,需要补充一个如下苞米豆。
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.3.1</version> </dependency>
-
注意pom.xml最后需要加个版本配置(之前500报错信息没记录,不写的话后面运行可能会突然给个难以预料的错误。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
2 web.xml
-
目前学习到关于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"> <!--过滤器:中文乱码--> <filter> <filter-name>charFilter</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>charFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--过滤器:解决delete put不能及时提交数据的问题--> <filter> <filter-name>formContentFilter</filter-name> <filter-class>org.springframework.web.filter.FormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>formContentFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--核心servlet--> <servlet> <servlet-name>ssm</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ssm</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
这几天练习过程中出现了很多次因为视图view里的ssm和controller的某个路径不匹配报500之类的问题,虽然说起来ssm确实是出现在这儿的,但问题一般不是在这儿,而是有可能:控制器里没写@ResponseBody以至于想返回数据却返回了路径,或者某个dao文件没有对应的同名dao.xml。
- 需要去检查一下java包下的xxDao.java有没有对应resources包下的xxDao.xml文件;
- 如果有对应的,再检查下xxDao.xml有没有写上对应的mapper地址;
- 如果xxDao.xml里的地址也是对应上的,再去检查一下applicationContext.xml,这里面大致会有三处要改的(没记错的话,实在不确定可以直接ctrl+f搜索下com来定位。
-
既然提到dao的东西了,就直接记这里吧:一个是java文件,在使用苞米豆方法时候,直接写个接口继承于BaseMapperM < T > 就好;一个是xml文件;注意两个对应的dao文件必须同名!
2 java包
- 把最开始学的domain dao service 和controller归为一类了。
domain
-
先是对应于数据库写好domain的数据,这里有几个新加的知识点,贴了一部分图讲解吧~
-
@TableName:加在实体类上的注解,具体用处我布吉岛…(手动划线
-
@TableId(type = IdType.AUTO):实现id的自增,应该要和数据库对应的吧,反正数据库自增了这里不自增会出问题(疯狂dubug的经验所得
-
@TableField(“categoryId”):引号里写数据库对应的列名,为了解决数据库和后端代码的列名属性不一致的问题而出现的注解,但实际上没啥软用,后面苞米豆里的增删改查自动sql照样用了后端代码的命名去查,能查个卵…(摊手
@TableName public class Category { @TableId(type = IdType.AUTO) @TableField("categoryId") private long categoryId; @TableField("categoryName") private String categoryName; ... }
-
dao
-
然后是dao,直接写个接口再继承BaseMapper就行。
-
注意这里的T一定要加哦,不然后面的serviceImpl有够好受的…new QueryWrapper<>()永远都是红浪浪,告诉你创建失败什么的,然而alt或者ctrl又能够正常点进源码,奇妙操作…这里再提一下Book是有个外链包的,在写这个T时候注意不要导包导成了java.awt.print.Book,自动挡操作最怕的就是这种基础导包导错了的…
-
贴一下代码,前面提过了两部分,一个java一个xml
package com.pro.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.pro.domain.Book; public interface BookDao extends BaseMapper<Book> { }
<?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.pro.dao.BookDao"> </mapper>
-
service
-
接着是service,业务这部分是无论用什么框架工具都免不了的一块。
-
写完service可以直接加个测试试一下结果,再去跑tomcat,免去controller混合带来的搞不清哪部分问题的问题。
-
分为接口和实现类,倒也没特别讲究,和以前写业务也差不多,就多了注解,这里直接以分页为例贴代码咯~
package com.pro.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.pro.domain.Book; public interface BookService { /** * 分页 * @param page 页码 * @param rows 页显示行数 * @return */ public IPage<Book> pageing(Integer page,Integer rows); }
package com.pro.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.pro.dao.BookDao; import com.pro.domain.Book; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true) public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao; /** * 分页对象 * @param page 页码 * @param rows 页显示行数 * @return */ public IPage<Book> pageing(Integer page, Integer rows) { Page<Book> p = new Page<>(page,rows); Page<Book> bookPage = bookDao.selectPage(p, new QueryWrapper<>()); return bookPage; } }
-
controller
(这里再去记一下jsp的四种提交方式!!!!!!!!!以及控制器和页面交互的几种方法!!!!!!!!!)
-
最后是controller,映射页面时候才用到,用来传数据或者页面地址。
-
这里先提是为了思维构建的方便性,毕竟初学时候这几个东西是一起学的。
-
控制层和业务层很容易混淆起来(我一开始不混,后来混了。但是单看实现的事情来看,还是有区别的,甚至可以说,业务层是服务于控制层的,因为在业务层需要注入控制层的元素。关于注入那部分知识我有些淡忘了,目前的理解就像套娃一样一层套一层,关系在前面的总结也提到了domain<dao<service<controller…
-
控制层主要是用来传数据或者地址的
- 每一个注入前面都需要加@Autowired
- 使用@GetMapping(“…”)还是@PostMapping(“…”)主要取决于前端数据提交过来的时候用的get还是post
- 加入@ResponseBody返回的是数据,好像有蛮多方法来着,这里就记录了返回视图的那种,也可以直接返回数组字符串好来着(忘了懒得查系列…);不加则返回个地址,注意此时的方法名需要和括号内是一致的,访问时候直接在项目名后加上这个地址。
-
贴代码,以分页为例,和service一样注意注解部分就好咯~
package com.pro.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.pro.domain.Book; import com.pro.domain.Category; import com.pro.service.BookService; import com.pro.service.CategoryService; import com.pro.service.CategoryServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.ArrayList; import java.util.List; /** * @author Yuhua * @since 21.7.30 16:28 */ @Controller public class BookController { @Autowired private CategoryService categoryService; @Autowired private BookService bookService; @GetMapping("/") public ModelAndView index() { ModelAndView mav = new ModelAndView("/index"); List<Category> categoryList = categoryService.selectAll(); mav.addObject("categoryList", categoryList); return mav; } @GetMapping("/books") @ResponseBody public IPage<Book> selectBooks(Integer page){ if (page == null) { page = 1; } IPage<Book> pageObject = bookService.pageing(page, 2); return pageObject; } }
-
3 其他配置文件
- 这些就日复一日复习吧,几乎不会变动的…tomcat也不再提啦,都是一样的操作~
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--加载属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--1 扫描包-->
<context:component-scan base-package="com.pro"/>
<!--2 springmvc对注解的支持-->
<mvc:annotation-driven/>
<!--3 静态资源排序 除了使用tomcat自动的default的 servlet处理-->
<mvc:default-servlet-handler/>
<!--freemarker配置-->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl"/>
<property name="freemarkerSettings">
<props><!--数据和模板渲染时的编码设置-->
<prop key="defaultEncoding">UTF-8</prop>
</props>
</property>
<!--使用classpath下的文件优先-->
<property name="preferFileSystemAccess" value="false"/>
</bean>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<!--设置freemarker 响应时的编码-->
<property name="contentType" value="text/html;charset=utf-8"/>
<property name="suffix" value=".ftl"/>
</bean>
<!--mybatis交给spring来管理,所以他的这些个配置要写在这里了-->
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
</bean>
<!--<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--这个是映射文件所在地 xml-->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="typeAliasesPackage" value="=com.pro.domain"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指向的我们在哪个包里面,写的dao接口,因为没有实现类,实现类就是被xml文件替代了
我们要将这个包下面的接口,生成代理类-->
<property name="basePackage" value="com.pro.dao"/>
</bean>
<!--加上事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启注解事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
jdbc.properties
# mysql访问数据库的驱动,地址,用户及密码
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/xzw
jdbc.username=root
jdbc.password=1234
jdbc.initialSize=5
jdbc.maxActive=30
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>
<settings>
<!--驼峰命名-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin>
</plugins>
</configuration>
2 前端
- 之前的前端有点懒了直接贴代码,主要练习了用jQuery去进行前端页面和后端数据的交互。
- 项目下直属的src里有两个文件夹,main和test,其中mian里一般有三个文件夹:一个java一个resources一个webapp
- java:com.pro…domain、dao、service、controller
- resources:
- mapper…xxDao.xml、yyDao.xml、zzDao.xml
- applicationContext.xml + jdbc.properties + mybatis-config.xml
- webapp:
- resources…images、js、css
- WEB-INF/ftl/…ftl
- WEB-INF/web.xml
- 其中ftl的名字需要和controller里的viewName保持一致(如果是返回ModelAndView的话)
- 实话说,好像确实没啥好记录的,直接贴代码最清晰了…
1 定义一个js模板,用id去定位使用
<script type="text/html" id="bookTemplate">
<!-- 一个图书 begin -->
<a href="/book/{{bookId}}" style="color: inherit">
<div class="row mt-2 book">
<div class="col-4 mb-2 pr-2">
<img class="img-fluid" src="./resources/images/{{cover}}">
</div>
<div class="col-8 mb-2 pl-0">
<h5 class="text-truncate">{{bookName}}</h5>
<div class="mb-2 bg-light small p-2 w-100 text-truncate">{{author}}</div>
<div class="mb-2 w-100">{{subTitle}}</div>
<p>
<#-- 第1个span是5个星 -->
<span class="stars" data-score="{{evaluationScore}}" title="gorgeous">
<#--<img alt="1" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="2" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="3" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="4" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="5" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<input name="score" type="hidden" value="{{evaluationScore}}" readonly="">-->
</span>
<#-- 第2个span是评分 -->
<span class="mt-2 ml-2">{{evaluationScore}}</span>
<#-- 第3个span是多少人评论 -->
<span class="mt-2 ml-2">{{evaluationQuantity}}人已评</span>
</p>
</div>
</div>
</a>
</script>
2 ajax请求后端图书数据,调用星星插件
- 这里需要通过星星插件实现,根据评分自动显示星星数目,并且仅可读的效果。
- 星星数目会根据小数点后面四舍五入,但.5的可以显示半颗星酱紫,具体原理布吉岛…
- 新设置可读时候可能是没有效果的,需要clean之后重新启动一下服务器噢。
<script type="text/javascript">
//初始化星形图片目录
$.fn.raty.defaults.path="./resources/raty/lib/images"
$(function () {
$.ajax({
url:"books",
data:{"page":1},
type:'get',
dataType:'json',
success:function (data) {
//console.log(data)
//拿到集合
var bookList = data.records;
for (var i = 0; i < bookList.length; i++) {
var book = bookList[i];
/*var html = '<li>'+ book.bookName +'</li>';
//将得到的图书,追加到图书列表的后面
$('#bookList').append(html);*/
//使用模板,将取出的book对象送入模板中赋值
var html = template('bookTemplate', book);
$('#bookList').append(html);
}
//$(".stars").raty();
$(".stars").raty({readOnly:true});
}
})
})
</script>
3 点击加载更多,页面刷新出下一页的内容
-
jQuery得到页面的nextPage,送给控制器里books路径下的selectBooks方法作为page参数,返回出新页面的数据给前端。
-
即success后,遍历新拿到的数组添加至页面结尾,达到刷新显示下一页的数据效果。
-
而nextPage也会随着点击刷新下一页而逐个增加,通过判断,达到增加至末尾页时显示触底的效果:如果页面没有到底,就显示下拉刷新按钮、隐藏触底提示,反之同理。
$(function () {
//让按钮有效
$('#btnMore').click(function () {
//alert("ok")
var nextPage = $('#nextPage').val();
$.ajax({
url:"books",
data:{"page":nextPage},
type:'get',
dataType:'json',
success:function (data) {
//console.log(data)
//拿到集合
var bookList = data.records;
for (var i = 0; i < bookList.length; i++) {
var book = bookList[i];
/*var html = '<li>'+ book.bookName +'</li>';
//将得到的图书,追加到图书列表的后面
$('#bookList').append(html);*/
//使用模板,将取出的book对象送入模板中赋值
var html = template('bookTemplate', book);
$('#bookList').append(html);
}
//$(".stars").raty();
$(".stars").raty({readOnly:true});
if(data.current<data.pages){
//将隐藏域中的值+1
$('#nextPage').val(parseInt(data.current)+1);
$('#btnMore').show();
$('#divNoMore').hide();
} else {
$('#btnMore').hide();
$('#divNoMore').show();
}
}
})
});
});
<div class="d-none">
<#-- 下一页的页码 -->
<input type="hidden" id="nextPage" value="2">
<#-- 按类别分类的id -->
<input type="hidden" id="categoryId" value="-1">
<#-- 排序的默认设置 -->
<input type="hidden" id="order" value="quantity">
</div>