一.环境说明
- Windows 10 ver 1703
- IDEA 2017 2.5
- JDK 1.8
- MySQL 5.7
- Maven 3.5
二.框架说明
- Spring 4.3.11
- SpringMVC 4.3.11
- Hibernate 5.2.11
- Bootstrap 3.3.7
- Flat UI 2.3
三.项目说明
利用SSH三大框架,实现一个留言页面,可以展示留言以及添加留言,基于注解.
四.源码
项目结构:
实体类:
Msg.class
package com.cs.qsx.domain;
import com.alibaba.fastjson.annotation.JSONField;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "tb_msg")
public class Msg {
@Id //主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //自增
private Integer id;
@Column(length = 10)
private String name;
@Column(length = 100)
private String context;
@Column(columnDefinition = "DATE") //指定属性在表中的字段类型
@JSONField(format = "yyyy-MM-dd") //指定json格式化时如何格式化date
private Date createDate;
public Msg() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
}
数据库连接配置
dbconfig.properties
jdbc.driverclass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/Msg_Test?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
Spring配置文件
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--Spring的约束文件 使用那些模块就标记那些模块的约束文档 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd ">
<!--1、加载外部配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties" />
<context:component-scan base-package="com.cs.qsx.dao"></context:component-scan>
<context:component-scan base-package="com.cs.qsx.service"></context:component-scan>
<!--2、配置数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="driverClassName" value="${jdbc.driverclass}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="stat" />
<!-- 配置初始化大小、最小、最大 -->
<property name="maxActive" value="20" />
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="20" />
</bean>
<!-- 3、配置SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--配置数据库连接池 -->
<property name="dataSource" ref="dataSource"></property>
<!--Hibernate的设置信息 -->
<property name="hibernateProperties">
<props>
<!--方言 -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>
<!--显示SQL -->
<prop key="hibernate.show_sql">false</prop>
<!--格式化sql语句 -->
<prop key="hibernate.format_sql">false</prop>
<!--ddl自动语句 -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
<!-- 最好使用Spring中对SessionContext的子类 -->
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext
</prop>
</props>
</property>
<!--扫描Hibernate注解的实体类包 -->
<property name="packagesToScan">
<value>com.cs.qsx.domain</value>
</property>
</bean>
<!--4、配置事务管理对象 -->
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--配置AOP注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!--设置注解事务的管理对象 -->
<tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>
</beans>
SpringMVC配置文件
springmvc.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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<!--解决@Responcebody中文乱码问题 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"></constructor-arg>
</bean>
<!--配合fastjson支持 -->
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="defaultCharset" value="UTF-8"></property>
<property name="supportedMediaTypes">
<list>
<value>application/json</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
<property name="fastJsonConfig" ref="fastJsonConfig"></property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--fastJsonConfig -->
<bean id="fastJsonConfig" class="com.alibaba.fastjson.support.config.FastJsonConfig">
<!--默认编码格式 -->
<property name="charset" value="UTF-8"></property>
<!--默认日期格式化格式 -->
<property name="dateFormat" value="yyyy-MM-dd"></property>
<property name="serializerFeatures">
<list>
<value>WriteNullListAsEmpty</value>
</list>
</property>
</bean>
<!--fastjson支持配置结束 -->
<!--放行静态资源 -->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--配置扫描包 -->
<context:component-scan base-package="com.cs.qsx.controller"></context:component-scan>
<!--视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件大小上限,单位为字节(10MB) -->
<property name="maxUploadSize">
<value>10485760</value>
</property>
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
</bean>
</beans>
项目配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<!--配置Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<!--配置springmvc -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置过滤器,解决post请求乱码 -->
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Maven依赖
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cs.qsx</groupId>
<artifactId>SSH_Msg</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SSH_Msg Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.11.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
</dependencies>
<build>
<finalName>SSH_Msg</finalName>
<!--提高编译级别 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
页面
leaveMessage.jsp
<%--
Created by IntelliJ IDEA.
User: 17535
Date: 2017/10/11
Time: 8:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>留言板</title>
<link href="/css/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/flat-ui.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script src="/js/flat-ui.min.js"></script>
<script type="text/javascript">
function getMsg() {
var url = "${pageContext.request.contextPath}/api/msg";
$.ajax({
url:url,
type:"post",
dataType:"json",
success:function (result) {
var html1 = "<thead><tr><th>留言内容</th><th>留言人</th><th>留言时间</th></tr></thead>";
var innHtml = "";
for (var i=0;i<result.length;i++){
var jsonObject = result[i];
innHtml = innHtml + "<tr><td>"+jsonObject.context+"</td><td>"+jsonObject.name+"</td><td>"+jsonObject.createDate+"</td></tr>";
}
$("#msgtable").html(html1 + innHtml);
},
error:function () {
alert("请求失败");
}
});
}
</script>
</head>
<body onload="getMsg()">
<div class="main">
<h2>请输入留言</h2>
<div class="addMsg">
<form action="/addMsg" method="post" class="navbar-form navbar-left">
<div class="form-group">
<input class="form-control" type="text" name="context" placeholder="请输入留言" />
<input class="form-control" type="text" name="name" placeholder="请输入姓名" />
<button class="btn btn-primary btn-small" type="submit">留言</button>
<button class="btn btn-warning btn-small" type="reset">清空</button>
</div>
</form>
</div>
<div class="show">
<table class="table table-bordered table-hover" id="msgtable">
</table>
</div>
</div>
</body>
</html>
业务逻辑层(接口)
MsgService.class
package com.cs.qsx.service;
import com.cs.qsx.domain.Msg;
import java.util.List;
public interface MsgService {
//查询
public List<Msg> findAll();
//新增
public void addMsg(Msg msg);
}
业务逻辑层(实现类)
MsgServiceImpl.class
package com.cs.qsx.service.impl;
import com.cs.qsx.dao.MsgDao;
import com.cs.qsx.domain.Msg;
import com.cs.qsx.service.MsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MsgServiceImpl implements MsgService {
@Autowired
private MsgDao msgDao;
@Override
public List<Msg> findAll() {
return msgDao.queryAll();
}
@Override
public void addMsg(Msg msg) {
msgDao.insertMsg(msg);
}
}
数据持久层(接口)
MsgDao.class
package com.cs.qsx.dao;
import com.cs.qsx.domain.Msg;
import java.util.List;
public interface MsgDao {
//查询
public List<Msg> queryAll();
//新增
public void insertMsg(Msg msg);
}
数据持久层(实现类)
MsgDaoImpl.class
package com.cs.qsx.dao.impl;
import com.cs.qsx.dao.MsgDao;
import com.cs.qsx.domain.Msg;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Repository("msgDao")
public class MsgDaoImpl extends HibernateDaoSupport implements MsgDao {
@Autowired
private SessionFactory sessionFactory;
@PostConstruct
protected void injectSessionFactory() {
super.setSessionFactory(sessionFactory);
}
@Override
public List<Msg> queryAll() {
return (List<Msg>) getHibernateTemplate().find("from Msg");
}
@Override
public void insertMsg(Msg msg) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = simpleDateFormat.parse(simpleDateFormat.format(new Date()));
} catch (ParseException e) {
e.printStackTrace();
}
msg.setCreateDate(date);
getHibernateTemplate().save(msg);
}
}
控制器
MsgController.class
package com.cs.qsx.controller;
import com.cs.qsx.domain.Msg;
import com.cs.qsx.service.MsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Controller
public class MsgController {
@Autowired
private MsgService msgService;
@RequestMapping("/msg")
public String showMsg() {
return "leaveMessage";
}
@ResponseBody
@RequestMapping("/api/msg")
public List<Msg> msgapi(HttpServletResponse response) {
List<Msg> msgs = msgService.findAll();
return msgs;
}
@RequestMapping("/addMsg")
public String addMsg(Msg msg){
msgService.addMsg(msg);
return "leaveMessage";
}
}
过滤器
HibernateFlushFilter.class
package com.cs.qsx.filter;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate5.support.OpenSessionInViewFilter;
import javax.persistence.FlushModeType;
import javax.servlet.annotation.WebFilter;
/**
* Servlet Filter implementation class HibernateFlushFilter
* 为了解决Spring二次修改Hibernate的FlushMode
*
*/
@WebFilter("/*")
public class HibernateFlushFilter extends OpenSessionInViewFilter {
@Override
protected Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
// TODO Auto-generated method stub
Session session=sessionFactory.openSession();
session.setFlushMode(FlushModeType.AUTO);
return session;
}
}
字符过滤器
EncodingFilter.class
package com.cs.qsx.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
@WebFilter(filterName = "EncodeFilter", urlPatterns = "/*")
public class EncodeFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//获取请求
HttpServletRequest request = (HttpServletRequest) req;
HttpServletRequest myRequest = new MyRequest(request);
//处理响应乱码
resp.setContentType("text/html;charset=utf-8");
//放行
chain.doFilter(myRequest,resp);
}
//自定义一个请求
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
private boolean hasEncode = false;
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public String getParameter(String s) {
//通过自己定义的已经处理过字符编码问题的方法获取map
Map<String,String[]> parameterMap = getParameterMap();
//根据map获取值,值是数组
String[] values = parameterMap.get(s);
if (values == null){
return null;
}
//取一个值,这个值就是数组的第0个元素
return values[0];
}
@Override
public String[] getParameterValues(String s) {
Map<String,String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(s);
return values;
}
//重写getParmeterMap方法,在内部把map中的中文乱码处理掉
@Override
public Map<String, String[]> getParameterMap() {
//处理中文乱码,区别对待get和post
String method = request.getMethod();
if ("post".equalsIgnoreCase(method)) {
//处理post乱码
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if ("get".equalsIgnoreCase(method)) {
//处理get乱码
Map<String, String[]> parameterMap = request.getParameterMap();
//对于每一个内容都要重新编码再解码
/*
说明:tomcat8之前的版本,默认编码格式是iso-8859-1
在8之后,就是utf-8了,所以只需要对Tomcat8之前的版本进行处理即可
*/
String servletInfo = request.getServletContext().getServerInfo();
if (!hasEncode) {
if (servletInfo.substring(servletInfo.lastIndexOf(File.separator) + 1).charAt(0) < 56) {
for (String parameterName : parameterMap.keySet()) {
//根据键拿到值,这个值并不确定是几个值
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
values[i] = new String(values[i].getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
}
return parameterMap;
}
return super.getParameterMap();
}
}
public void init(FilterConfig config) throws ServletException {
}
}
附:
Flat UI 官网:
Flat UI 官网
效果图:
GitHub源码地址:
SSH小例子
成功的路上,总有坎坷,走过去,迎接你的将是—下一个坎坷.
2017/10/11
Slicenfer