我用的是ide;参考学习地址:http://how2j.cn/k/tmall_springboot/tmall_springboot-1891/1891.html;我只是记录下笔记
要配置的引用,我用的是jdk1.8
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <!-- springboot web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springboot tomcat 支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- 热部署 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- jpa--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- springboot test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- thymeleaf --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- elastic search --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <!-- 用了 elasticsearch 就要加这么一个,不然要com.sun.jna.Native 错误 --> <dependency> <groupId>com.sun.jna</groupId> <artifactId>jna</artifactId> <version>3.0.9</version> </dependency> <!-- thymeleaf legacyhtml5 模式支持 --> <dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> <version>1.9.22</version> </dependency> <!-- 测试支持 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- tomcat的支持.--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>8.5.23</version> </dependency> <!-- mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version> 4.12</version> </dependency> <!-- commons-lang --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <!-- hsqldb --> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
然后配置文件application.properties
#database spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tmall_springboot?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.hibernate.ddl-auto = none #thymeleaf spring.thymeleaf.mode=LEGACYHTML5 #html语法不用很严谨 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=false #context http://localhost:8080/tmall_springboot/ server.context-path=/tmall_springboot #设置上传文件大小,默认只有1 m spring.http.multipart.maxFileSize=100Mb spring.http.multipart.maxRequestSize=100Mb #jpa对实体类的默认字段会把驼峰命名的属性,转换为字段名的时候自动加上下划线。 这个配置的作用就是去掉下划线 #比如属性名称是 createDate, jpa 默认转换为字段名 create_Date。 有了这个配置之后,就会转换为同名字段 createDate spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #显示 hibernate运行的 sql 语句 spring.jpa.show-sql=true
然后按照参考网站copy代码
先添加模型
package com.how2java.tmall.pojo; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @Entity @Table(name = "category") //jpa json会忽略这两个属性 @JsonIgnoreProperties({ "handler","hibernateLazyInitializer" }) public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY)//自增id @Column(name = "id") int id; String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
用的是springdatajap,参考博客:https://www.cnblogs.com/yeqingxue/p/11153721.html
package com.how2java.tmall.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.how2java.tmall.pojo.Category; public interface CategoryDAO extends JpaRepository<Category,Integer>{ }
在添加一个jpa服务,操作数据
package com.how2java.tmall.service; import java.util.List; import com.how2java.tmall.util.Page4Navigator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import com.how2java.tmall.dao.CategoryDAO; import com.how2java.tmall.pojo.Category; @Service public class CategoryService { @Autowired CategoryDAO categoryDAO; public List<Category> list() { Sort sort = new Sort(Sort.Direction.DESC, "id"); return categoryDAO.findAll(sort); } public Page4Navigator<Category> list(int start, int size, int navigatePages) { Sort sort = new Sort(Sort.Direction.DESC, "id"); Pageable pageable = new PageRequest(start, size,sort); Page pageFromJPA =categoryDAO.findAll(pageable); return new Page4Navigator<>(pageFromJPA,navigatePages); } public void add(Category bean) { categoryDAO.save(bean); } public void delete(int id) { categoryDAO.delete(id); } public Category get(int id) { Category c= categoryDAO.findOne(id); return c; } public void update(Category bean) { categoryDAO.save(bean); } }
然后添加控制器,一个是视图控制器,一个是操作数据控制器
package com.how2java.tmall.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class AdminPageController { @GetMapping(value="/admin") public String admin(){ return "redirect:admin_category_list"; } @GetMapping(value="/admin_category_list") public String listCategory(){ return "admin/listCategory"; } @GetMapping(value="/admin_category_edit") public String editCategory(){ return "admin/editCategory"; } }
package com.how2java.tmall.web; import com.how2java.tmall.pojo.Category; import com.how2java.tmall.service.CategoryService; import com.how2java.tmall.util.ImageUtil; import com.how2java.tmall.util.Page4Navigator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.List; @RestController public class CategoryController { @Autowired CategoryService categoryService; @GetMapping("/categories") public Page4Navigator<Category> list(@RequestParam(value = "start", defaultValue = "0") int start, @RequestParam(value = "size", defaultValue = "5") int size) throws Exception { start = start<0?0:start; Page4Navigator<Category> page =categoryService.list(start, size, 5); //5表示导航分页最多有5个,像 [1,2,3,4,5] 这样 return page; } @PostMapping("/categories") public Object add(Category bean, MultipartFile image, HttpServletRequest request) throws Exception { categoryService.add(bean); saveOrUpdateImageFile(bean, image, request); return bean; } public void saveOrUpdateImageFile(Category bean, MultipartFile image, HttpServletRequest request) throws IOException { File imageFolder= new File(request.getServletContext().getRealPath("img/category")); File file = new File(imageFolder,bean.getId()+".jpg"); if(!file.getParentFile().exists()) file.getParentFile().mkdirs(); image.transferTo(file); BufferedImage img = ImageUtil.change2jpg(file); ImageIO.write(img, "jpg", file); } @DeleteMapping("/categories/{id}") public String delete(@PathVariable("id") int id, HttpServletRequest request) throws Exception { categoryService.delete(id); File imageFolder= new File(request.getServletContext().getRealPath("img/category")); File file = new File(imageFolder,id+".jpg"); file.delete(); return null; } @GetMapping("/categories/{id}") public Category get(@PathVariable("id") int id) throws Exception { Category bean=categoryService.get(id); return bean; } @PutMapping("/categories/{id}") public Object update(Category bean, MultipartFile image, HttpServletRequest request) throws Exception { String name = request.getParameter("name"); bean.setName(name); categoryService.update(bean); if(image!=null) { saveOrUpdateImageFile(bean, image, request); } return bean; } }
然后是通用的分页和图片上传
package com.how2java.tmall.util; import java.util.List; import org.springframework.data.domain.Page; public class Page4Navigator<T> { Page<T> pageFromJPA; int navigatePages; int totalPages; int number; long totalElements; int size; int numberOfElements; List<T> content; boolean isHasContent; boolean first; boolean last; boolean isHasNext; boolean isHasPrevious; int[] navigatepageNums; public Page4Navigator() { //这个空的分页是为了 Redis 从 json格式转换为 Page4Navigator 对象而专门提供的 } public Page4Navigator(Page<T> pageFromJPA,int navigatePages) { this.pageFromJPA = pageFromJPA; this.navigatePages = navigatePages; totalPages = pageFromJPA.getTotalPages(); number = pageFromJPA.getNumber() ; totalElements = pageFromJPA.getTotalElements(); size = pageFromJPA.getSize(); numberOfElements = pageFromJPA.getNumberOfElements(); content = pageFromJPA.getContent(); isHasContent = pageFromJPA.hasContent(); first = pageFromJPA.isFirst(); last = pageFromJPA.isLast(); isHasNext = pageFromJPA.hasNext(); isHasPrevious = pageFromJPA.hasPrevious(); calcNavigatepageNums(); } private void calcNavigatepageNums() { int navigatepageNums[]; int totalPages = getTotalPages(); int num = getNumber(); //当总页数小于或等于导航页码数时 if (totalPages <= navigatePages) { navigatepageNums = new int[totalPages]; for (int i = 0; i < totalPages; i++) { navigatepageNums[i] = i + 1; } } else { //当总页数大于导航页码数时 navigatepageNums = new int[navigatePages]; int startNum = num - navigatePages / 2; int endNum = num + navigatePages / 2; if (startNum < 1) { startNum = 1; //(最前navigatePages页 for (int i = 0; i < navigatePages; i++) { navigatepageNums[i] = startNum++; } } else if (endNum > totalPages) { endNum = totalPages; //最后navigatePages页 for (int i = navigatePages - 1; i >= 0; i--) { navigatepageNums[i] = endNum--; } } else { //所有中间页 for (int i = 0; i < navigatePages; i++) { navigatepageNums[i] = startNum++; } } } this.navigatepageNums = navigatepageNums; } public int getNavigatePages() { return navigatePages; } public void setNavigatePages(int navigatePages) { this.navigatePages = navigatePages; } public int getTotalPages() { return totalPages; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public long getTotalElements() { return totalElements; } public void setTotalElements(long totalElements) { this.totalElements = totalElements; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public int getNumberOfElements() { return numberOfElements; } public void setNumberOfElements(int numberOfElements) { this.numberOfElements = numberOfElements; } public List<T> getContent() { return content; } public void setContent(List<T> content) { this.content = content; } public boolean isHasContent() { return isHasContent; } public void setHasContent(boolean isHasContent) { this.isHasContent = isHasContent; } public boolean isFirst() { return first; } public void setFirst(boolean first) { this.first = first; } public boolean isLast() { return last; } public void setLast(boolean last) { this.last = last; } public boolean isHasNext() { return isHasNext; } public void setHasNext(boolean isHasNext) { this.isHasNext = isHasNext; } public boolean isHasPrevious() { return isHasPrevious; } public void setHasPrevious(boolean isHasPrevious) { this.isHasPrevious = isHasPrevious; } public int[] getNavigatepageNums() { return navigatepageNums; } public void setNavigatepageNums(int[] navigatepageNums) { this.navigatepageNums = navigatepageNums; } }
package com.how2java.tmall.util; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; import java.awt.image.PixelGrabber; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class ImageUtil { public static BufferedImage change2jpg(File f) { try { Image i = Toolkit.getDefaultToolkit().createImage(f.getAbsolutePath()); PixelGrabber pg = new PixelGrabber(i, 0, 0, -1, -1, true); pg.grabPixels(); int width = pg.getWidth(), height = pg.getHeight(); final int[] RGB_MASKS = { 0xFF0000, 0xFF00, 0xFF }; final ColorModel RGB_OPAQUE = new DirectColorModel(32, RGB_MASKS[0], RGB_MASKS[1], RGB_MASKS[2]); DataBuffer buffer = new DataBufferInt((int[]) pg.getPixels(), pg.getWidth() * pg.getHeight()); WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, RGB_MASKS, null); BufferedImage img = new BufferedImage(RGB_OPAQUE, raster, false, null); return img; } catch (InterruptedException e) { e.printStackTrace(); return null; } } public static void resizeImage(File srcFile, int width,int height, File destFile) { try { if(!destFile.getParentFile().exists()) destFile.getParentFile().mkdirs(); Image i = ImageIO.read(srcFile); i = resizeImage(i, width, height); ImageIO.write((RenderedImage) i, "jpg", destFile); } catch (IOException e) { e.printStackTrace(); } } public static Image resizeImage(Image srcImage, int width, int height) { try { BufferedImage buffImg = null; buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); buffImg.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); return buffImg; } catch (Exception e) { e.printStackTrace(); } return null; } }
然后一个全局异常处理
package com.how2java.tmall.exception; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestController; @RestController @ControllerAdvice public class GloabalExceptionHandler { @ExceptionHandler(value = Exception.class) public String defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { e.printStackTrace(); Class constraintViolationException = Class.forName("org.hibernate.exception.ConstraintViolationException"); if(null!=e.getCause() && constraintViolationException==e.getCause().getClass()) { return "违反了约束,多半是外键约束"; } return e.getMessage(); } }
一个跨域的,但是现在没用
package com.how2java.tmall.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class CORSConfiguration extends WebMvcConfigurerAdapter{ @Override public void addCorsMappings(CorsRegistry registry) { //所有请求都允许跨域 registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*"); } }
主要的是application启动
package com.how2java.tmall; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
然后把视图文件加上:http://how2j.cn/k/tmall_springboot/tmall_springboot-1891/1891.html
然后增; 删;改;分页;上传图片就完成了
出现thymeleaf的问题:我用replace找不到页面,然后改成了include就解决了