一.项目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=utf8
CREATE 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
有问题留言