上一篇搭建起了大体架构,这一篇写个增删改查demo,
第三篇是完善第二篇的bug:第三篇
7、测试显示table 信息 √
(建table,在sql 里面添加几条数据,显示到页面)
8、增加热部署功能 √(自动刷新后台java,xml代码变动情况,无需手动重启,
不过idea对它支持不大友好,建议idea写完框架后用 sts(eclipse对spring包的集成)继续修改
spring.thymeleaf.cache 设为false
或者使用springboot的devtools
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<version>1.3.0.RELEASEversion>
dependency>
)
9、增加 redis设置 √
(前台,写个隐藏域,获取id,如果id为空,执行添加;如果id有值,执行修改;实现两个功能用一个方法)
12、设置报错页面 √
13、美化页面,规范代码 √
————————————————————
效果:
目录结构:
工欲善其事必先利其器,配置几个不错的功能再写demo吧:
主页:Application.java ,这里有个跳转首页的注解方法,index主页大家自己写比较好
@Controller
@SpringBootApplication
@ServletComponentScan
@EnableScheduling
@EnableCaching
@MapperScan(basePackages = {"com.example.demo.other.MyMapper"})
//启注解事务管理
@EnableTransactionManagement
public class Application {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"
};
@RequestMapping(value="/index",method = RequestMethod.GET)
public String showIndex(){
return "index";
}
}
4.0.0
com.example
demo
0.0.1-SNAPSHOT
jar
demo
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
2.0.3.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
mysql
mysql-connector-java
5.1.46
org.mybatis.spring.boot
mybatis-spring-boot
1.3.2
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
org.mybatis.spring.boot
mybatis-spring-boot-autoconfigure
1.3.2
javax.persistence
persistence-api
1.0
tk.mybatis
mapper-spring-boot-starter
RELEASE
org.springframework
springloaded
1.2.7.RELEASE
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-starter-jdbc
com.google.code.gson
gson
2.7
org.springframework.boot
spring-boot-maven-plugin
当前mysql密码为空,redies还没完全配置好
#设置Tomcat端口,默认8081
server.port=8081
#设置项目ContextPath
server.servlet.context-path =/test
server.jsp-servlet.init-parameters.*= # Init parameters used to configure the JSP servlet
#设置Tomcat编码
server.tomcat.uri-encoding=UTF-8
#设置视图解析器路径
spring.mvc.view.prefix=/static/jsp/
#设置视图解析器后缀
spring.mvc.view.suffix=.jsp
#修改jsp后立即加载
server.jsp-servlet.init-parameters.development=true
#server.html-servlet.init-parameters.development=true
#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.thymeleaf.prefix=classpath:/templates/
#配置.xml文件路径
mybatis.mapper-locations=classpath*:mapper/**/*.xml
#配置模型路径
mybatis.type-aliases-package=com.example.demo.model
mapper.mappers=com.example.demo.other.MyMapper
mapper.not-empty=false
mapper.identity=MYSQL
#jpa create table
spring.jpa.database = MYSQL
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.DefaultNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
#关闭缓存,及时刷新
spring.freemarker.cache=false
#热部署生效
spring.devtools.restart.enabled=true
spring.devtools.restart.exclude=META-INF/maven/**,META-INF/resources/**,resources/**,static/**,public/**,templates/**,**/*Test.class,**/*Tests.class,git.properties # Patterns that should be excluded from triggering a full restart.
#设置重启的目录,添加那个目录的文件需要restart(监听目录)
spring.devtools.restart.additional-paths=src/main/java
# 热部署引起的乱码
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=172.31.19.222
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
## LOG4J配置
log4j.rootCategory=DEBUG,stdout
## 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
1、Setting-compiler-make project automatically 勾上,自动启动刷新;
2、ctrl + shift + alt + /,选择Registry,勾上 Compiler autoMake allow when app running
(每个人的idea版本不同,快捷键不一定,我的是 Ctrl+Shift+A )
3、重启idea,完成热部署
(其他参考:https://www.jianshu.com/p/7b659c75c0ee)
注意:idea对热部署的支持不友好,sts才能完成适应热部署!
我需要配置myBatis,myMapper,redis三个类,
application已经配置了扫描路径,这里直接给方法:
1、MybatisProperties
package com.example.demo.other;
/**
* Created by Administrator on 2018/6/15 0015.
*/
import org.apache.ibatis.session.ExecutorType;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
/**
* Configuration properties for Mybatis.
*
* @author Eddú Meléndez
*/
@ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties {
public static final String MYBATIS_PREFIX = "mybatis";
/**
* Config file path.
*/
private String config;
/**
* Location of mybatis mapper files.
*/
private Resource[] mapperLocations;
/**
* Package to scan domain objects.
*/
private String typeAliasesPackage;
/**
* Package to scan handlers.
*/
private String typeHandlersPackage;
/**
* Check the config file exists.
*/
private boolean checkConfigLocation = false;
/**
* Execution mode.
*/
private ExecutorType executorType = ExecutorType.SIMPLE;
public String getConfig() {
return this.config;
}
public void setConfig(String config) {
this.config = config;
}
public Resource[] getMapperLocations() {
return this.mapperLocations;
}
public void setMapperLocations(Resource[] mapperLocations) {
this.mapperLocations = mapperLocations;
}
public String getTypeHandlersPackage() {
return this.typeHandlersPackage;
}
public void setTypeHandlersPackage(String typeHandlersPackage) {
this.typeHandlersPackage = typeHandlersPackage;
}
public String getTypeAliasesPackage() {
return this.typeAliasesPackage;
}
public void setTypeAliasesPackage(String typeAliasesPackage) {
this.typeAliasesPackage = typeAliasesPackage;
}
public boolean isCheckConfigLocation() {
return this.checkConfigLocation;
}
public void setCheckConfigLocation(boolean checkConfigLocation) {
this.checkConfigLocation = checkConfigLocation;
}
public ExecutorType getExecutorType() {
return this.executorType;
}
public void setExecutorType(ExecutorType executorType) {
this.executorType = executorType;
}
}
2、MyMapper.java (数据库持久层dao,我需要调用它封装的sql方法)
package com.example.demo.other;
/**
* Created by Administrator on 2018/6/15 0015.
*/
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
/**
* 被继承的Mapper,一般业务Mapper继承它
*
*/
public interface MyMapper extends Mapper, MySqlMapper {
//TODO
//FIXME 特别注意,该接口不能被扫描到,否则会出错
}
3、RedisConfig
package com.example.demo.other;
/**
* Created by Administrator on 2018/6/16 0016.
*/
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.HashMap;
import java.util.Map;
/**
* Redis缓存配置类
* @author szekinwin
*
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
@Bean(name="redisTemplate")
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate<>();
RedisSerializer redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
//key序列化方式
template.setKeySerializer(redisSerializer);
//value序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
//value hashmap序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
/* @Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes")RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(3000);
return cacheManager;
}*/
}
1、mysql建表:
CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`age` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`to_day` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
2、model :实体类 Student.java
(注意,springboot里面,不大支持Integer id,
这里id 我用Long类型,使用的时候记得转换类型)
package com.example.demo.model;
import javax.persistence.*;
import java.io.Serializable;
/**
* Created by Administrator on 2018/6/15 0015.
*/
@Entity
@Table(name="student")
public class Student implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
private String toDay;
public Student(){
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getToDay() {
return toDay;
}
public void setToDay(String toDay) {
this.toDay = toDay;
}
}
3、service层,接口跟方法
StudentService接口:
package com.example.demo.service;
import com.example.demo.model.Student;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Created by Administrator on 2018/6/15 0015.
*/
@Component
public interface StudentService {
//显示table信息
public List showTable();
//添加信息
/* public Integer addStudent(Student st);*/
//删除
public Integer deleteStudent(String id);
//修改
/* public Integer editStudent(Student st);*/
//查询(模糊查询:age,name)
public List findStudent(String testInput);
//添加,修改共用一个方法
public Integer updateStudent(Student st);
}
StudentServiceImpl.java 实现接口方法
(这里用了MyMapper带有的sql方法,它不是一个jar包,需要自己手动加上去,
但是用起来非常方便!不过查询是在 StudentMapper.java 接口的方法 ,
sql语句在 resources-mapper-StudentMapper.xml
)package com.example.demo.service.impl;
import com.example.demo.mapper.StudentMapper;
import com.example.demo.model.Student;
import com.example.demo.service.StudentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* Created by Administrator on 2018/6/15 0015.
*/
@Service
public class StudentServiceImpl implements StudentService {
@Resource
StudentMapper sm;
@Override
public List showTable() {
System.out.println("----------显示table全部信息------");
return sm.selectAll();
}
//添加
/* @Override
public Integer addStudent(Student st) {
System.out.println("---------添加信息---------"+st);
return sm.insert(st);
}*/
//删除: 因为javabean里,ID是Long型的,所以需要转换
@Override
public Integer deleteStudent(String id) {
System.out.println("----------删除信息------"+id);
return sm.deleteByPrimaryKey(Long.valueOf(id));
}
//修改
/* @Override
public Integer editStudent(Student st) {
System.out.println("------修改信息-------"+st);
return sm.updateByPrimaryKey(st);
}*/
//尝试添加,修改写同一个方法
@Override
public Integer updateStudent(Student st) {
//获取id
if(st.getId() !=null){
System.out.println("----id不为空,执行修改---"+st.getId());
return sm.updateByPrimaryKey(st);
}else{
System.out.println("----id空,执行新增---"+st.getId());
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
st.setToDay(sdf.format(new Date()));
return sm.insert(st);
}
}
//模糊查询:age,name
@Override
public List findStudent(String testInput){
System.out.println("------查询输入信息----"+testInput);
return sm.selectStudentUrl("%" + testInput+ "%" , "%"+ testInput +"%");
}
}
4、mapper,数据库持久层:
StudentMapper.java
package com.example.demo.mapper;
import com.example.demo.model.Student;
import com.example.demo.other.MyMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Created by Administrator on 2018/6/15 0015.
*/
@Mapper
public interface StudentMapper extends MyMapper {
List selectStudentUrl(@Param("age") String age, @Param("name") String name);
}
5、controller层:(以上都配置好有,再写控制层,给前端页面调用)
StudentController.java
package com.example.demo.controller;
import com.example.demo.model.Student;
import com.example.demo.service.impl.StudentServiceImpl;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import org.slf4j.Logger;
/**
* Created by Administrator on 2018/6/15 0015.
*/
@Controller
public class StudentController {
private Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private StudentServiceImpl ssi;
@RequestMapping ("/hello")
public String showTest(){
return "testStudent";
}
@RequestMapping("/showTable")
@ResponseBody
public List showStudent(){
List ls=ssi.showTable();
return ls;
}
/**
* 添加学生
*/
/* @RequestMapping("/addStudent")
@ResponseBody
public Integer addStudent(Student st){
return ssi.addStudent(st);
}*/
/**
* 删除学生
*/
@RequestMapping("/deleteStudent")
@ResponseBody
public Integer deleteStudent(String id){
return ssi.deleteStudent(id);
}
/**
* 修改学生
*/
/* @RequestMapping("/editStudent")
@ResponseBody
public Integer editStudent(Student st){
return ssi.editStudent(st);
}*/
/**
* 添加/修改学生
*/
@RequestMapping("/updateStudent")
@ResponseBody
public Integer updateStudent(Student st){
return ssi.updateStudent(st);
}
/**
* 查询学生,需要studentRepository的方法
*/
@RequestMapping("/selectStudent")
@ResponseBody
public List selectTestPeople(HttpServletRequest request) {
String testInput=request.getParameter("testInput");
logger.info("selectTestPeopleUrl===="+testInput);
return ssi.findStudent(testInput);
}
}
6、resource-mapper下的xml文件:StudentMapper.xml
(
用于我mybatis用的少,有时会犯错,
提醒一下各位,
1、规范 : xml文件与mapper层的类同名
xxxMapper.xml 与 xxxMapper.java
2、规则:mapper,serviceImpl层的方法名需要和xml 的id一致:
return sm.selectStudentUrl.....
ListselectStudentUrl( ....
)
————————————————————————
五、页面布局:后台方法已经写好了,那么页面直接调用即可,页面默认第一级目录:templates
1、testStudent.html
温馨提示:springboot识别js,css 不能用绝对路径,
在页头加上:
css用这个方式:
js用这个:
这里使用了:bootstrap,bootstrap-table的css跟js,可以用cdn外链:https://cdn.baomitu.com/
layUi 的css跟js ,没有外链,直接下载丢进项目:http://www.layui.com/
多看看console是否有未识别的js,cs,是否有错误的代码;
testStudent
id
年龄
姓名
日期
操作
2、testStudent.js:用bootstrap-table.js 跟 layui.js
/**
*操作格式化
*/
function operateFormatter(value, row, index) {
return [
' ',
''
].join('');
}
/**
任务列表删除
*/
function deleteStudentBtn(th){
var id=$(th).attr("id");
layer.confirm('你确定删除信息吗?', {
btn: ['确定','取消'] //按钮
}, function(){
$.ajax({
type : "post",
url:"deleteStudent",
data:{id:id},
async:false,
success: function (data) {
layer.msg("操作成功",{icon:1});
$("#list_showStudent").bootstrapTable('remove',{
field:'id'
});
}
});
$("#list_showStudent").bootstrapTable('refresh');
$("#list_showStudent").bootstrapTable('refresh');
}, function () {
});
}
/**
添加学生:保存后获取form全部信息,以pos请求使用添加方法,隐藏弹框,刷新table
*/
$(function () {
$(".btn_saveStudent").click(function () {
var ser=$("#form_addStudent").serialize();
$.post("updateStudent",ser, function (data) {
/* $.post("addStudent",ser, function (data) { */
if(data==1){
layer.msg("操作成功",{icon:1});
$("#addStudent").modal('hide');
$("#list_showStudent").bootstrapTable('refresh');
}
});
});
});
/**
* 修改学生信息:获取table的全部信息,获取每一行的字段内容,预备显示到弹框
*/
function editStudentBtn(index){
var data=$("#list_showStudent").bootstrapTable('getData');
$("#ids").val(data[index].id);
$("#OldAge").val(data[index].age);
$("#OldName").val(data[index].name);
$("#OldToDay").val(data[index].toDay);
}
$(".btn_editStudent").click(function () {
var ser=$("#form_editStudent").serialize();
$.post("updateStudent",ser,function(data){
/* $.post("editStudent",ser,function(data){ */
if (data==1){
layer.msg("操作成功",{icon:1});
$("#list_showStudent").bootstrapTable("refresh");
$("#editStudentDiv").modal('hide');
}
});
});
/**
查询信息
*/
$("#button_selectStudent").click(function(){
var testInput=$("#input_title").val();
$("#list_showStudent").bootstrapTable('refresh',{url:"selectStudent",query:{testInput:testInput}});
});
好了,demo的代码都给了,有错误请自行解决,
其他:自定义错误页面
1、在templates加一个错误页面,我的是:error/error.html
404
啊,页面出错了!404!
——来自异世界的客户端!
2、自定义一个控制类,实现ErrorController接口,
设置页面跳转ok
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by Administrator on 2018/6/18 0018.
*/
@Controller
public class ErrorIndexController implements ErrorController{
@Override
@RequestMapping(value = "/error")
public String getErrorPath() {
return "error/error";
}
/* @RequestMapping
public String error() {
return getErrorPath();
}*/
}
框架搭建完成,自行规范优化代码,美化页面,
有致命报错或者意见,请到群里去找我,博客左边有链接,
欢迎各位的指点,后期会出第三篇,继续完善这个框架