web中hasmoreelements_Web开发模式【Mode I 和Mode II的介绍、应用案例】

开发模式的介绍

在Web开发模式中,有两个主要的开发结构,称为模式一(Mode I)和模式二(Mode II).

首先我们来理清一些概念吧:DAO(Data Access Object):主要对数据的操作,增加、修改、删除等原子性操作。

Web层:界面+控制器,也就是说JSP【界面】+Servlet【控制器】

Service业务层:将多个原子性的DAO操作进行组合,组合成一个完整的业务逻辑

控制层:主要使用Servlet进行控制

数据访问层:使用DAO、Hibernate、JDBC技术实现对数据的增删改查

JavaBean用于封装数据,处理部分核心逻辑,每一层中都用到!

模式一

模式一指的就是在开发中将显示层、控制层、数据层的操作统一交给JSP或者JavaBean来进行处理!

模式一有两种情况:完全使用JSP做开发优点:

缺点:程序的可读性差、复用性低、代码复杂!什么jsp代码、html代码都往上面写,这肯定很难阅读,很难重用!开发速度贼快,只要写JSP就行了,JavaBean和Servlet都不用设计!

小幅度修改代码方便,直接修改JSP页面交给WEB容器就行了,不像Servlet还要编译成.class文件再交给服务器!【当然了,在ide下开发这个也不算是事】

使用JSP+JavaBean做开发优点:

缺点:没有流程控制,程序中的JSP页面都需要检查请求的参数是否正确,异常发生时的处理。显示操作和业务逻辑代码工作会紧密耦合在一起的!日后维护会困难程序的可读性较高,大部分的代码都写在JavaBean上,不会和HTML代码混合在一起,可读性还行的。

可重复利用高,核心的代码都由JavaBean开发了,JavaBean的设计就是用来重用、封装,大大减少编写重复代码的工作!

应用例子:

我们使用JavaBean+JSP开发一个简易的计算器吧,效果如图下:

de4beedecc7d73654104c22420ec72b8.png

c05240e45becb8978e1945bf5470c553.png首先开发JavaBean对象public class Calculator {

private double firstNum;

private double secondNum;

private char Operator = '+';

private double result;

//JavaBean提供了计算的功能

public void calculate() {

switch (this.Operator) {

case '+':

this.result = this.firstNum + this.secondNum;

break;

case '-':

this.result = this.firstNum - this.secondNum;

break;

case '*':

this.result = this.firstNum * this.secondNum;

break;

case '/':

if (this.secondNum == 0) {

throw new RuntimeException("除数不能为0");

}

this.result = this.firstNum / this.secondNum;

break;

default:

throw new RuntimeException("传入的字符非法!");

}

}

public double getFirstNum() {

return firstNum;

}

public void setFirstNum(double firstNum) {

this.firstNum = firstNum;

}

public double getSecondNum() {

return secondNum;

}

public void setSecondNum(double secondNum) {

this.secondNum = secondNum;

}

public char getOperator() {

return Operator;

}

public void setOperator(char operator) {

Operator = operator;

}

public double getResult() {

return result;

}

public void setResult(double result) {

this.result = result;

}

}再开发显示页面%--开发用户界面--%>

简单计数器

第一个参数:

运算符

+

-

*

/

第二个参数:效果:

37919b00faeb8339992f75d67e39a73f.png获取得到显示页面提交的参数,调用JavaBean的方法,最后输出结果!calculator.calculate();效果:

c21af20be6b011f723022851949db568.png

开发这个简易的计算器,只用了一个JSP页面和一个JavaBean完成!

总的来说,Mode I 适合小型的开发,复杂程序低的开发,因为Mode I 的特点就是开发速度快,但在进行维护的时候就要付出更大的代价!

模式二

Mode II 中所有的开发都是以Servlet为主体展开的,由Servlet接收所有的客户端请求,然后根据请求调用相对应的JavaBean,并所有的显示结果交给JSP完成!,也就是俗称的MVC设计模式!

6674c9be4aae6f8fc7498647abfb1666.png

MVC设计模式:显示层(View):主要负责接受Servlet传递的内容,调用JavaBean,将内容显示给用户

控制层(Controller):主要负责所有用户的请求参数,判断请求参数是否合法,根据请求的类型调用JavaBean,将最终的处理结果交给显示层显示!

模型层(Mode):模型层包括了业务层,DAO层。

应用例子:

我们使用MVC模式开发一个简单的用户登陆注册的案例吧!作为一个简单的用户登陆注册,这里就直接使用XML文档当作小型数据库吧!

①搭建开发环境导入相对应的开发包

创建程序的包名

创建xml文件,当做小型的数据库

44337f81fda36975bb698bac360ea20c.png

②开发实体Userprivate int id;

private String username;

private String password;

private String email;

private Date birthday;

//....各种setter、getter

③开发dao这个根据业务来开发,我们是登陆注册,那应该提供什么功能呢?注册(外界传递一个User对象进来,我可以在XML文档多一条信息)。登陆(外界传递用户名和密码过来,我就在XML文档中查找有没该用户名和密码,如果有就返回一个User对象)

3.1登陆功能://外界传递用户名和密码进来,我要在XML文档中查找是否有该条记录

public User find(String username, String password) {

//得到XML文档的流对象

InputStream inputStream = UserImplXML.class.getClassLoader().getResourceAsStream("user.xml");

//得到dom4j的解析器对象

SAXReader saxReader = new SAXReader();

try {

//解析XML文档

Document document = saxReader.read(path);

//使用XPATH技术,查找XML文档中是否有传递进来的username和password

Element element = (Element) document.selectSingleNode("//user[@username='" + username + "' and@password='" + password + "']");

if (element == null) {

return null;

}

//如果有,就把XML查出来的节点信息封装到User对象,返回出去

User user = new User();

user.setId(Integer.parseInt(element.attributeValue("id")));

user.setUsername(element.attributeValue("username"));

user.setPassword(element.attributeValue("password"));

user.setEmail(element.attributeValue("email"));

//生日就需要转换一下了,XML文档保存的是字符串,User对象需要的是Date类型

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yy-MM-dd");

Date birthday = simpleDateFormat.parse(element.attributeValue("birthday"));

user.setBirthday(birthday);

//返回User对象出去

return user;

} catch (DocumentException e) {

e.printStackTrace();

throw new RuntimeException("初始化时候出错啦!");

} catch (ParseException e) {

e.printStackTrace();

throw new RuntimeException("查询的时候出错啦!");

}

}做完一个功能,最好就测试一下,看有没有错误再继续往下写!private String username = "zhongfucheng";

private String password = "123";

@Test

public void testLogin() {

UserImplXML userImplXML = new UserImplXML();

User user = userImplXML.find(username, password);

System.out.println(user.getBirthday());

System.out.println(user.getEmail());

System.out.println(user.getId());

System.out.println(user.getUsername());

System.out.println(user.getPassword());

}效果:

07c88f81fab884c36c03f9770fe4731a.png

3.2注册功能//注册功能,外界传递一个User对象进来。我就在XML文档中添加一条信息

public void register(User user) {

//获取XML文档路径!

String path = UserImplXML.class.getClassLoader().getResource("user.xml").getPath();

try {

//获取dom4j的解析器,解析XML文档

SAXReader saxReader = new SAXReader();

Document document = saxReader.read(path);

//在XML文档中创建新的节点

Element newElement = DocumentHelper.createElement("user");

newElement.addAttribute("id", String.valueOf(user.getId()));

newElement.addAttribute("username", user.getUsername());

newElement.addAttribute("email", user.getEmail());

newElement.addAttribute("password", user.getPassword());

//日期返回的是指定格式的日期

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yy-MM-dd");

String date = simpleDateFormat.format(user.getBirthday());

newElement.addAttribute("birthday",date);

//把新创建的节点增加到父节点上

document.getRootElement().add(newElement);

//把XML内容中文档的内容写到硬盘文件上

OutputFormat outputFormat = OutputFormat.createPrettyPrint();

outputFormat.setEncoding("UTF-8");

XMLWriter xmlWriter = new XMLWriter(new FileWriter(path),outputFormat);

xmlWriter.write(document);

xmlWriter.close();

} catch (DocumentException e) {

e.printStackTrace();

throw new RuntimeException("注册的时候出错了!!!");

} catch (IOException e) {

e.printStackTrace();

throw new RuntimeException("注册的时候出错了!!!");

}

}我们也测试一下有没有错误!@Test

public void testRegister() {

UserImplXML userImplXML = new UserImplXML();

//这里我为了测试的方便,就添加一个带5个参数的构造函数了!

User user = new User(10, "nihao", "123", "sina@qq.com", new Date());

userImplXML.register(user);

}注意!测试的结果是在classes目录下的user.xml文件查询的!因为我们是用Test来测试代码,读取XML文件时使用的是类装载器的方法,在编译后,按照WEB的结构目录,XML文件的读写是在WEB-INF的classes目录下的!

36943a6ce10e74b5ae8aacda962cb82e.pngDAO的实现已经开发完成了,接下来我们就对DAO的实现进行抽取。【当然了,也可以先写DAO再写DAO的实现】

f652b60dc91a102f235a77cb6db8c420.png

④开发service层

service层的开发就非常简单了!上面已经说了,service层就是:将多个原子性的DAO操作进行组合,组合成一个完整的业务逻辑。简单来说:对web层提供所有的业务服务的!

在逻辑代码不是非常复杂的情况下,我们可以没有service层的,这里还是演示一下吧!public class UserServiceXML {

//Service层就是调用Dao层的方法,我们就直接在类中创建Dao层的对象了

UserDao userImplXML = new UserImplXML();

public void register(User user) {

userImplXML.register(user);

}

public void login(String username, String password) {

userImplXML.find(username, password);

}

}当然了,为了更好的解耦,也把它抽取成接口!

2d99fa5d2209817b10aae127210f880d.png

⑤开发web层

5.1我们来先做注册的界面吧!提供注册界面的Servletpublic class RegisterUIServlet extends javax.servlet.http.HttpServlet {

protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

//直接跳转到显示注册界面的JSP

request.getRequestDispatcher("/WEB-INF/register.jsp").forward(request, response);

}

protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

this.doPost(request, response);

}

}开发注册界面的JSP欢迎来到注册界面!

用户名

密码

确认密码

邮箱

生日JSP页面是这样子的

8f6c45067ec59b202213ee473ebcd153.png接下来,我们要开发处理用户注册提交的Servlet//首先要接受Parameter的参数,封装到User里面去

String username = request.getParameter("username");

String password = request.getParameter("password");

//......如果参数过多,我们就要写好多好多类似的代码了...此时,我们应该想起反射机制中的BeanUtils开发包..为了更好地重用,我就将它写成一个工具类!/*

* 将Parameter参数的数据封装到Bean中,为了外边不用强转,这里就使用泛型了!

*

* @request   由于要获取的是Parameter参数的信息,所以需要有request对象

* @tClass    本身是不知道封装什么对象的,所以用class

*

* */

public static T request2Bean(HttpServletRequest httpServletRequest, Class tClass) {

try {

//创建tClass的对象

T bean = tClass.newInstance();

//获取得到Parameter中全部的参数的名字

Enumeration enumeration = httpServletRequest.getParameterNames();

//遍历上边获取得到的集合

while (enumeration.hasMoreElements()) {

//获取得到每一个带过来参数的名字

String name = (String) enumeration.nextElement();

//获取得到值

String value = httpServletRequest.getParameter(name);

//把数据封装到Bean对象中

BeanUtils.setProperty(bean, name, value);

}

return bean;

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException("封装数据到Bean对象中出错了!");

}

}经过我们测试,日期不能直接封装到Bean对象中,会直接报出异常!

d74584c490a5dca0da769beb768190e2.png对于日期而言,需要一个日期转换器。当BeanUtils的setProperty()方法检测到日期时,会自动调用日期转换器对日期进行转换,从而实现封装!

于是乎,就在上面的方法中添加以下一句代码//日期转换器

ConvertUtils.register(new DateLocaleConverter(), Date.class);还有一个问题,用户的id不是自己输入的,是由程序生成的。我们避免id的重复,就使用UUID生成用户的id吧!为了更好的重用,我们也把它封装成一个方法!/*生成ID*/

public static int makeId() {

return Integer.parseInt(UUID.randomUUID().toString());

}好的,我们来测试一下吧!以下是RegisterServlet的代码User user = WebUtils.request2Bean(request, User.class);

user.setId(WebUtils.makeId());

//调用service层的注册方法,实现注册

ServiceBussiness serviceBussiness = new UserServiceXML();

serviceBussiness.register(user);效果:

8910c9c0170b8df7ea6cc4f7fa98bb0a.png

上面的代码是不够完善的(没有校验用户输入的信息、注册成功或失败都没有给出提示..等等)下面,我们来校验用户输入的信息吧,如果用户输入的信息不合法,就直接跳转回注册的界面。

刚才我们是用BeanUtils把Parameter的信息全部直接封装到User对象中,但现在我想要验证用户提交表单的数据,也应该把表单的数据用一个对象保存着【面向对象的思想、封装、重用】

流程是这样子的:当用户提交表单数据的时候,就把表单数据封装到我们设计的表单对象上,调用表单对象的方法,验证数据是否合法!

好了,我们来开发一个表单的对象吧,最重要的是怎么填写validate()方法!!public class FormBean {

//表单提交过来的数据全都是String类型的,birthday也不例外!

private String username;

private String password;

private String password2;

private String email;

private String birthday;

/*用于判断表单提交过来的数据是否合法*/

public boolean validate() {

return false;

}

//......各种setter、getter方法

}以下是我定下的规则:

8f431a552a6cdfe7d44abc143ddfb866.png方法的代码如下:public boolean validate() {

//用户名不能为空,并且要是3-8的字符 abcdABcd

if (this.username == null || this.username.trim().equals("")) {

return false;

} else {

if (!this.username.matches("[a-zA-Z]{3,8}")) {

return false;

}

}

//密码不能为空,并且要是3-8的数字

if (this.password == null || this.password.trim().equals("")) {

return false;

} else {

if (!this.password.matches("\\d{3,8}")) {

return false;

}

}

//两次密码要一致

if (this.password2 != null && !this.password2.trim().equals("")) {

if (!this.password2.equals(this.password)) {

return false;

}

}

//邮箱可以为空,如果为空就必须合法

if (this.email != null && !this.email.trim().equals("")) {

if (!this.email.matches("\\w+@\\w+(\\.\\w+)+")) {

System.out.println("邮箱错误了!");

return false;

}

}

//日期可以为空,如果为空就必须合法

if (this.birthday != null && !this.birthday.trim().equals("")) {

try {

DateLocaleConverter dateLocaleConverter = new DateLocaleConverter();

dateLocaleConverter.convert(this.birthday);

} catch (Exception e) {

System.out.println("日期错误了!");

return false;

}

}

//如果上面都没有执行,那么就是合法的了,返回true

return true;

}处理表单数据的Servlet,代码是这样子的://将表单的数据封装到formBean中

FormBean formBean = WebUtils.request2Bean(request, FormBean.class);

//验证表单的数据是否合法,如果不合法就跳转回去注册的页面

if(formBean.validate()==false){

request.getRequestDispatcher("/WEB-INF/register.jsp").forward(request, response);

return;

}

try {

//将表单的数据封装到User对象中

User user = WebUtils.request2Bean(request, User.class);

user.setId(WebUtils.makeId());

//调用service层的注册方法,实现注册

ServiceBussiness serviceBussiness = new UserServiceXML();

serviceBussiness.register(user);

} catch (Exception e) {

e.printStackTrace();

}接下来我们测试一下吧!将所有的信息都按照规定的输入!

7eedb164647fef7a37483e1013db610f.png没有问题!已经将记录写到XML文件上了!

23166729aead957ddbf81d82d1e178cd.png但是,如果我没有输入日期呢?

99f5c7d421966f4dcd4aa8fa978f4915.png

它抛出了错误!原因也非常简单:表单数据提交给Servlet,Servlet将表单的数据(Parameter中的数据)用BeanUtils封装到User对象中,当封装到日期的时候,发现日期为null,无法转换成日期对象!

那我们现在要怎么解决呢?

首先我们要明确:因为我们在设定的时候,已经允许了email和birthday可以为空,那么在DAO层就应该有相应的逻辑判断email和birthday是否为空!if (user.getEmail() == null) {

newElement.addAttribute("email", "");

} else {

newElement.addAttribute("email", user.getEmail());

}

//如果不是空才格式化信息

if (user.getBirthday() != null) {

//日期返回的是指定格式的日期

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

String date = simpleDateFormat.format(user.getBirthday());

newElement.addAttribute("birthday", date);

} else {

newElement.addAttribute("birthday", "");

}

解决办法:Parameter中的数据如果是"",我就不把数据封装到User对象中,执行下一次循环!public static T request2Bean(HttpServletRequest httpServletRequest, Class tClass) {

try {

//创建tClass的对象

T bean = tClass.newInstance();

//获取得到Parameter中全部的参数的名字

Enumeration enumeration = httpServletRequest.getParameterNames();

//日期转换器

ConvertUtils.register(new DateLocaleConverter(), Date.class);

//遍历上边获取得到的集合

while (enumeration.hasMoreElements()) {

//获取得到每一个带过来参数的名字

String name = (String) enumeration.nextElement();

//获取得到值

String value = httpServletRequest.getParameter(name);

//如果Parameter中的数据为"",那么我就不封装到User对象里边去!执行下一次循环

if (value == "") {

continue;

} else {

//把数据封装到Bean对象中

BeanUtils.setProperty(bean, name, value);

}

}

return bean;

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException("封装数据到Bean对象中出错了!");

}

}效果:

e7ed9ff48a4ec787d85ab25efb214e04.png

a41520f04606b05dfdb3ea8e00c0fd08.png

将数据封装到User对象中还有另外一个办法:我们知道BeanUtils有个copyProperties()方法,可以将某个对象的成员数据拷贝到另外一个对象的成员变量数据上(前提是成员变量的名称相同!)我们FormBean对象的成员变量名称和User对象的成员变量的名称是一致的!并且,前面在验证的时候,我们已经把Parameter中带过来的数据封装到了FormBean对象中了,所以我们可以使用copyProperties()方法!

使用该方法时,值得注意的是:第一个参数是拷贝到哪一个对象上(也就是User对象),第二个参数是被拷贝的对象(也就是formbean对象),口诀:后拷前....不要搞混了!!!!!(我就是搞混了,弄了很久...)

857e4cf9d4a1219f4454cb6965a8b742.png处理表单的Servlet完整代码如下://将表单的数据封装到formBean中

FormBean formBean = WebUtils.request2Bean(request, FormBean.class);

//验证表单的数据是否合法,如果不合法就跳转回去注册的页面

if(formBean.validate()==false){

request.getRequestDispatcher("/WEB-INF/register.jsp").forward(request, response);

return;

}

try {

//这是第一种--------------------------

/*User user = new User();

user.setId(WebUtils.makeId());

BeanUtils.copyProperties(user,formBean);*/

//------------------------------------------

//这是第二种

User user1 = WebUtils.request2Bean(request,User.class);

user1.setId(WebUtils.makeId());

//-----------------------------------

//调用service层的注册方法,实现注册

ServiceBussiness serviceBussiness = new UserServiceXML();

serviceBussiness.register(user1);

} catch (Exception e) {

e.printStackTrace();

}

现在还有问题,如果我填写信息不合法,提交给服务器验证以后,服务器应该告诉用户哪个信息不合法,而不是直接把跳转回注册界面,把所有的信息全部清空,让用户重新填写!

ad12301b662159f8041403c4f07f88af.png

我们应该这样做:当发现用户输入的信息不合法时,把错误的信息记录下来,等到返回注册页面,就提示用户哪里出错了!在FormBean对象中添加一个HashMap集合(因为等会还要根据关键字把错误信息显示给用户!)

FormBean的全部代码如下://表单提交过来的数据全都是String类型的,birthday也不例外!

private String username;

private String password;

private String password2;

private String email;

private String birthday;

//记录错误的信息

private HashMap error = new HashMap<>();

/*用于判断表单提交过来的数据是否合法*/

public boolean validate() {

//用户名不能为空,并且要是3-8的字符 abcdABcd

if (this.username == null || this.username.trim().equals("")) {

error.put("username", "用户名不能为空,并且要是3-8的字符");

return false;

} else {

if (!this.username.matches("[a-zA-Z]{3,8}")) {

error.put("username", "用户名不能为空,并且要是3-8的字符");

return false;

}

}

//密码不能为空,并且要是3-8的数字

if (this.password == null || this.password.trim().equals("")) {

error.put("password", "密码不能为空,并且要是3-8的数字");

return false;

} else {

if (!this.password.matches("\\d{3,8}")) {

error.put("password", "密码不能为空,并且要是3-8的数字");

return false;

}

}

//两次密码要一致

if (this.password2 != null && !this.password2.trim().equals("")) {

if (!this.password2.equals(this.password)) {

error.put("password2", "两次密码要一致");

return false;

}

}

//邮箱可以为空,如果为空就必须合法

if (this.email != null && !this.email.trim().equals("")) {

if (!this.email.matches("\\w+@\\w+(\\.\\w+)+")) {

error.put("email", "邮箱不合法!");

return false;

}

}

//日期可以为空,如果为空就必须合法

if (this.birthday != null && !this.birthday.trim().equals("")) {

try {

DateLocaleConverter dateLocaleConverter = new DateLocaleConverter();

dateLocaleConverter.convert(this.birthday);

} catch (Exception e) {

error.put("birthday", "日期不合法!");

return false;

}

}

//如果上面都没有执行,那么就是合法的了,返回true

return true;

}

//.....各种的setter和getter在跳转到注册页面之前,把formbean对象存到request域中。在注册页面就可以把错误的信息取出来(使用EL表达式)!

处理表单的Servlet的部分代码//验证表单的数据是否合法,如果不合法就跳转回去注册的页面

if(formBean.validate()==false){

//在跳转之前,把formbean对象传递给注册页面

request.setAttribute("formbean", formBean);

request.getRequestDispatcher("/WEB-INF/register.jsp").forward(request, response);

return;

}在注册页面中,使用EL表达式把错误的信息写出来

a15ca4fdc1fb7e00c5f7d92d7d6e3a13.png测试:

bcd2e22c9c49a2bee1f4f87f6498c10c.png效果:

672efe6fc37dc7c23f71d7c47bb93dab.png

做到这里,还是有丢丢的问题,我们不应该把用户输入的数据全部清空的!你想想,如果用户注册需要输入多个信息,仅仅一个出错了,就把全部信息清空,要他重新填写,这样是不合理的!我们在各个的输入项中使用EL表达式回显数据就行了!

957a65a78b176d3d4410f108bc98ad41.png效果:

f4027d1749d3c84425c9c52620a819bb.png

还没有完善,细心的朋友可以发现,上面图的日期也是错误的,但是没一次性标记出来给用户!要改也十分简单:在验证的时候,不要先急着return false 用一个布尔型变量记住,最后返回布尔型的变量即可

98e2ab092a850447cbbda52b2c67916f.png

无论注册成功还是失败都需要给用户一个友好界面的!

06e7ee027ff457749c5f6802d7cbe542.png

5.2登陆界面

登陆和注册是类似的,我们按着注册的步骤来写就对了!

首先写一个提供登陆界面的Servlet//直接跳转到登陆界面

request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);写登陆界面这是登陆界面

用户名

密码写处理登陆表单的Servlet//获取提交过来的数据

String username = request.getParameter("username");

String password = request.getParameter("password");

//调用service层的方法,去查询数据库(XML)是否有该条记录

try {

ServiceBussiness serviceBussiness = new UserServiceXML();

User user = serviceBussiness.login(username, password);

if (user == null) {

request.setAttribute("message", "用户名或密码是错的");

} else {

request.setAttribute("message","登陆成功");

}

} catch (Exception e) {

e.printStackTrace();

request.setAttribute("message","登陆失败咯");

}

request.getRequestDispatcher("/message.jsp").forward(request, response);效果:

6940cde4fd73167ff9db2832c64014c1.png

5.3把注册和登陆都挂在首页上这是首页!

登陆

注册

25e13bbc5b51b37e45f5432e858e90cc.png

总结使用JSP+JavaBean开发一个简单计算器,是非常容易的,显示页面和请求都是交由JSP来做。没有什么新的知识点,用一些JSP行为就能完成了。

MVC模式开发使用Servlet来做处理请求,代码量略大,但层次清晰

使用BeanUtils开发组件可以将request请求的参数封装到JavaBean对象中,Date属性要另外处理

校验的功能也是使用一个JavaBean来完成,目的就是为了可重用性,职责分工。同时,我们可以在该JavaBean设置一个Map集合来保存错误的信息,以便在前台上展示错误信息。如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,可以关注微信公众号:Java3y

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506928.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络传输大端序_大端、小端与网络字节序

大端(Big-Endian)&#xff0c;小端(Little-Endian)以及网络字节序的概念在编程中经常会遇到&#xff0c;网络字节序(Network Byte Order)一般是指大端(Big-Endian&#xff0c;对大部分网络传输协议而言)传输&#xff0c;大端小端的概念是面向多字节数据类型的存储方式定义的&am…

poi的sax模式读取xls_POI SAX 如何修改大excel 文件内容-问答-阿里云开发者社区-阿里云...

I think POI is using too much memory! What can I do?This one comes up quite a lot, but often the reason isnt what you might initially think. So, the first thing to check is - whats the source of the problem? Your file? Your code? Your environment? Or …

cupload怎么保存图片_原生js的图片上传插件cupload

插件描述&#xff1a;支持图片预览、像素限制、大小限制、多图上传、更新模式下页面初始化加载图片更新时间&#xff1a;2020-09-25 00:23:49更新说明&#xff1a;添加 删除时&#xff0c;同时删除服务器图片的功能&#xff0c;文档提供php实例。添加参数Url参数更新 {ele: &q…

mysql 半同步_mysql 主从同步 与 半同步

mysql主从同步复制定义主从同步使得数据可以从一个数据库服务器复制到其他服务器上&#xff0c;在复制数据时&#xff0c;一个服务器充当主服务器(master)&#xff0c;其余的服务器充当从服务器(slave)。通过配置文件&#xff0c;可以指定复制所有的数据库&#xff0c;某个数据…

mysql内存数据库性能_Mysql内存表配置及性能测试

centos7 mysql数据库安装和配可以参考一下文章&#xff0c;基本照做就可以了(我选的方法二)&#xff1a;http://www.cnblogs.com/starof/p/4680083.html说到内存表&#xff0c;首先有两个概念简单区分下&#xff1a;1.临时表&#xff1b;2.内存表&#xff1b;临时表与内存表的区…

mysql字符集排序规则_MySQL原理 - 字符集与排序规则

任何计算机存储数据&#xff0c;都需要字符集&#xff0c;因为计算机存储的数据其实都是二进制编码&#xff0c;将一个个字符&#xff0c;映射到对应的二进制编码的这个映射就是字符编码(字符集)。这些字符如何排序呢&#xff1f;决定字符排序的规则就是排序规则。查看内置字符…

mysql服务器默认操作字符集,如何在mysql中找到默认服务器字符集?

Using MySQL on FreeBSD 8.2. How do I find out the default server character set? Is there some command I can run or file I can check?UPDATEActually I want to know how to find both the default server character set and the current server character set.解决方…

mysql异常修复_MySQL错误修复:Table xx is marked as crashed and last (automatic?) repair failed...

问题一 Table xx is marked as crashed and last (automatic?) repair failed有开发找到我&#xff0c;说数据库坏了&#xff0c;连不上数据库&#xff0c;看了下 MySQL 的错误日志&#xff0c;报错如下&#xff1a;Error: Table ./db_name/table_name is marked as crashed a…

mysql 改变表的类型吗_mysql中修改表类型所带来的问题探讨

对于MySQL数据库&#xff0c;如果你要使用事务以及行级锁就必须使用INNODB引擎。如果你要使用全文索引&#xff0c;那必须使用myisam,那如何修改修改MySQL的引擎为INNODB呢&#xff0c;下面介绍一个修改方法。对于MySQL数据库&#xff0c;如果你要使用事务以及行级锁就必须使用…

mysql 字符串 截取字母_MySQL字符串函数:字符串截取

MySQL 字符串截取函数&#xff1a;left(), right(), substring(), substring_index()。还有 mid(), substr()。其中&#xff0c;mid(), substr() 等价于 substring() 函数&#xff0c;substring() 的功能非常强大和灵活。1. 字符串截取&#xff1a;left(str, length)mysql> …

建立学生选课表 mysql 语句_学生选课数据库SQL语句45道练习题整理及mysql常用函数(20161019)...

学生选课数据库SQL语句45道练习题&#xff1a;一、 设有一数据库&#xff0c;包括四个表&#xff1a;学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。四个表的结构分别如表1-1的表(一)~表(四)所示&#xff0c;数据如表1-2的表(一)~表(四)…

java mysql jsp分页代码_JAVA/JSP学习系列之六(MySQL翻页例子)

JAVA/JSP学习系列之六(MySQL翻页例子)更新时间&#xff1a;2006年10月13日 00:00:00 作者&#xff1a;一、运行前准备下载了mysql的jdbc驱动(一个jar文件)并加载在CLASSPATH(方法见《JAVA/JSP学习系列之一(JDK安装) 》)(如果找不到&#xff0c;请从本站下载)建一个MySQL数据库…

mysql内置含糊_mySQL入门04 内置函数

【欢迎关注&#xff0c;点赞&#xff0c;收藏&#xff0c;私信交流】字符串函数查看字符的ascii码值ascii(str)&#xff0c;str是空串时返回0select ascii(a);查看ascii码值对应的字符char(数字)select char(97);拼接字符串concat(str1,str2...)select concat(12,34,ab);包含字…

mysql与citespace_CiteSpace与MySQL数据库的连接-科学网—博客.PDF

CiteSpace与MySQL数据库的连接-科学网—博客.PDFCiteSpace与MySQL数据库的连接1,2 3李杰 &#xff0c;陈超美1.上海海事大学海洋科学与工程学院2.上海海事大学科技情报研究所3. Drexel University- College of Computing and InformaticsCiteSpace科技文本挖掘及可视化知识分享…

gcn代码pytorch_GCN的简单实现(pytorch)

import torch import torch.nn as nn import torch.nn.functional as Fimport networkx as nxdef normalize(A , symmetricTrue):# A AIA A torch.eye(A.size(0))# 所有节点的度d A.sum(1)if symmetric:#D D^-1/2D torch.diag(torch.pow(d , -0.5))return D.mm(A).mm(D)e…

mysql的check语言_check在SQL语句中的意思是什么?

展开全部在SQL中 CHECK 的意思&#xff1a;约束CHECK 约束用于限制列中的值的范围。如果对单个列定义 CHECK 约束&#xff0c;那么32313133353236313431303231363533e58685e5aeb931333365646261该列只允许特定的值。如果对一个表定义 CHECK 约束&#xff0c;那么此约束会在特定…

当电压放大电路的开路增益和输出电阻固定后_放大器的设计基础

放大器是电子电路(尤其是模拟电路)中的主要构件之一&#xff0c;使用放大器&#xff0c;它们会提高信号电平。放大器是一个术语&#xff0c;用于描述增加输入信号强度的电路。放大器广泛用于从音频应用到射频应用的各个领域中。但是&#xff0c;对于所有放大器&#xff0c;无论…

mysql数据库 auto_increment_mysql数据库 auto_increment

MySQL内核月报 2014.09-MySQL 捉虫动态auto_increment背景&#xff1a;Innodb引擎使用B_tree结构保存表数据&#xff0c;这样就需要一个唯一键表示每一行记录(比如二级索引记录引用)。Innodb表定义中处理主键的逻辑是&#xff1a;1.如果表定义了主键&#xff0c;就使用主键唯一…

javascript 嵌入python_通过Python将区块链数据嵌入Javascript,这是正确的方法吗?

你说得对。此页面是使用JavaScript异步填充的,因此BeautifulSoup和类似的工具将无法看到您试图获取的特定内容。但是,如果您记录浏览器的网络流量,您可以看到一些(XHR)httpget请求被发送到restapi,restapi以JSON形式提供其结果。这个JSON恰好包含您要查找的信息。它实际上会向不…

linux 嵌入式 快照_Linux 系统之Systemd

标签&#xff1a;子贡问为仁。子曰&#xff1a;“工欲善其事&#xff0c;必先利其器。居是邦也&#xff0c;事其大夫之贤者&#xff0c;友其士之仁者。”——孔子(春秋)《论语卫灵公》【工欲善其事&#xff0c;必先利其器】掌握一门技术&#xff0c;知道其发展历程是非常重要的…