├── .gitignore ├── Readme.md ├── pom.xml └── src ├── main ├── java │ └── br │ │ └── com │ │ └── casadocodigo │ │ └── loja │ │ ├── CasadocodigoSpringbootApplication.java │ │ ├── controllers │ │ ├── HomeController.java │ │ └── ProductsController.java │ │ ├── daos │ │ └── ProductDAO.java │ │ ├── infra │ │ ├── FileSaver.java │ │ └── HttpPartUtils.java │ │ └── models │ │ ├── BookType.java │ │ ├── Price.java │ │ └── Product.java ├── resources │ ├── application.properties │ └── log4j.xml └── webapp │ └── WEB-INF │ ├── footer.jsp │ ├── header.jsp │ ├── jsp │ ├── index.jsp │ └── products │ │ ├── form.jsp │ │ ├── list.jsp │ │ └── show.jsp │ └── tags │ └── page.tag └── test └── java └── br └── com └── casadocodigo └── loja └── CasadocodigoSpringbootApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | bin 3 | target 4 | .classpath 5 | .project 6 | .settings 7 | src/main/webapp/META-INF 8 | .idea 9 | *.iml 10 | imagens-textos-livro 11 | jsonData.txt 12 | output.txt 13 | inserts-security.txt 14 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | #Aplicação do livro de Spring MVC usando o Spring boot 2 | 3 | A ideia é acompanhando as mudanças no boot e ir atualizando aplicação. Também vai servir de fonte de inspiração para o blog :). -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | br.com.casadocodigo 7 | loja-springboot 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | casadocodigo-springboot 12 | Casa do c�digo com o springboot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.3.0.BUILD-SNAPSHOT 18 | 19 | 20 | 21 | UTF-8 22 | 1.8 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-data-jpa 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-devtools 50 | 51 | 52 | 53 | javax.servlet 54 | jstl 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-tomcat 60 | provided 61 | 62 | 63 | org.apache.tomcat.embed 64 | tomcat-embed-jasper 65 | provided 66 | 67 | 68 | 69 | 70 | 71 | mysql 72 | mysql-connector-java 73 | 74 | 75 | 76 | 77 | 78 | 79 | org.springframework.boot 80 | spring-boot-maven-plugin 81 | 82 | 83 | 84 | 85 | 86 | 87 | spring-snapshots 88 | http://repo.spring.io/snapshot 89 | 90 | true 91 | 92 | 93 | 94 | spring-milestones 95 | http://repo.spring.io/milestone 96 | 97 | 98 | 99 | 100 | spring-snapshots 101 | http://repo.spring.io/snapshot 102 | 103 | 104 | spring-milestones 105 | http://repo.spring.io/milestone 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/CasadocodigoSpringbootApplication.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja; 2 | 3 | import javax.sql.DataSource; 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.core.env.Environment; 9 | import org.springframework.jdbc.datasource.DriverManagerDataSource; 10 | 11 | @SpringBootApplication 12 | public class CasadocodigoSpringbootApplication { 13 | @Bean 14 | public DataSource dataSource(Environment environment) { 15 | DriverManagerDataSource dataSource = new DriverManagerDataSource(); 16 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 17 | dataSource.setUrl("jdbc:mysql://localhost:3306/casadocodigo"); 18 | dataSource.setUsername("root"); 19 | dataSource.setPassword(""); 20 | return dataSource; 21 | } 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(CasadocodigoSpringbootApplication.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/controllers/HomeController.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.controllers; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.ResponseBody; 6 | 7 | @Controller 8 | public class HomeController { 9 | 10 | @RequestMapping("/") 11 | public String home() { 12 | return "index"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/controllers/ProductsController.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.controllers; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletContext; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import javax.transaction.Transactional; 10 | import javax.validation.Valid; 11 | 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.cache.annotation.CacheEvict; 14 | import org.springframework.cache.annotation.Cacheable; 15 | import org.springframework.stereotype.Controller; 16 | import org.springframework.validation.BindingResult; 17 | import org.springframework.web.bind.annotation.ModelAttribute; 18 | import org.springframework.web.bind.annotation.PathVariable; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.RequestMethod; 21 | import org.springframework.web.multipart.MultipartFile; 22 | import org.springframework.web.servlet.ModelAndView; 23 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 24 | import org.springframework.web.servlet.view.InternalResourceViewResolver; 25 | 26 | import br.com.casadocodigo.loja.daos.ProductDAO; 27 | import br.com.casadocodigo.loja.infra.FileSaver; 28 | import br.com.casadocodigo.loja.models.BookType; 29 | import br.com.casadocodigo.loja.models.Product; 30 | 31 | @Controller 32 | @Transactional 33 | @RequestMapping("/produtos") 34 | public class ProductsController { 35 | 36 | @Autowired 37 | private ProductDAO products; 38 | @Autowired 39 | private FileSaver fileSaver; 40 | @Autowired 41 | private ServletContext ctx; 42 | @Autowired 43 | private InternalResourceViewResolver resolver; 44 | 45 | 46 | @RequestMapping(method=RequestMethod.POST) 47 | @CacheEvict(value="lastProducts", allEntries=true) 48 | public ModelAndView save(MultipartFile summary,@ModelAttribute("product") @Valid Product product,BindingResult bindingResult,RedirectAttributes redirectAttributes) throws IOException{ 49 | if(bindingResult.hasErrors()){ 50 | return form(product); 51 | } 52 | 53 | //Sera que passo o product como parametro? 54 | String webPath = fileSaver.write("uploaded-images",summary); 55 | product.setSummaryPath(webPath); 56 | products.save(product); 57 | 58 | redirectAttributes.addFlashAttribute("success", "Produto cadastrado com sucesso"); 59 | return new ModelAndView("redirect:produtos"); 60 | } 61 | 62 | @RequestMapping("/form") 63 | public ModelAndView form(@ModelAttribute Product product){ 64 | ModelAndView modelAndView = new ModelAndView("products/form"); 65 | modelAndView.addObject("bookTypes", BookType.values()); 66 | return modelAndView; 67 | } 68 | 69 | @RequestMapping(method=RequestMethod.GET) 70 | @Cacheable(value="lastProducts") 71 | public ModelAndView list() throws ServletException, IOException{ 72 | System.out.println("ola"); 73 | ModelAndView modelAndView = new ModelAndView("products/list"); 74 | modelAndView.addObject("products", products.findAll()); 75 | return modelAndView; 76 | } 77 | 78 | 79 | @RequestMapping("/{id}") 80 | public ModelAndView show(@PathVariable("id") Integer id){ 81 | ModelAndView modelAndView = new ModelAndView("products/show"); 82 | Product product = products.findOne(id); 83 | modelAndView.addObject("product", product); 84 | return modelAndView; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/daos/ProductDAO.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.daos; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.Repository; 8 | import org.springframework.data.repository.query.Param; 9 | 10 | import br.com.casadocodigo.loja.models.BookType; 11 | import br.com.casadocodigo.loja.models.Product; 12 | 13 | @org.springframework.stereotype.Repository 14 | public interface ProductDAO extends Repository{ 15 | 16 | @Query("select distinct(p) from Product p join fetch p.prices where p.id=:id") 17 | public Product findOne(@Param("id") Integer id); 18 | 19 | @Query("select sum(price.value) from Product p join p.prices price where price.bookType = :book") 20 | public BigDecimal sumPricesPerType(@Param("book") BookType book); 21 | 22 | public List findByPagesGreaterThan(@Param("pages") int pages); 23 | 24 | public List findAll(); 25 | 26 | public Product save(Product product); 27 | 28 | } -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/infra/FileSaver.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.infra; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | @Component 13 | public class FileSaver { 14 | 15 | @Autowired 16 | private HttpServletRequest request; 17 | 18 | public String write(String baseFolder, MultipartFile multipartFile) { 19 | String realPath = request.getServletContext().getRealPath("/"+baseFolder); 20 | try { 21 | String path = realPath+"/"+multipartFile.getOriginalFilename(); 22 | multipartFile.transferTo(new File(path)); 23 | return baseFolder+"/"+multipartFile.getOriginalFilename(); 24 | } catch (IOException e) { 25 | throw new RuntimeException(e); 26 | } 27 | 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/infra/HttpPartUtils.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.infra; 2 | 3 | import javax.servlet.http.Part; 4 | 5 | public class HttpPartUtils { 6 | 7 | public static String extractFileName(Part part) { 8 | String contentDisp = part.getHeader("content-disposition"); 9 | String[] items = contentDisp.split(";"); 10 | for (String s : items) { 11 | if (s.trim().startsWith("filename")) { 12 | return s.substring(s.indexOf("=") + 2, s.length()-1); 13 | } 14 | } 15 | return ""; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/models/BookType.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.models; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | @XmlRootElement 6 | public enum BookType { 7 | 8 | EBOOK,PRINTED,COMBO 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/models/Price.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.models; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Embeddable; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Embeddable 10 | public class Price { 11 | 12 | @Column(scale = 2) 13 | //@NumberFormat(style=Style.CURRENCY) 14 | private BigDecimal value; 15 | private BookType bookType; 16 | 17 | public BigDecimal getValue() { 18 | return value; 19 | } 20 | 21 | public void setValue(BigDecimal valor) { 22 | this.value = valor; 23 | } 24 | 25 | public BookType getBookType() { 26 | return bookType; 27 | } 28 | 29 | public void setBookType(BookType tipoLivro) { 30 | this.bookType = tipoLivro; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "Price [value=" + value + ", bookType=" + bookType + "]"; 36 | } 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/br/com/casadocodigo/loja/models/Product.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja.models; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.ArrayList; 5 | import java.util.Calendar; 6 | import java.util.List; 7 | 8 | import javax.persistence.ElementCollection; 9 | import javax.persistence.Entity; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.Lob; 14 | import javax.validation.constraints.Min; 15 | import javax.xml.bind.annotation.XmlRootElement; 16 | 17 | import org.hibernate.validator.constraints.NotBlank; 18 | import org.springframework.format.annotation.DateTimeFormat; 19 | import org.springframework.format.annotation.DateTimeFormat.ISO; 20 | 21 | @Entity 22 | @XmlRootElement 23 | public class Product { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | private Integer id; 28 | @NotBlank 29 | private String title; 30 | @Lob 31 | @NotBlank 32 | private String description; 33 | @Min(30) 34 | private int pages; 35 | @ElementCollection 36 | private List prices = new ArrayList(); 37 | 38 | // motivar que eu quero fazer uma configuração global suportando este estilo 39 | // primeiro motiva que podemos criar um converter para isso. 40 | // @DateTimeFormat(iso=ISO.DATE) 41 | @DateTimeFormat 42 | private Calendar releaseDate; 43 | private String summaryPath; 44 | 45 | public String getSummaryPath() { 46 | return summaryPath; 47 | } 48 | 49 | public void setSummaryPath(String summaryPath) { 50 | this.summaryPath = summaryPath; 51 | } 52 | 53 | public Calendar getReleaseDate() { 54 | return releaseDate; 55 | } 56 | 57 | public void setReleaseDate(Calendar releaseDate) { 58 | this.releaseDate = releaseDate; 59 | } 60 | 61 | public Integer getId() { 62 | return id; 63 | } 64 | 65 | public List getPrices() { 66 | return prices; 67 | } 68 | 69 | public void setPrices(List valores) { 70 | this.prices = valores; 71 | } 72 | 73 | public String getTitle() { 74 | return title; 75 | } 76 | 77 | public void setTitle(String titulo) { 78 | this.title = titulo; 79 | } 80 | 81 | public String getDescription() { 82 | return description; 83 | } 84 | 85 | public void setDescription(String descricao) { 86 | this.description = descricao; 87 | } 88 | 89 | public int getPages() { 90 | return pages; 91 | } 92 | 93 | public void setPages(int numeroPaginas) { 94 | this.pages = numeroPaginas; 95 | } 96 | 97 | @Override 98 | public String toString() { 99 | return "Produto [id=" + id + ", titulo=" + title + ", descricao=" 100 | + description + ", numeroPaginas=" + pages + ", valores=" 101 | + prices + "]"; 102 | } 103 | 104 | public BigDecimal priceFor(BookType bookType) { 105 | return prices 106 | .stream() 107 | .filter(price -> price.getBookType().equals(bookType)) 108 | .findFirst().get().getValue(); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.mvc.view.prefix=/WEB-INF/jsp/ 2 | spring.mvc.view.suffix=.jsp 3 | 4 | #hibernate 5 | spring.jpa.hibernate.ddl-auto=update -------------------------------------------------------------------------------- /src/main/resources/log4j.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 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/footer.jsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asouza/casadocodigo-springboot/0d55efbca95770a03664367a8cb0de92f6a9e099/src/main/webapp/WEB-INF/footer.jsp -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/header.jsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asouza/casadocodigo-springboot/0d55efbca95770a03664367a8cb0de92f6a9e099/src/main/webapp/WEB-INF/header.jsp -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | oioi 4 | 5 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/products/form.jsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asouza/casadocodigo-springboot/0d55efbca95770a03664367a8cb0de92f6a9e099/src/main/webapp/WEB-INF/jsp/products/form.jsp -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/products/list.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 4 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> 5 | <%@taglib tagdir="/WEB-INF/tags" prefix="customTags"%> 6 | 7 | 8 | 9 | 10 | ${success} 11 | 12 | 13 | Cadastrar novo produto 14 | 15 | 16 | 17 | Titulo 18 | Valores 19 | 20 | 21 | 22 | ${product.title} 23 | 24 | 25 | [${price.value} - ${price.bookType}] 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/products/show.jsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asouza/casadocodigo-springboot/0d55efbca95770a03664367a8cb0de92f6a9e099/src/main/webapp/WEB-INF/jsp/products/show.jsp -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/tags/page.tag: -------------------------------------------------------------------------------- 1 | <%@attribute name="title" required="true" %> 2 | <%@attribute name="bodyClass" required="true" %> 3 | <%@attribute name="extraScripts" fragment="true" %> 4 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 5 | <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> 6 | <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> 7 | <%@taglib uri="http://www.springframework.org/tags" prefix="spring" %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | ${title} 22 | 23 | 24 | 25 | <%@include file="/WEB-INF/header.jsp" %> 26 | 27 | 28 | 29 | <%@include file="/WEB-INF/footer.jsp" %> 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/test/java/br/com/casadocodigo/loja/CasadocodigoSpringbootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package br.com.casadocodigo.loja; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.SpringApplicationConfiguration; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | 8 | @RunWith(SpringJUnit4ClassRunner.class) 9 | @SpringApplicationConfiguration(classes = CasadocodigoSpringbootApplication.class) 10 | public class CasadocodigoSpringbootApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------