idea 搭建ssm框架----項目實例在線商城講解

建立項目

以在線商城爲例,演示idea如何搭建ssm開發環境。如果覺得maven下載速度過慢,可以打開c盤的user目錄中的.m2文件夾下的setting.xml文件夾目錄,修改爲阿里源,然後重啓。這樣還是不行建議翻牆試試。

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          https://maven.apache.org/xsd/settings-1.0.0.xsd">

      <mirrors>
        <mirror>  
            <id>alimaven</id>  
            <name>aliyun maven</name>  
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>  
            <mirrorOf>central</mirrorOf>          
        </mirror>  
      </mirrors>
</settings>

在這裏插入圖片描述

創建各層的package

在這裏請選擇springspringmvc,然後一路next就能創建成功。之後請在src的包下創建四個模塊

  • controller
  • service
  • dao
  • pojo

創建resource目錄

右鍵最上層的文件夾創建一個與srcweb相同級別的resource目錄。將此目錄設置成resource root,右鍵resource選擇 Make Directory as ->resource root。爲什麼需要這麼做?因爲可以在許多的地方使用classpath:來引用這個目錄,否則使用一般文件目錄可能就無法生效,這很重要,後面會有講到在哪裏使用。

springbootclasspath默認是resource目錄。在springmvc中默認是src目錄。

新建實體對象

public class Book {
    private int id;
    private String name;
    private String Author;
    private double price;
    private String image;
    private String description;
    private int category_id;
	//省略setter、getter
}

/*-----------分割線,請在兩個不同class文件中建立這兩個對象---------------*/
public class Category {
    private int id;
    private String name;
    private String description;
}

sql 代碼

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(50) DEFAULT NULL,
  `author` char(10) DEFAULT NULL,
  `price` decimal(10,2) DEFAULT NULL,
  `image` varchar(50) DEFAULT '/image/book.jpeg',
  `description` varchar(1024) DEFAULT NULL,
  `category_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `book_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4


CREATE TABLE `category` (
  `id` int(11) NOT NULL,
  `name` varchar(256) DEFAULT NULL,
  `description` varchar(1024) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

完善目錄結構

  1. WEB-INF中views的文件夾,用來存放jsp文件
  2. 測試代碼目錄test
  3. mybatis的xml文件目錄mapper
  4. 靜態資源(css、js、image)
  5. 數據庫配置文件 db.properties
    在這裏插入圖片描述

web.xml文件配置

這個文件是與Tomcat相關聯的,如果這個目錄出錯,服務器是無法啓動的,在這裏我們需要配置springspringmvc,請在你爲web-app中加入下面的內容,前面之所以需要建立resource文件夾是方便在這裏利用applicationContext.xmldispatch-servlet.xml文件。

<!--配置spring-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--指定spring配置文件的位置-->
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--配置springmvc-->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--加入初始化參數指定springmvc配置文件的路徑-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <!--這裏需要修改一下-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

dispatch-servlet.xml文件配置

springmvc管理的是controller層,因此只需要掃描controller層的註解即可,其他層由spring的ioc容器管理。其次,要想在jsp中使用static中的靜態資源需要爲其配置映射。請在你的beans下添加下面內容

<!--mvc管理controller-->
    <context:component-scan base-package="cn.edu.ncu.bookstore.controller"></context:component-scan>

    <!--配套使用,啓動mvc註解-->
    <mvc:annotation-driven />
    <!--靜態資源映射-->
    <mvc:resources mapping="/css/**" location="/WEB-INF/static/css" />
    <mvc:resources mapping="/js/**" location="/WEB-INF/static/js" />
    <mvc:resources mapping="/images/**" location="/WEB-INF/static/images" />


<!--配置邏輯視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

applicationContext.xml文件配置

mybatis的配置和spring的配置都是在這個文件中進行,spring掃描包需要排除controller。這裏需要導入的包有:mybatis和mysql的jar。

<!--引入數據庫配置文件-->
    <context:property-placeholder location="classpath:db.properties" />

    <!--指定註解掃描路徑,排除controller-->
    <context:component-scan base-package="cn.edu.ncu.bookstore">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
    </context:component-scan>

    <!--以下內容都是配置mybatis-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--識別mapper文件-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean>
    <!--<bean id="categoryDao" class="org.mybatis.spring.mapper.MapperFactoryBean">-->
        <!--<property name="mapperInterface" value="cn.edu.ncu.bookstore.dao.CategoryDao"></property>-->
        <!--<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>-->
    <!--</bean>-->

    <!--導入所有的dao-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.edu.ncu.bookstore.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

db.properties文件內容如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

請根據自己的情況進行修改,另外mysql8版本的數據庫驅動名不再是com.mysql.jdbc.Driver而是com.mysql.cj.jdbc.Driver所以在導入mysql的驅動包時需要看清楚版本號

dao層開發

使用mybatis之後不需要在java中書寫sql語句,所有的數據庫操作都在xml文件中完成。使用repository和mapper其中之一就能完成bean的加入,看個人喜好

@Repository
@Mapper
public interface CategoryDao {
    List<Category> findAll();
}
@Repository
@Mapper
public interface BookDao {
    List<Book> findBookByCategoryId(@Param("id") int id);
}

然後在mapper層建立兩個mybatis-cogfig.xml配置文件

namespace指向你的具體dao接口,每個增刪改查操作的id都指向具體dao裏面的方法。

BookMapper.xml

<?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="cn.edu.ncu.bookstore.dao.BookDao">
    <resultMap id="bookMap" type="cn.edu.ncu.bookstore.entity.Book">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="author" column="author"></result>
        <result property="price" column="price"></result>
        <result property="description" column="description"></result>
        <result property="category_id" column="category_id"></result>
    </resultMap>

    <select id="findBookByCategoryId" resultMap="bookMap">
        select * from book where category_id = #{id}
    </select>
</mapper>

CategoryMapper.xml

<?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="cn.edu.ncu.bookstore.dao.CategoryDao">
    <resultMap id="categoryMap" type="cn.edu.ncu.bookstore.entity.Category">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="description" column="description"></result>
    </resultMap>

    <select id="findAll" resultMap="categoryMap">
        select * from category;
    </select>
</mapper>

一般idea在新建文件時沒有mybatis-config.xml這個選項,但是我們可以加以一個模板,在setting->editor->file and code templates中點擊‘+’,新建一個mybatis-config,將extension修改爲xml。將下面內容粘貼進去

<?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">

關於方法傳參說明
注意到BookDao的findBookByCategoryId()方法有一個@Param註解,這個註解幾乎能解決所有的傳參問題。

@Param適用場景

  • 當傳入參數有多個時,無法在xml文件中說明多個傳入參數的類型,如果用@Param註解就可以不用聲明參數的類型,可以直接用#{paramname}引用參數值
  • 當參數是基本數據類型時可以使用這個註解

tips當傳入的參數是一個對象可以不用這個註解,就可以在引用參數時省略類名。例如,不使用該註解就能這麼寫#{name},如果使用註解就要這麼寫,#{user.name}。
還有很多書寫技巧,例如根據字段的等值匹配查詢數據可以不用創建多個select,一個select也能完成任務,例如:

<select id="findUserByColumn" returnType="User">
	select * from user where ${column} = #{paramname};
</select>

這裏的column是你傳進來的String 類型的字段名稱,例如name,id等等,而paramname是查詢條件的值。

關於resultMap
resultMap是用來解決數據庫字段名與java對象名稱不匹配的情況,例如User對象有一個name屬性,而數據庫中是username,需要使用下面的語句進行映射。

<result properties="name"  column="username">

如果有對象的屬性在數據庫中是主鍵則需要使用id而不是result,可以唯一標識一個對象mybatis更強大的關係映射請參考mybatis中文文檔,有一對多、一對一、多對多的關係,mybatis可以通過多表查詢結果自動實例化多個對象。這裏的關係也有許多細節需要注意,例如當可以保證查詢結果不爲空時使用連接查詢可以防止N+1的情況,如果多表查詢結果可能爲空,例如有一個Userblog表,在java中的user對象有一個List<Blog>對象,但是在數據庫中blog表中沒有該user發佈的blog,在這種情況下使用連接查詢其結果就爲空,自然mybatis就無數據可以填充user對象,因此返回的user爲null,但是我們需要的是user對象,List我們不關心,在這種情況下我們不得不N+1,即查詢一個User獲得外鍵user_id後在blog表中判斷N遍將得到的結果去實例化List,N+1極大的降低了效率。

service層開發

@Service
public class CategoryService {
    @Autowired
    private CategoryDao categoryDao;

    public List<Category> findAll(){
        return categoryDao.findAll();
    }
}
@Service
public class BookService {
    @Autowired
    private BookDao bookDao;

    public List<Book> findBookesById(int id){
        return bookDao.findBookByCategoryId(id);
    }
}

在這裏需要說明的是每一個使用註解加入到bean容器的對象它的id名稱會默認是類名首字符小寫的駝峯式命名,在使用@AutoWired時如果是service的impl需要注意。

測試

Test目錄下新建一個ServiceTest類。如果沒有建立resource目錄,applicationContext.xml文件默認是在web文件夾下,就只能通過file的形式進行定位,但是我試了網上的好多方法最後的結果是tomcat無法加載這個xml文件。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"applicationContext.xml"})
public class ServiceTest {
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private BookService bookService;
    @Test
    public void TestCategoryService(){
        System.out.println(categoryService.findAll());
    }
    @Test
    public void TestBookService(){
        System.out.println(bookService.findBookesById(1));
    }
}

這裏需要導入junil和hamcrest的jar包。@ContextConfiguration指明從哪個文件構造ioc容器。

測試結果
在這裏插入圖片描述

controller開發

@Controller
@RequestMapping("/category")
public class CategoryController {
    @Autowired
    private CategoryService categoryService;

    @RequestMapping("/view")
    public String viewCategory(Model model){
        List<Category> list = categoryService.findAll();
        model.addAttribute("category",list);
        return "main";
    }

    /*使用modelAndView*/
    @RequestMapping("/modelview")
    public ModelAndView showCategory(ModelAndView model){
        List<Category> list = categoryService.findAll();
        model.setViewName("main");
        model.addObject("category",list);
        return model;
    }
}
@Controller
@RequestMapping("/book")
public class BookController {
    @Autowired
    private BookService bookService;

/*restful風格*/
    @RequestMapping("/{id}")
    @ResponseBody
    public List<Book> showBookedByCategoryId(@PathVariable("id") int id){
        return bookService.findBookesById(id);
    }
/*常規方式
	@RequestMapping("")
	@ResponseBody
	public List<Book> showBookCategoryId(@RequestParam("id") int id){
	}
	*/

}

使用@controller將這個類加入容器,@RequestMapping進行攔截url。

一般常見url的幾種風格有一下幾種:

  1. 常規方式
    http://localhost:8080/book?id=1
  2. restful風格推薦
    http://localhost:8080/book/1
    如果是ajax請求json數據,可以使用@ResponseBody,將返回的對象以字符串的形式寫入body中,這裏需要引入三個jackson的jar,springmvc才能自動的將對象轉化爲字符串
    • jackson-databind.jar
    • jackson-annotation.jar
    • jackson-core.jar

view開發

在view文件夾下新建main.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.ResultSet" %>

<%@ page import="java.util.List" %>
<%--
  Created by IntelliJ IDEA.
  User: maoalong
  Date: 2019/11/4
  Time: 10:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <script type="text/javascript" src="/js/jquery.min.js"></script>
    <link href="/css/bootstrap3.min.css" rel="stylesheet">
    <link href="/css/main-style.css" rel="stylesheet">
    <script type="text/javascript" src="/js/bootstrap3.min.js"></script>
    <script src="/js/commons.js"></script>
    <title>網上書店</title>
</head>
<body>
<div class="header">
    <div class="container">
        <div class="row">
            <div class="login col-md-12">
                <h1><a href="">歡迎來到<strong>我的</strong>書店</a>
                    <span style="color: red">.</span>
                </h1>
            </div>
        </div>
        <div class="row">
            <div class="login col-md-3 col-md-offset-9">
                <a class="login" href="" rel="tooltip"  data-toggle="modal" data-target="#myModal">登錄</a>
                <a class="register" href="" rel="tooltip" data_placement="bottom">註冊</a>
            </div>
        </div>
    </div>
</div>

<div class="aside">
    <div class="container">
        <div class="row"> <%--下方左右div控制--%>
            <div class="col-md-3"> <%--左側菜單div控制--%>
                <ul class="nav nav-pills nav-stacked" id="categorylist">
                    <li class="nav-header">書籍類型</li>
                    <c:forEach items="${category}" var="category">
                        <li>
                            <a href="javascript:showBook(${category.id})">${category.name}</a>
                        </li>
                    </c:forEach>
                </ul>
            </div><%--左側菜單div控制--%>
        </div>
    </div>
</div>


<div id="book">
    <%--<div class="col-md-9">&lt;%&ndash;右側書本div控制&ndash;%&gt;--%>
    <%--<%--%>
    <%--Object books = request.getAttribute("books");--%>
    <%--List<Book> listBook = null;--%>
    <%--if (books instanceof List) {--%>
    <%--listBook =(List<Book>)books;--%>
    <%--}--%>
    <%--if(listBook!=null) {--%>
    <%--for(Book book:listBook) {--%>
    <%--String desc = book.getDescription();--%>
    <%--if(desc.length() > 18) {--%>
    <%--desc = desc.substring(1,18) + "...";--%>
    <%--}--%>
    <%--%>--%>
    <%--<div class="col-sm-9 col-md-3">--%>
    <%--<div class="thumbnail">--%>
    <%--<img src="/images/book.jpeg"--%>
    <%--alt="通用的佔位符縮略圖">--%>
    <%--<div class="caption">--%>
    <%--<h4><%=book.getName()%></h4>--%>
    <%--<p><%=desc%></p>--%>
    <%--<p>--%>
    <%--<a href="#" class="btn btn-primary" role="button">--%>
    <%--按鈕--%>
    <%--</a>--%>
    <%--<a href="#" class="btn btn-default" role="button">--%>
    <%--按鈕--%>
    <%--</a>--%>
    <%--</p>--%>
    <%--</div>--%>
    <%--</div>--%>
    <%--</div>--%>
    <%--<%--%>
    <%--}--%>
    <%--}--%>
    <%--%>--%>
    <%--</div>&lt;%&ndash;右側書本div控制&ndash;%&gt;--%>
</div>




<div class="modal fade" id="myModal" >
    <div class="modal-dialog" style="width:550px;" >
        <div class="modal-content">
            <!--  模態框的頭 -->
            <div class="modal-header">
                <h2 class="modal-title" id="myModalLabel" style="margin: 0 auto;font-weight: 300;font-family: '宋體'">登錄</h2>
            </div>
            <div class="modal-body">

                <!--   以下是登錄的form表單 -->
                <form class="form-group" action="showID.jsp" method="post">
                    <div class="form-group">
                        <label>用戶名</label>
                        <input name="id" class="form-control" type="text" placeholder="請輸入用戶名">
                    </div>
                    <div class="form-group">
                        <label>密碼</label>
                        <input name="pwd" class="form-control" type="password" placeholder="請輸入密碼">
                    </div>

                    <div class="text-right">
                        <button class="btn btn-primary" type="submit">登錄</button>
                        <button class="btn btn-danger" data-dismiss="modal">取消</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>


</body>
<script language="JavaScript">
    // function showCategory() {
    //     var xmlHttp = new XMLHttpRequest();
    //     xmlHttp.open("GET","/category",true);
    //     xmlHttp.onreadystatechange = function () {
    //         if(xmlHttp.readyState==4) {
    //             var data = xmlHttp.responseText;
    //             var obj = JSON.parse(data);
    //             obj = obj.categories;
    //             var listHtml = "<li class=\"nav-header\">書籍類別</li>\n" ;
    //             for(var i=0;i<obj.length;i++){
    //                 listHtml += "<li>\n" +
    //                     " <a href=\"javascript:showBook("+ obj[i].id + ")\">"+obj[i].name+"</a>\n" +
    //                     "           </li>"
    //             }
    //             document.getElementById("categorylist").innerHTML=listHtml;
    //         }
    //     }
    //     xmlHttp.send();
    // }

    function showBook(categoryID) {
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open("GET", "/book/"+categoryID, true);
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4) {
                var data = xmlHttp.responseText;
                var obj = JSON.parse(data);
                var listbook = '';
                for(var i = 0; i<obj.length;i++){
                    var bookname = obj[i].name;
                    var desc = obj[i].description;
                    if(desc.length > 20) {
                        desc = desc.substring(0,17)
                    }
                    listbook += `<div class="col-sm-9 col-md-3"><div class="thumbnail" ><img src="/images/book.jpeg"><div class="caption"><h4>
                                ${bookname}</h4><p>${desc}</p><p><a href="#" class="btn btn-primary"role="button">加入購物車</a>
                                <a href="#" class="btn btn-default" role="button">查看詳情</a></p></div></div> </div>`;
                }
                document.getElementById("book").innerHTML = listbook;
            }
        }
        xmlHttp.send();
    }
</script>
</html>

static中引用的靜態文件
在這裏插入圖片描述

到這裏一個簡單的在線商城已經完成了,現在可以看下效果怎麼樣。配置你的tomcat服務器,啓動後在地址欄輸入:http://localhost:8080/category/view

在這裏插入圖片描述

點擊其中一種書籍類型,後臺的ajax函數會爲我們請求數據

在這裏插入圖片描述

我們不妨看看ajax返回的數據,結果是一個json字符串,爲了看得更清楚點可以使用postman軟件發送請求。可以看到返回的就是一個js的數組對象。

在這裏插入圖片描述

springboot版本的在線商城請參考idea搭建springboot項目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章