SSM框架整合-实现CRUD,登录和分页操作
一.项目git地址:https://github.com/807028059/Test-User
二.项目结构:spring+springmvc+mybatis+maven+mysql+freemark+jetty
三.项目介绍:主要实现登录 crud以及分页效果
1.登录界面
2.主页
3.添加页面
4.编辑页面
四.搭建
1)准备配置文件
jar包依赖 这里推荐一个插件 mavenHelper.jar 可以自动检测jar包的冲突依赖关系
<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.zj</groupId>
<artifactId>Test-User</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>
<!-- 定义spring的版本变量在dependency里面直接引用 -->
<spring.version>4.3.2.RELEASE</spring.version>
<slf4j.version>1.7.2</slf4j.version>
</properties>
<dependencies>
<!-- spring web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web开发要有servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<!-- spring 测试 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 单元测试 -->
<!-- <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- spring jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring事物 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- aspectj切面编程的jar -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!-- tomcat 连接池 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>7.0.42</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- 添加mybatis与Spring整合的核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- mysql 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- 日志打印相关的jar -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- mybatis分页插件 -->
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>1.2.17</version>
<exclusions>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Template Language -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.21</version>
</dependency>
<!-- Java utility类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<!-- fastjson配置 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
<!--GSON-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<!--kaptcha-->
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
<!--spring session-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
</dependency>
<!-- <dependency>
<groupId>com.alibaba</groupId>
<artifactId>sms-dayu</artifactId>
<version>1.0</version>
</dependency>-->
</dependencies>
<build>
<finalName>Test-User</finalName>
<!-- 资源文件的设置 -->
<plugins>
<!-- compiler plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
<compilerArguments>
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.1.v20140609</version>
<configuration>
<!--<webAppSourceDirectory>WebContent</webAppSourceDirectory>-->
<!--<scanIntervalSeconds>3</scanIntervalSeconds>-->
<!--<contextXml>src/main/resources/jetty-contexts.xml</contextXml>-->
<webAppConfig>
<!--<contextPath>/crm</contextPath>-->
<!-- 此处指定默认Jetty Web配置文件
<defaultsDescriptor>src/main/resources/webdefault.xml</defaultsDescriptor> -->
</webAppConfig>
</configuration>
</plugin>
</plugins>
</build>
</project>
准备spring-mybatis.xml spring集成对数据库的配置
<?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: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-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 自动扫描 -->
<context:component-scan base-package="com.zj" />
<!-- 引入配置文件 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="poolProperties">
<bean class="org.apache.tomcat.jdbc.pool.PoolProperties">
<property name="driverClassName" value="${JDBC.driver}"/>
<property name="url" value="${JDBC.url}"/>
<property name="username" value="${JDBC.username}"/>
<property name="password" value="${JDBC.password}"/>
<property name="jmxEnabled" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="false"/>
<property name="validationInterval" value="30000"/>
<property name="validationQuery" value="SELECT 1"/>
<property name="timeBetweenEvictionRunsMillis" value="30000"/>
<property name="maxActive" value="200"/>
<property name="initialSize" value="10"/>
<property name="maxWait" value="30000"/>
<property name="minEvictableIdleTimeMillis" value="30000"/>
<property name="minIdle" value="10"/>
<property name="logAbandoned" value="false"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="jdbcInterceptors" value="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"/>
</bean>
</property>
</bean>
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<!-- 配置sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- mybatis配置文件的路径 -->
<property name="configLocation" value="classpath:mybatis.xml" />
<!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描/mapper/下所有以xml结尾的文件-->
<property name="mapperLocations" value="classpath:/mapper/*.xml" />
</bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zj.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 设置事物增强 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="add*" rollback-for="Exception"/>
<tx:method name="insert*" rollback-for="Exception" />
<tx:method name="update*" rollback-for="Exception" />
<tx:method name="delete*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<!-- 配置扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描com.shsxt.crm.dao这个包以及它的子包下的所有映射接口类 -->
<property name="basePackage" value="com.zj.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
</beans>
准备spring-mvc.xml 配置视图 aop
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd ">
<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="com.zj.controller" />
<mvc:annotation-driven />
<!-- 静态资源文件的处理-->
<mvc:default-servlet-handler />
<!-- 启用@Aspect注解 -->
<aop:aspectj-autoproxy />
<!-- 视图配置 -->
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer" >
<property name="templateLoaderPath" value="/WEB-INF/views/" />
<property name="defaultEncoding" value="UTF-8" />
<property name="freemarkerSettings">
<props>
<prop key="number_format">0.##########</prop> <!--解决数字问题-->
<prop key="boolean_format">true,false</prop> <!--解决页面布尔值的输出-->
<prop key="tag_syntax">square_bracket</prop> <!-- auto_detect:自动选择(选择第一种标签语法) angle_bracket(<#if>) square_bracket[#if]-->
<prop key="classic_compatible">true</prop> <!--非空不会报错-->
<prop key="template_update_delay">0</prop> <!--缓存时间-->
<prop key="default_encoding">UTF-8</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="time_format">HH:mm:ss</prop>
</props>
</property>
<property name="freemarkerVariables">
<map>
<entry key="student_list" value-ref="studentDirective" />
</map>
</property>
</bean>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="prefix" value="" />
<property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=UTF-8"/>
</bean>
<!-- 文本转化 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
准备mybatis.xml 配置实体层和分页插件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 通过别名简化对类的使用 -->
<typeAliases>
<!-- 通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean, 并且默认设置一个别名,默认的名字为非限定类名来作为它的别名。 -->
<package name="com.zj.model" />
</typeAliases>
<plugins>
<!-- 分页插件配置 -->
<plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
<property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect"/>
</plugin>
</plugins>
</configuration>
准备log4j.porperties
<span style="color:#666666;"># Global logging configuration
log4j.rootLogger=INFO,stdout,file
# MyBatis logging configuration...
log4j.logger.com.sdrd.mapper=DEBUG
#log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] %c{1}:%L - %m%n
### direct messages to file file.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.file.Threshold = INFO
log4j.appender.file.append=true
log4j.appender.file.File=./logs/info.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss} %5p %c{1}:%L - %m%n
jdbc.porperties配置文件
JDBC.username=root
JDBC.password=root
JDBC.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
JDBC.driver=com.mysql.jdbc.Driver
这些文件都是放在resource下
web.xml配置 web项目的入口 配置扫描以上文件产生联动
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<!-- Spring和mybatis的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<!-- 编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 防止Spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
2)准备实体类
因为要进行分页操作先定义一个BaseDto
package com.zj.model;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.commons.lang3.StringUtils;
public class BaseDto {
private Integer page;
private Integer pageSize;
private String sort;
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public PageBounds buildPageBounds(){
if(this.page == null||this.page<1){
this.page = 1;
}
if(this.pageSize==null||this.pageSize<1){
this.pageSize = 2;
}
PageBounds pageBounds = new PageBounds(this.page,this.pageSize);
if (StringUtils.isNotBlank(this.sort)) {
pageBounds.setOrders(Order.formString(this.sort));
}
return pageBounds;
}
}
接着定义User类和Student类
package com.zj.model;
import java.io.Serializable;
public class User implements Serializable{
private Integer userId;
private String userName;
private String userPassword;
private Integer uid;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userPassword='" + userPassword + '\'' +
", uid=" + uid +
'}';
}
}
package com.zj.model;
public class Student extends BaseDto{
private Integer id;
private String name;
private Integer gender;
private Integer age;
private Integer uid;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
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 Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", gender=" + gender +
", age=" + age +
", uid=" + uid +
'}';
}
}
建完以后大家是不是发现有个IsLogin的注解类 这个注解是用来进行登录验证的 想想看 进行crud的时候是不是要登录以后才能进行 那我们利用aop和注解实现这么一个功能 在crud的方法上加上这个标签就可以实现这个功能是不是就很简单 开始
定义一个注解的名字
package com.zj.model;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsLogin {
}
然后给这个注解加上功能
package com.zj.proxy;
import com.zj.exception.LoginException;
import com.zj.model.IsLogin;
import com.zj.model.User;
import javafx.fxml.LoadException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
@Component
@Aspect
public class LoginProxy {
@Autowired
private HttpSession session;
@Pointcut(value = "@annotation(com.zj.model.IsLogin)")
private void pointcut(){
}
@Before(value="pointcut()")
public void beforeMethod(JoinPoint joinPoint){
User user = (User) session.getAttribute("user");
System.out.println("-------进行登录验证-------");
if(user == null){
throw new LoginException("请先登录");
}
}
}
接着来 定义一个结果类 什么操作都要有个结果 对吧 这样前台才好判断是不是执行成功或者失败 对吧
package com.zj.result;
public class ResultInfo {
String mes;
int code;
public ResultInfo(){
}
public ResultInfo(String mes){
this.mes = mes;
}
public String getMes() {
return mes;
}
public void setMes(String mes) {
this.mes = mes;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
2)准备工具类和异常类
package com.zj.exception;
import com.alibaba.fastjson.JSON;
import com.zj.controller.BaseController;
import com.zj.result.ResultInfo;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@ControllerAdvice
public class GlobalExceptionHandler extends BaseController {
@ExceptionHandler(value = LoginException.class)
public String handlerParamException(LoginException loginException, HttpServletRequest request,
HttpServletResponse response,Model model){
model.addAttribute("proPath", request.getContextPath());
String xmlHttpRequest = request.getHeader("X-Requested-With");
return "login";
}
}
package com.zj.exception;
public class LoginException extends RuntimeException {
private int errCode;
public int getErrCode() {
return errCode;
}
public void setErrCode(int errCode) {
this.errCode = errCode;
}
public LoginException(){
}
public LoginException(String mes) {
super(mes);
}
}
package com.zj.exception;
public class ParameterException extends RuntimeException {
public ParameterException(){
}
public ParameterException(String mes){
super(mes);
}
}
package com.zj.util;
import com.zj.exception.ParameterException;
public class AssertUtil {
public static void isNull(Object value){
if(value == null){
throw new ParameterException("不能空");
}
}
}
3)准备dao,service和controller的编写
再来写用户登陆的Dao层和对学生操作的Dao层
package com.zj.dao;
import com.zj.model.User;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserDao {
@Select("select * from usertable where userName =#{userName} and userPassword =#{userPassword}")
public User login(User user);
/*测试*/
List<User> test();
}
package com.zj.dao;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.zj.model.Student;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentDao {
@Select("select a.* from student a,usertable b where a.uid=b.uid and limit #{limit}")
PageList<Student> findListStudent(@Param(value = "limit") Integer limit);
@Select("select * from student ")
PageList<Student> findStudent(PageBounds pageBounds);
@Select("select a.* from student a,usertable b where a.uid=b.uid and a.id=#{id}")
Student findStudentById(@Param(value = "id") Integer id);
@Update({"insert student(name,gender,age,uid) values(#{name},#{gender},#{age},#{uid})"})
void addStudent(Student student);
@Update({"UPDATE student set name=#{name},gender=#{gender},age=#{age} where id = #{id} and uid=#{uid}"})
void updateStudent(Student student);
@Delete("delete from student where id=#{id} and uid=#{uid}")
void deleteStudent(@Param(value = "id") Integer id,@Param(value = "uid") Integer uid);
}
接着来service层
package com.zj.service;
import com.zj.dao.UserDao;
import com.zj.model.User;
import com.zj.util.RedisUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService{
@Autowired
private UserDao userDao;
private Logger log = Logger.getLogger(UserService.class);
RedisUtil r = new RedisUtil();
public User login(User user,String id) {
log.info("用户登录:"+user);
return userDao.login(user);
}
}
package com.zj.service;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.zj.dao.StudentDao;
import com.zj.model.Student;
import com.zj.result.ResultInfo;
import com.zj.util.AssertUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentService {
@Autowired
private StudentDao studentDao;
private static Logger log = Logger.getLogger(StudentService.class);
public ResultInfo addStudent(Integer uid,Student student){
ResultInfo resultInfo = new ResultInfo();
log.info("addStudent入参:"+resultInfo);
if(student!=null){
student.setUid(uid);
studentDao.addStudent(student);
resultInfo.setCode(200);
resultInfo.setMes("添加成功");
return resultInfo;
}
resultInfo.setCode(300);
resultInfo.setMes("添加失败");
return resultInfo;
}
public ResultInfo updateStudent(Student student,Integer uid){
ResultInfo resultInfo = new ResultInfo();
log.info("updateStudent入参:"+student.toString());
if(student!=null){
student.setUid(uid);
studentDao.updateStudent(student);
resultInfo.setCode(200);
resultInfo.setMes("添加成功");
return resultInfo;
}
resultInfo.setCode(300);
resultInfo.setMes("添加失败");
return resultInfo;
}
public void deleteStudent(Integer id,Integer uid){
AssertUtil.isNull(id);
studentDao.deleteStudent(id,uid);
log.info("deleteStudents删除ID:"+id);
}
public Student findStudentById(Integer id,Integer uid){
AssertUtil.isNull(id);
log.info("findStudentById寻找ID:"+id);
return studentDao.findStudentById(id);
}
public PageList<Student> findListStudent(Integer limit){
PageList<Student> students = studentDao.findListStudent(limit);
return students;
}
public PageList<Student> findStudent(Student student){
PageList<Student> students = studentDao.findStudent(student.buildPageBounds());
return students;
}
}
再来controller层
首先来个BaseController 存储项目路径(tomcat启动的有用)
package com.zj.controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import javax.servlet.http.HttpServletRequest;
public class BaseController {
@ModelAttribute
protected void preMethod(HttpServletRequest request, Model model) {
String ctx = request.getContextPath();
System.out.println("ctx------------->"+ctx);
model.addAttribute("proPath",ctx);
}
}
接着用户和学生的controller层
package com.zj.controller;
import com.zj.model.User;
import com.zj.result.ResultInfo;
import com.zj.service.UserService;
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.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@Controller
@RequestMapping("user")
public class UserController extends BaseController{
@Autowired
private UserService userService;
/*
* 登录操作
* */
@RequestMapping("login")
@ResponseBody
public ResultInfo login(User user, HttpServletRequest request, HttpSession session){
ResultInfo resultInfo = new ResultInfo();
String id = request.getSession().getId();
User acc= userService.login(user,id);
System.out.println("sessioid---------------->"+id);
if(acc!=null){
//存session
session.setAttribute("user", acc);
resultInfo.setCode(200);
resultInfo.setMes("登陆成功");
return resultInfo;
}
resultInfo.setCode(300);
resultInfo.setMes("登录失败");
return resultInfo;
}
/*
* 跳转主页
* */
@RequestMapping("index")
public String index(HttpServletRequest request, HttpSession session){
User user = (User)session.getAttribute("user");
if(user!=null){
return "redirect:/student/main";
}
return "login";
}
/*
* 登出操作
* */
@RequestMapping("out")
public String out(HttpSession session){
session.removeAttribute("user");
return "login";
}
/*
* 生成验证码
* */
@RequestMapping("yzm")
public void sendYzm(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 图片高度
final int IMG_HEIGHT = 100;
// 图片宽度
final int IMG_WIDTH = 25;
// 验证码长度
final int CODE_LEN = 4;
// 用于绘制图片,设置图片的长宽和图片类型(RGB)
BufferedImage bi = new BufferedImage(IMG_HEIGHT, IMG_WIDTH, BufferedImage.TYPE_INT_RGB);
// 获取绘图工具
Graphics graphics = bi.getGraphics();
graphics.setColor(new Color(100, 230, 200)); // 使用RGB设置背景颜色
graphics.fillRect(0, 0, 100, 30); // 填充矩形区域
// 验证码中所使用到的字符
char[] codeChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456".toCharArray();
String captcha = ""; // 存放生成的验证码
Random random = new Random();
for(int i = 0; i < CODE_LEN; i++) { // 循环将每个验证码字符绘制到图片上
int index = random.nextInt(codeChar.length);
// 随机生成验证码颜色
graphics.setColor(new Color(random.nextInt(150), random.nextInt(200), random.nextInt(255)));
// 将一个字符绘制到图片上,并制定位置(设置x,y坐标)
graphics.drawString(codeChar[index] + "", (i * 20) + 15, 20);
captcha += codeChar[index];
}
// 将生成的验证码code放入sessoin中
request.getSession().setAttribute("code", captcha);
// 通过ImageIO将图片输出
ImageIO.write(bi, "JPG", response.getOutputStream());
}
/*
* 验证码校验
* */
@RequestMapping("check")
@ResponseBody
public ResultInfo checkYzm(HttpServletRequest request, HttpServletResponse response){
ResultInfo resultInfo = new ResultInfo();
// 获取存放在session中的验证码
String code = (String) request.getSession().getAttribute("code");
// 获取页面提交的验证码
String inputCode = request.getParameter("code");
if(code.toLowerCase().equals(inputCode.toLowerCase())) { // 验证码不区分大小写
// 验证成功,跳转到成功页面
resultInfo.setCode(200);
} else { // 验证失败
resultInfo.setCode(300);
resultInfo.setMes("验证码错误");
}
return resultInfo;
}
}
package com.zj.controller;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.zj.model.IsLogin;
import com.zj.model.Student;
import com.zj.model.User;
import com.zj.result.ResultInfo;
import com.zj.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("student")
public class StudentController extends BaseController{
@Autowired
private StudentService studentService;
/*
* 添加操作
* */
@RequestMapping("add")
@ResponseBody
@IsLogin
public ResultInfo addStudent(HttpServletRequest request,Student student){
HttpSession session = request.getSession();
User user = (User)session.getAttribute("user");
int uid = user.getUid();
return studentService.addStudent(uid,student);
}
/*
* 跳转添加视图
* */
@RequestMapping("addView")
@IsLogin
public String addView(){
return "addView";
}
/*
* 跳转主页
* */
@RequestMapping("main")
@IsLogin
public String findListStudent(Student student, Model model){
PageList<Student> students = studentService.findStudent(student);
model.addAttribute("students",students);
model.addAttribute("pagenator",students.getPaginator());
model.addAttribute("student",student);
return "main";
}
/*
* 删除操作
* */
@RequestMapping("delete/{id}")
@IsLogin
public String deleteStudent(@PathVariable Integer id,@PathVariable Integer uid){
studentService.deleteStudent(id,uid);
return "redirect:/student/main";
}
/*
* 跳转编辑页面
* */
@RequestMapping("updateView/{id}")
@IsLogin
public String updateView(@PathVariable Integer id,Model model,HttpSession session){
User user = (User) session.getAttribute("user");
Student student = studentService.findStudentById(id,user.getUid());
model.addAttribute("student",student);
return "update";
}
/*
* 编辑操作
* */
@RequestMapping("update")
@ResponseBody
public ResultInfo updateStudent(Student student, HttpServletRequest request, HttpSession session){
User user = (User) session.getAttribute("user");
/*if(user == null){
ResultInfo resultInfo = new ResultInfo();
resultInfo.setCode(300);
resultInfo.setMes("请先登录");
return resultInfo;
}*/
return studentService.updateStudent(student,user.getUid());
}
}
其实我这不规范 对逻辑的处理都应该放在service层的 懒得改了… 有兴趣的同学自行修改
因为前台使用的freemark所以 页面的展示数据我通过TemplateDirectiveModel实现
package com.zj.directive;
import com.alibaba.fastjson.JSON;
import freemarker.core.Environment;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.BeansWrapperBuilder;
import freemarker.template.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public abstract class BaseDirective implements TemplateDirectiveModel{
//获取参数值
public <T> T getParameter(String paramName,Map params,Class<?> clazz)
throws TemplateException{
BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
//获取参数
TemplateModel templateModel = (TemplateModel) params.get(paramName);
T value = (T) beansWrapper.unwrap(templateModel, clazz);
return value;
}
//输出
public void setVariable(Environment env, TemplateDirectiveBody body,String key,Object value)
throws TemplateException,IOException{
BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
TemplateModel templateModel = beansWrapper.wrap(value);
env.setVariable(key, templateModel);
// 输出
if (body != null) {
body.render(env.getOut());
} else {
env.getOut().write(JSON.toJSONString(value));
}
}
}
package com.zj.directive;
import com.alibaba.fastjson.JSON;
import com.zj.model.Student;
import com.zj.model.User;
import com.zj.service.StudentService;
import com.zj.service.UserService;
import freemarker.core.Environment;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.BeansWrapperBuilder;
import freemarker.template.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@Component
public class StudentDirective extends BaseDirective{
@Autowired
private StudentService studentService;
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
Integer limit = getParameter("limit", params, Integer.class);
List<Student> students = studentService.findListStudent(limit);
setVariable(env,body,"students",students);
}
}
4)全部完成后 进行前台页面的编写
登录页
<html>
<head>
<title>Login page</title>
<script src="${proPath}/statics/js/jquery-1.11.3.js"></script>
<script src="${proPath}/statics/js/jquery.js"></script>
<script type="text/javascript">
function flushCode() {
// 每次刷新的时候获取当前时间,防止浏览器缓存刷新失败
var time = new Date();
document.getElementById("scode").src = "${proPath}/user/yzm?time=" + time;
}
function check() {
var userName = $("#name").val();
var password = $("#password").val();
if(userName == ""){
alert("用户名不能为空");
return;
}
if(password == ""){
alert("密码不能为空");
return;
}
$.ajax({
url:'${proPath}/user/check',
data:{
code:$("#yzm").val()
},
type:'post',
dataType:'json',
success:function (data) {
if(data.code==200){
$.ajax({
url:'${proPath}/user/login',
data:{
userName:userName,
userPassword:password
},
type:'post',
dataType:'json',
success:function (data) {
if(data.code == 200){
window.location.href="${proPath}/student/main";
}else{
alert(data.mes);
}
}
})
}else{
alert(data.mes);
}
}
})
}
</script>
</head>
<body>
<div id="loginDiv">
<div style="position:absolute;width:500px;height:200px;top:200px;left:550px">
<table border="">
<tr>
<td>
<label for="name">账号:</label>
</td>
<td>
<input type="text" id="name" name="userName" />
</td>
</tr>
<tr>
<td>
<label for="password">密码:</label>
</td>
<td>
<input type="text" id="password" name="userPassword" />
</td>
</tr>
<tr>
<td>
<label for="yzm">验证码:</label>
</td>
<td>
<input type="text" id="yzm" name="userYzm" />
<img alt="验证码" id="scode" src="${proPath}/user/yzm" >
<a href="#" onclick="javascript:flushCode();">看不清?</a>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button type="button" onclick="check()">登录</button>
</td>
</tr>
</table>
</div>
<div style="color:red">${requestScope.msg}</div>
</div>
</body>
</html>
主页
<html xmlns="http://www.w3.org/1999/html">
<head>
<title>Main</title>
<script src="${proPath}/statics/js/jquery.js" type=text/javascript></script>
<script type="text/javascript">
$(function () {
$.pageSkip = function(pageNumber) {
$("#pageNumber").val(pageNumber);
$("#student").submit();
return false;
}
})
</script>
</head>
<body>
<div style="position:absolute;width:500px;height:200px;top:200px;left:550px">
<form id="student" action="${proPath}/student/main" method="post">
<input type="hidden" id="pageNumber" name="page" value="${student.page}" />
<input type="hidden" id="pageSize" name="pageSize" value="${student.pageSize}" />
<table border="">
<tr>
<td>编号</td>
<td>姓名</td>
<td>级别</td>
<td>年龄</td>
<td>操作</td>
</tr>
[#if students?has_content]
[#list students as student]
<tr>
<td>${student.id}</td>
<td>${student.name}</td>
<td>${student.gender}</td>
<td>${student.age}</td>
<td>
[#--<a href="${proPath}/student/buyView/${student.id}">购买</a>|--]
<a href="${proPath}/student/updateView/${student.id}">编辑</a>|
<a href="${proPath}/student/delete/${student.id}">删除</a>
</td>
</tr>
[/#list]
[#else]
<tr align="center">
<td colspan="5">无数据...</td>
</tr>
[/#if]
<tr align="center">
<td colspan="5">
[#if pagenator.totalPages>1]
[#if pagenator.isFirstPage()]
[#else]
<a href="javascript: $.pageSkip(1);" class="">首页</a>
[/#if]
[#if pagenator.hasPrePage]
<a href="javascript: $.pageSkip(${pagenator.prePage});" class="previousPage">上一页</a>
[#else]
<span class="previousPage"> </span>
[/#if]
[#list pagenator.slider(3) as slider ]
[#if slider==pagenator.page ]
<span class="currentPage">${slider}</span>
[#else]
<a href="javascript: $.pageSkip(${slider});">${slider}</a>
[/#if]
[/#list]
[#if pagenator.hasNextPage]
<a href="javascript: $.pageSkip(${pagenator.nextPage});" class="nextPage">下一页</a>
[#else]
<span class="nextPage"> </span>
[/#if]
[#if pagenator.isLastPage()]
<span class="lastPage" > </span>
[#else]
<a href="javascript: $.pageSkip(${pagenator.totalPages});" class="lastPage">末页</a>
[/#if]
[/#if]
</td>
</tr>
<tr align="center" >
<td colspan="5">
<a href="${proPath}/student/addView">添加</a>
<a href="${proPath}/user/out">退出</a>
</td>
</tr>
</table>
</form
</div>
</body>
</html>
添加页
<html>
<head>
<title>Main</title>
<script src="${proPath}/statics/js/jquery.js" type=text/javascript></script>
<script type="text/javascript">
$(function(){
$("#back").click(function () {
window.location.href="main";
})
$("#add").click(function () {
var name = $("#name").val();
var gender = $("#gender").val();
var age = $("#age").val();
if(name!=""&&gender!=""&&age!=""){
$.ajax({
type:'post',
url:'${proPath}/student/add',
data:$('#form').serialize(),
dataType:'json',
success:function (data) {
console.log('...');
if(data.code==200){
console.log(data.mes);
window.location.href="main";
}else{
console.log(data.mes);
}
}
})
}else{
alert("请填写完整...");
}
})
})
</script>
</head>
<body>
<div style="position:absolute;width:500px;height:200px;top:200px;left:550px">
<form id="form" method="post" >
<table border="">
<tr>
<td>姓名</td>
<td><input id="name" type="text" name="name"/></td>
</tr>
<tr>
<td>级别</td>
<td><input id="gender" type="text" name="gender"/></td>
</tr>
<tr>
<td>年龄</td>
<td><input id="age" type="text" name="age"/></td>
</tr>
<tr align="center">
<td colspan="4">
<button type="button" id="add">添加</button>
<button type="button" id="back">返回</button>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
编辑页
<html>
<head>
<title>Main</title>
<script src="${proPath}/statics/js/jquery.js" type=text/javascript></script>
<script type="text/javascript">
$(function(){
$("#back").click(function () {
window.location.href="${proPath}/student/main";
})
$("#update").click(function () {
var name = $("#name").val();
var gender = $("#gender").val();
var age = $("#age").val();
if(name!=""&&gender!=""&&age!=""){
$.ajax({
type:'post',
url:'${proPath}/student/update',
data:$('#form').serialize(),
dataType:'json',
success:function (data) {
console.log('...');
if(data.code==200){
console.log(data.mes);
window.location.href="${proPath}/student/main";
}else{
window.location.href="${proPath}/user/index";
}
}
})
}else{
alert("请填写完整...");
}
})
})
</script>
</head>
<body>
<div style="position:absolute;width:500px;height:200px;top:200px;left:550px">
<form id="form" method="post" >
<input type="hidden" id="id" name="id" value="${student.id}" />
<table border="">
<tr>
<td>姓名</td>
<td><input id="name" type="text" name="name" value="${student.name}"/></td>
</tr>
<tr>
<td>级别</td>
<td><input id="gender" type="text" name="gender" value="${student.gender}"/></td>
</tr>
<tr>
<td>年龄</td>
<td><input id="age" type="text" name="age" value="${student.age}"/></td>
</tr>
<tr align="center">
<td colspan="4">
<button type="button" id="update">修改</button>
<button type="button" id="back">返回</button>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
五.数据库的表新建
用的mysql 两张表
CREATE TABLE `usertable` (
`userId` int(11) DEFAULT NULL,
`userName` varchar(255) DEFAULT NULL,
`userPassword` varchar(255) DEFAULT NULL,
`uid` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8CREATE TABLE `student` (
`id` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`gender` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`uid` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
六.完成
以上搭建完成后 最后配置jetty运行
七.结语
写的比较粗糙 大致介绍了ssm框架的基本操作 关于ssm结合xml进行sql编写的配置请看
https://blog.csdn.net/weixin_41634885/article/details/82022187
有问题留言
还没有评论,来说两句吧...